OctopusEnviroment.psm1
#Install-Module PowershellOctopusClientPS Import-Module PowershellOctopusClientPS (Get-Module -ListAvailable PowershellOctopusClientPS).ModuleBase try { $octoclientpath = Join-Path -Path (Get-Module -ListAvailable PowershellOctopusClientPS).ModuleBase -ChildPath "lib\Octopus.Client.dll" $newtonsoftPath = Join-Path -Path (Get-Module -ListAvailable PowershellOctopusClientPS).ModuleBase -ChildPath "lib\Newtonsoft.Json.dll" Add-Type -Path $newtonsoftPath Add-Type -Path $octoclientpath } catch [System.Reflection.ReflectionTypeLoadException] { #system.attonations always throws #Write-Host "Message: $($_.Exception.Message)" #Write-Host "StackTrace: $($_.Exception.StackTrace)" #Write-Host "LoaderExceptions: $($_.Exception.LoaderExceptions)" } <# .SYNOPSIS return a setup client #> function LoadOctopusClientAndDependancies{ [OutputType([Octopus.Client.OctopusClient])] Param( [parameter(Mandatory=$true)][String]$url, [parameter(Mandatory=$true)][String]$apiKey ) $client = [Octopus.Client.OctopusClient]::new([Octopus.Client.OctopusServerEndpoint]::new($url, $apiKey)) $client } <# .SYNOPSIS Deletes an enviroment, project links are removed automatically #> function DeleteOctopusEnviroment { Param( [parameter(Mandatory=$true)] [String]$octopusURL, [parameter(Mandatory=$true)] [String]$octopusAPIKey, #Name of the enviroment to destroy. [parameter(Mandatory=$true)] [String]$enviromentName, #Octopus space to destroy enviroment in, if empty/null will add to all spaces. [parameter(Mandatory=$false)][String]$inSpace = '' ) $client = LoadOctopusClientAndDependancies -url $octopusURL -apiKey $octopusAPIKey $repository = $client.ForSystem() $spaces = $null if([string]::IsNullOrEmpty($inSpace)) { write-output "Space was empty removing Enviroment: $enviromentName from ALL spaces." $spaces = $repository.Spaces.GetAll() }else{ $spaces = $repository.Spaces.FindByName($inSpace) } $spaces | foreach { try { $currSpace = $repository.Spaces.FindByName($_.Name) $repositoryForSpace = $client.ForSpace($currSpace) $theEnviromentResource = $repositoryForSpace.Environments.FindByName($enviromentName) if(-not($theEnviromentResource -eq $null)) { ##remove lifecycles and phases $lCycles = $repositoryForSpace.Lifecycles.FindAll() if(-not($lCycles -eq $null)) { $lCycles | foreach{ $foundPhase = $_.Phases.FindIndex({$args[0].Name -eq $enviromentName}) if($foundPhase -gt -1){ $_.Phases.RemoveAt($foundPhase) | out-null if($_.Phases.Count -eq 0){ write-output "Deleting Lifecycle: $($_.Name)" $repositoryForSpace.Lifecycles.Delete($_) } else { write-output "Deleting Phase: $enviromentName from Lifecycle: $($_.Name)" $repositoryForSpace.Lifecycles.Modify($_) | out-null } } } } #detach/remove cloud regions $wpoolResource = $repositoryForSpace.WorkerPools.FindByName($enviromentName) if(-not($wpoolResource -eq $null)){ $machines = $repositoryForSpace.Machines.List(0,$null,$null,$null,$null,$null,$null,$null,[Octopus.Client.Model.CommunicationStyle]::None,$null,$null,$enviromentResource.Id) $machines.Items | foreach { $currMachine = $_ if(([Octopus.Client.Model.Endpoints.CloudRegionEndpointResource]$currMachine.Endpoint).DefaultWorkerPoolId -eq $wpoolResource.Id) { write-output "Deleting Machine: $($currMachine.Name)" $repositoryForSpace.Machines.Delete($currMachine) } } write-output "Deleting Worker Pool: $($wpoolResource.Name)" $repositoryForSpace.WorkerPools.Delete($wpoolResource) } write-output "Deleting Enviroment: $($theEnviromentResource.Name) from space $($currSpace.Name)" $repositoryForSpace.Environments.Delete($theEnviromentResource) } }catch { Write-Error "DeleteOctopusEnviroment -> $($_)" } } } <# .SYNOPSIS Creates a new enviroment in octopus and optionally creates a lifecycle for it and adds it to existing default lifecycle #> function CreateOctopusEnviroment { Param( [parameter(Mandatory=$true)][String] $octopusURL, [parameter(Mandatory=$true)][String] $octopusAPIKey, #Name of the enviroment to create. [parameter(Mandatory=$true)][String] $enviromentName, #Octopus space to add enviroment to, if empty/null will add to all spaces. [parameter(Mandatory=$false)][String]$inSpace = '', #Should a lifecycle be created that only contains this enviroment? [parameter(Mandatory=$false)][bool] $createStandaloneLifecycle = $false, #if a value is provided a stage for this enviroment will be created and inserted into the default lifecyle before the stage provided. [parameter(Mandatory=$false)][String]$addToDefaultLifecycleBeforeStage = '' ) $client = LoadOctopusClientAndDependancies -url $octopusURL -apiKey $octopusAPIKey $repository = $client.ForSystem() $spaces = $null if([string]::IsNullOrEmpty($inSpace) -eq $true) { write-output "Space was empty adding Enviroment: $enviromentName to ALL spaces." $spaces = $repository.Spaces.GetAll() }else{ $spaces = $repository.Spaces.FindByName($inSpace) } $spaces | foreach { $currSpace = $_ $repositoryForSpace = $client.ForSpace($currSpace) $createdEnviroment = $repositoryForSpace.Environments.CreateOrModify($enviromentName) $newEnviromentAsResouce = $repositoryForSpace.Environments.FindByName($createdEnviroment.Instance.Name) write-output "Added Enviroment $enviromentName to space $($currSpace.Name)" if($createStandaloneLifecycle -eq $true) { $newLifecycleResource = [Octopus.Client.Model.LifecycleResource]::new() $newLifecycleResource.Name = $enviromentName $releaseRetention = [Octopus.Client.Model.RetentionPeriod]::new(2,[Octopus.Client.Model.RetentionUnit]::Items) $newLifecycleResource.WithReleaseRetentionPolicy($releaseRetention).WithTentacleRetentionPolicy($releaseRetention) | Out-Null $standAlonePhase = $newLifecycleResource.AddOrUpdatePhase($enviromentName) $standAlonePhase.IsOptionalPhase = $false [Octopus.Client.Model.EnvironmentResource[]]$phaseEnviroments = @($newEnviromentAsResouce) $standAlonePhase.WithOptionalDeploymentTargets($phaseEnviroments) | Out-Null $repositoryForSpace.Lifecycles.Create($newLifecycleResource) | Out-Null write-output "Added lifecycle $enviromentName to space $($currSpace.Name)" } if(-not ([string]::IsNullOrEmpty($addToDefaultLifecycleBeforeStage))) { $lifecycle = $repositoryForSpace.Lifecycles.FindByName("Default Lifecycle") $phasesList = $lifecycle.Phases $newPhase = [Octopus.Client.Model.PhaseResource]::new() $newPhase.Name = $enviromentName $newPhase.IsOptionalPhase = $true $newPhase.WithOptionalDeploymentTargets($newEnviromentAsResouce) | Out-Null $phasesList.Insert($phasesList.FindIndex({$args[0].Name -eq $addToDefaultLifecycleBeforeStage}),$newPhase) | Out-Null $repositoryForSpace.Lifecycles.Modify($lifecycle) | Out-Null write-output "Added phase $enviromentName to the Default Lifecycle in space $($currSpace.Name)" } } } <# .SYNOPSIS Links an enviroment to projects and tenants #> function LinkProjectAndEnviromentAndTenant { Param( [parameter(Mandatory=$true)][String]$octopusURL, [parameter(Mandatory=$true)][String]$octopusAPIKey, #Name of the enviroment to linkup. [parameter(Mandatory=$true)][String]$enviromentName, #Octopus space to perform action in, if null will use all spaces. [parameter(Mandatory=$false)][String]$inSpace = '', #name of the project to link, if null will link all [parameter(Mandatory=$false)][String]$projectName = '', #name of the tenant to link, if null will link all [parameter(Mandatory=$false)][String]$tenantName = '', #tenant tags to lookup tenants to link, only used if tenantName is null [parameter(Mandatory=$false)][String]$tenantTag = '' ) if( -not ([string]::IsNullOrEmpty($tenantTag))){ if(-not([string]::IsNullOrEmpty($tenantName))){ Throw 'Please provide only a tenant tag or tenant name paramater, both were provided. Exiting!' } } if([string]::IsNullOrEmpty($tenantTag)){ if([string]::IsNullOrEmpty($tenantName)){ Throw 'Please provide a tenant tag or tenant name. Exiting!' } } $client = LoadOctopusClientAndDependancies -url $octopusURL -apiKey $octopusAPIKey $repository = $client.ForSystem() $spaces = $null $projects = $null $tenants = [System.Collections.Generic.List[Octopus.Client.Model.TenantResource]]::new() if([string]::IsNullOrEmpty($inSpace) -eq $true) { $spaces = $repository.Spaces.GetAll() }else{ $spaces = $repository.Spaces.FindByName($inSpace) } $spaces | foreach { $currSpace = $_ $repositoryForSpace = $client.ForSpace($currSpace) $envResource = $repositoryForSpace.Environments.FindByName($enviromentName) if(-not($envResource -eq $null)){ if([string]::IsNullOrEmpty($tenantName) -eq $true){ $tmpTenants = $repositoryForSpace.Tenants.GetAll() if([string]::IsNullOrEmpty($tenantTag) -eq $true){ $tenants = $tmpTenants }else { $tmpTenants | foreach { $currTmpTenant = $_ if($currTmpTenant.TenantTags.Contains($tenantTag) -eq $true) { $tenants.Add($currTmpTenant) } } } }else { $tenants = $repositoryForSpace.Tenants.FindByName($tenantName) } if([string]::IsNullOrEmpty($projectName) -eq $true){ $projects = $repositoryForSpace.Projects.GetAll() }else { $projects = $repositoryForSpace.Projects.FindByName($projectName) } $tenants | foreach { $currTenant = $_ $projects | foreach { $currProject = $_ if(-not($currProject.TenantedDeploymentMode -eq "Untenanted")) { if($currTenant.ProjectEnvironments.ContainsKey($currProject.Id) -eq $false){ write-output "Making a link from Tenant: $($currTenant.Name) to Project: $($currProject.Name) in Enviroment: $($envResource.Name)." $item = $currTenant.ProjectEnvironments.Add($currProject.Id,$envResource.Id) }else{ write-output "Adding Enviroment: $($envResource.Name) to existing $($currTenant.Name)/$($currProject.Name) link." $tenantProj = $currTenant.ProjectEnvironments[$currProject.Id] $tenantProj.Add($envResource.Id) | Out-Null } $repositoryForSpace.Tenants.Modify($currTenant) | Out-Null } } } } } } |