Classes/Providers/ParcelProvider.ps1
class ParcelProvider { [string] $Name = [string]::Empty [bool] $RunAsPowerShell = $false [string] $DefaultSource [ParcelArguments] $Arguments # base constructor ParcelProvider([string]$_name, [bool]$_runAsPowershell, [string]$_defaultSource) { if ([string]::IsNullOrWhiteSpace($_name)) { throw 'No name provided for Parcel provider' } $this.Name = $_Name $this.RunAsPowerShell = $_runAsPowershell $this.DefaultSource = $_defaultSource $this.Arguments = [ParcelArguments]::new($null) } # implemented base functions [ParcelStatus] InstallProvider([hashtable]$_context, [bool]$_dryRun) { # get the scriptblock and invoke it if (!$_dryRun) { Invoke-Command -ScriptBlock ($this.GetProviderInstallScriptBlock($_context)) -ErrorAction Stop | Out-Null } # changed return [ParcelStatus]::new('Changed') } [ParcelStatus] Install([ParcelPackage]$_package, [hashtable]$_context, [bool]$_dryRun) { # check if package is valid $status = $_package.TestPackage($_context) if ($null -ne $status) { return $status } # check if the provider is installed if (!$this.TestProviderInstalled($_context)) { throw "The $($this.Name) provider is not installed" } # do nothing if package is already installed if ($this.TestPackageInstalled($_package)) { return [ParcelStatus]::new('Skipped', 'Already installed') } # run any pre-install scripts $_package.Scripts.PreInstall($_dryRun) # attempt to install $output = [string]::Empty try { # get install script - adding args, version and source $_script = $this.GetPackageInstallScript($_package, $_context) $_script += " $($_package.Arguments.Install)" $_script += " $($this.Arguments.Install)" if ($_script -ilike '*@PARCEL_NO_VERSION*') { $_script = $_script -ireplace '\@PARCEL_NO_VERSION', '' } else { $_version = $this.GetVersionArgument($_package) if (![string]::IsNullOrWhiteSpace($_version) -and !$_script.Contains($_version)) { $_script += " $($_version)" } } if ($_script -ilike '*@PARCEL_NO_SOURCE*') { $_script = $_script -ireplace '\@PARCEL_NO_SOURCE', '' } else { $_source = $this.GetSourceArgument($_package) if (![string]::IsNullOrWhiteSpace($_source) -and !$_script.Contains($_source)) { $_script += " $($_source)" } } Write-Verbose $_script if (!$_dryRun) { if ($this.RunAsPowerShell) { $output = Invoke-ParcelPowershell -Command $_script } else { $output = Invoke-Expression -Command $_script -ErrorAction Stop } if (!$this.TestExitCode($LASTEXITCODE, $output, 'install')) { throw 'Failed to install package' } } } catch { $output | Out-Default throw $_.Exception } # run any pre-install scripts $_package.Scripts.PostInstall($_dryRun) # state we have changed something return [ParcelStatus]::new('Changed') } [ParcelStatus] Uninstall([ParcelPackage]$_package, [hashtable]$_context, [bool]$_dryRun) { # check if the provider is installed if (!$this.TestProviderInstalled($_context)) { throw "The $($this.Name) provider is not installed" } # check if package is valid $status = $_package.TestPackage($_context) if ($null -ne $status) { return $status } # do nothing if already uninstalled if ($this.TestPackageUninstalled($_package)) { return [ParcelStatus]::new('Skipped', 'Already uninstalled') } # run any pre-install scripts $_package.Scripts.PreUninstall($_dryRun) # attempt to uninstall $output = [string]::Empty try { # get uninstall script - adding args $_script = $this.GetPackageUninstallScript($_package, $_context) $_script += " $($_package.Arguments.Uninstall)" $_script += " $($this.Arguments.Uninstall)" Write-Verbose $_script if (!$_dryRun) { if ($this.RunAsPowerShell) { $output = Invoke-ParcelPowershell -Command $_script } else { $output = Invoke-Expression -Command $_script -ErrorAction Stop } if (!$this.TestExitCode($LASTEXITCODE, $output, 'uninstall')) { throw 'Failed to uninstall package' } } } catch { $output | Out-Default throw $_.Exception } # run any pre-install scripts $_package.Scripts.PostUninstall($_dryRun) # state we have changed something return [ParcelStatus]::new('Changed') } [void] SetPackageLatestVersion([ParcelPackage]$_package) { if (!$_package.IsLatest) { return } $_package.Version = $this.GetPackageLatestVersion($_package) } [string] GetPackageHeaderMessage([ParcelPackage]$_package) { $_latestFlag = [string]::Empty if ($_package.IsLatest) { $_latestFlag = ' <latest>' } $_version = [string]::Empty if (![string]::IsNullOrWhiteSpace($_package.Version) -and ($_package.Version -ine 'latest')) { $_version = "v$($_package.Version)" } if ([string]::IsNullOrWhiteSpace($_version)) { $_latestFlag = $_latestFlag.Trim() } return "$($_package.Name.ToUpperInvariant()) [$($_version)$($_latestFlag) - $($this.Name)]" } [bool] TestPackageUninstalled([ParcelPackage]$_package) { return (!$this.TestPackageInstalled($_package)) } [bool] TestExitCode([int]$_code, [string]$_output, [string]$_action) { return ($_code -ieq 0) } [void] SetCustomSources([hashtable]$_sources, [bool]$_dryRun) { # do nothing if there are no sources if ($null -eq $_sources) { return } # ensure we don't haave more than 1 source as default if (($_sources | Where-Object { $_.default } | Measure-Object).Count -gt 1) { throw "More than one custom source has been flagged as default for the $($this.Name) provider" } Write-ParcelHeader -Message "SOURCES [$($this.Name)]" # attempt to add each source, failing if there is no name/url foreach ($_source in $_sources) { Write-Host "- $($_source.name): $($_source.url)" $this.RemoveSource($_source, $_dryRun) $this.AddSource($_source, $_dryRun) } Write-Host ([string]::Empty) } [void] AddSource([hashtable]$_source, [bool]$_dryRun) { if ([string]::IsNullOrWhiteSpace($_source.name)) { throw "A $($this.Name) source has no name defined" } if ([string]::IsNullOrWhiteSpace($_source.url)) { throw "A $($this.Name) source ($($_source.name)) has no URL defined" } $output = [string]::Empty try { # get add source script $_script = $this.GetProviderAddSourceScript($_source.name, $_source.url) Write-Verbose $_script if (![string]::IsNullOrWhiteSpace($_script) -and !$_dryRun) { if ($this.RunAsPowerShell) { $output = Invoke-ParcelPowershell -Command $_script } else { $output = Invoke-Expression -Command $_script -ErrorAction Stop } if (!$this.TestExitCode($LASTEXITCODE, $output, 'source')) { throw 'Failed to add source' } } if ($_source.default) { $this.DefaultSource = $_source.name } } catch { $output | Out-Default throw $_.Exception } } [void] RemoveSource([hashtable]$_source, [bool]$_dryRun) { if ([string]::IsNullOrWhiteSpace($_source.name)) { throw "A $($this.Name) source has no name defined" } $output = [string]::Empty try { # get remove source script $_script = $this.GetProviderRemoveSourceScript($_source.name) Write-Verbose $_script if (![string]::IsNullOrWhiteSpace($_script) -and !$_dryRun) { if ($this.RunAsPowerShell) { $output = Invoke-ParcelPowershell -Command $_script } else { $output = Invoke-Expression -Command $_script -ErrorAction Stop } if (!$this.TestExitCode($LASTEXITCODE, $output, 'source')) { throw 'Failed to remove source' } } } catch { $output | Out-Default throw $_.Exception } } [void] SetArguments([object]$_args) { $this.Arguments = [ParcelArguments]::new($_args) } # unimplemented base functions [bool] TestProviderInstalled([hashtable]$_context) { return $true } [string] GetPackageLatestVersion([ParcelPackage]$_package) { return [string]::Empty } [string] GetVersionArgument([ParcelPackage]$_package) { return [string]::Empty } [string] GetSourceArgument([ParcelPackage]$_package) { return [string]::Empty } [scriptblock] GetProviderInstallScriptBlock([hashtable]$_context) { throw [System.NotImplementedException]::new("GetProviderInstallScriptBlock ($($this.Name))") } [string] GetPackageInstallScript([ParcelPackage]$_package, [hashtable]$_context) { throw [System.NotImplementedException]::new("GetPackageInstallScript ($($this.Name))") } [string] GetPackageUninstallScript([ParcelPackage]$_package, [hashtable]$_context) { throw [System.NotImplementedException]::new("GetPackageUninstallScript ($($this.Name))") } [bool] TestPackageInstalled([ParcelPackage]$_package) { throw [System.NotImplementedException]::new("TestPackageInstalled ($($this.Name))") } [string] GetProviderAddSourceScript([string]$_name, [string]$_url) { throw [System.NotImplementedException]::new("GetProviderAddSourceScript ($($this.Name))") } [string] GetProviderRemoveSourceScript([string]$_name, [string]$_url) { throw [System.NotImplementedException]::new("GetProviderRemoveSourceScript ($($this.Name))") } } |