classes.ps1


using namespace System.Collections.Generic

$ErrorActionPreference = "Stop"
$InformationPreference = "Continue"
#$VerbosePreference = "Continue"

Import-Module "Profile"



class Resource {
    [bool] Test() {
        throw "Abstract method"
        return $false
    }
    [void] Set() {
        throw "Abstract method"
    }
    [string] ToString() {
        throw "Abstract method"
        return ""
    }
    static [void] Run([resource[]]$resources) {
        foreach ($resource in $resources) {
            Write-Log $resource.Name {
                $pass = [bool](Write-Log "Test" {$resource.Test()})
                if (-not $pass) {
                    Write-Log "Set" {$resource.Set()}
                    $pass = [bool](Write-Log "Test" {$resource.Test()})
                    if (-not $pass) {
                        Write-Log "Failed"
                        throw "$($resource.Name) failed to install"
                    }
                }
            }
        }
    }
}





class Extension : Resource {

    static [string] $ConfigurationFileName = "Extensions.json"
    static [string] $Container = "C:\Extensions"
    static [PSCustomObject] $Configuration

    [ValidateNotNullOrEmpty()]
    [string] $Name
    [ValidateNotNullOrEmpty()]
    [string] $Path
    [ValidateNotNullOrEmpty()]
    [hashtable] $BaseParameters

    static Extension() {
        $fileName = [Extension]::ConfigurationFileName
        [Extension]::Configuration = Get-MergedConfig $fileName
    }

    Extension([string] $name) {
        $this.Name = $name
        $this.Path = [Extension]::Container + "\$name"
        $this.BaseParameters = @{
            Service       = $env:Service
            FlightingRing = $env:FlightingRing
            Region        = $env:Region
        }
        $this.BaseParameters[$this.Name] = [Extension]::Configuration.($this.Name)
    }

    [bool] Test() {
        $script = $this.Path + "\test.ps1"
        $params = $this.GetParameters($script)
        return &$script @params
    }

    [void] Set() {
        $script = $this.Path + "\set.ps1"
        $params = $this.GetParameters($script)
        &$script @params
    }

    [hashtable] GetParameters([string] $script) {
        $params = @{}
        $supportedParameters = (Get-Command $script).ScriptBlock.Ast.ParamBlock.Parameters.Name `
            | % {$_ -replace "\$"}
        $this.BaseParameters.Keys `
            | ? {$_ -in $supportedParameters} `
            | % {$params[$_] = $this.BaseParameters[$_]}
        return $params
    }

}