DSCResources/OctopusProjects/OctopusProjects.psm1
function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey, [parameter(Mandatory = $true)] [System.String] $ProjectTR, [parameter(Mandatory = $true)] [System.String] $ProjectEnv ) #Write-Verbose "Use this cmdlet to deliver information about command processing." #Write-Debug "Use this cmdlet to write debug information while troubleshooting." <# $returnValue = @{ OctopusURL = [System.String] OctopusAPIKey = [System.String] ProjectTR = [System.String] ProjectEnv = [System.String] } $returnValue #> } function Set-TargetResource { [CmdletBinding()] param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey, [parameter(Mandatory = $true)] [System.String] $ProjectTR, [parameter(Mandatory = $true)] [System.String] $ProjectEnv ) #Write-Verbose "Use this cmdlet to deliver information about command processing." #Write-Debug "Use this cmdlet to write debug information while troubleshooting." #Include this line if the resource requires a system reboot. #$global:DSCMachineStatus = 1 Begin { $IISExistingWebSites = Get-Website | Select-Object -ExpandProperty name New-Alias -Name Octo -Value "C:\Temp\OctopusTools\Octo.exe" -Force $ProjectsList = Get-OctopusProjectsIISWebSiteNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv | Select-Object -ExpandProperty Octopus.Action.IISWebSite.WebSiteName $IISProjectID = Get-IISWebSiteNamesandProjects -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv $ProjectIDIISnames= Get-ProjectIDandNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey } Process { $websites = @() foreach ($website in $IISExistingWebSites) { if ($website -ne "Default Web Site"){ $websites += $website } } #### Finds out the missing projects### Write-Verbose "Comparing project list" -Verbose $ProjectsMissing = Compare-Object $ProjectsList $websites | Where SideIndicator -EQ "<=" | Select-Object -ExpandProperty InputObject If ($ProjectsMissing -gt 0) { Write-Verbose "Setting Up the following Projects: $ProjectsMissing" -Verbose foreach ($OctopusProject in $ProjectsMissing) { Write-Verbose "creating Missing project ID and Missing Project Names" -Verbose $MissingProjectID = $IISProjectID.get_item($OctopusProject) $MissingProjectName = $ProjectIDIISnames.get_item($MissingProjectID) Write-Verbose "Starting to deploy projects" -Verbose $OctoAlias = Get-Alias octo |Select-Object -ExpandProperty Definition Write-Verbose "Set location to C:\Temp\OctopusTools\" -Verbose Push-Location "C:\Temp\OctopusTools\" Invoke-AndAssert { & .\Octo.exe deploy-release --project $MissingProjectName --version=latest --deployto $ProjectEnv --specificmachines=$env:computername --server $OctopusURL --apiKey $OctopusAPIKey} } } Else {Write-Verbose -Message 'Nothing to deploy' -Verbose} } End { Start-Sleep -Seconds 5 $IISWebsites = Get-Website | Select-Object -ExpandProperty name Write-Verbose "Websites/Projects running on this node: $IISWebsites " } } function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey, [parameter(Mandatory = $true)] [System.String] $ProjectTR, [parameter(Mandatory = $true)] [System.String] $ProjectEnv ) #Write-Verbose "Use this cmdlet to deliver information about command processing." #Write-Debug "Use this cmdlet to write debug information while troubleshooting." <# $result = [System.Boolean] $result #> Write-Verbose -Message 'Testing if octo.exe exist' If (!(Test-Path -Path "C:\Temp\OctopusTools\Octo.exe")) { Write-Verbose -Message 'Octo.exe tool does not exist' -Verbose Write-Verbose "Downloading latest Octopus Tools from $CommandLineToolsURL to $CommandLineToolsPath" Get-OctopusCommandLineTools $CommandLineToolsURL $CommandLineToolsPath } Else { Write-Verbose 'Octo.exe exists'} $IISExistingWebSites = Get-Website | Select-Object -ExpandProperty name New-Alias -Name Octo -Value "C:\Temp\OctopusTools\Octo.exe" -Force $ProjectsList = Get-OctopusProjectsIISWebSiteNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv | Select-Object -ExpandProperty Octopus.Action.IISWebSite.WebSiteName $IISProjectID = Get-IISWebSiteNamesandProjects -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv $ProjectIDIISnames= Get-ProjectIDandNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey $websites = @() foreach ($website in $IISExistingWebSites) { if ($website -ne "Default Web Site"){ $websites += $website } } #### Finds out the missing projects### Write-Verbose "Comparing project list 2" -Verbose $ProjectsMissing = Compare-Object $ProjectsList $websites | Where SideIndicator -EQ "<=" | Select-Object -ExpandProperty InputObject Write-Verbose -Message "projects missing $ProjectsMissing" Write-Verbose -Message 'tested if something missing01' If ($ProjectsMissing -gt 0) {return $false} else {Write-Verbose -Message 'Node has all necesary projects running. Nothing to deploy' return $true} Write-Verbose -Message 'tested if something missing' } function Get-EnvironmentID { [CmdletBinding()] [Alias()] [OutputType([Hashtable])] Param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey ) Write-Verbose -Message 'Building environment name and environment ID hash table' -Verbose $Environments = Invoke-RestMethod $OctopusURL/api/environments -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select -ExpandProperty Items $Environments | Select-Object Name, ID | % { $EnvironmentHashTable = @{} } { $EnvironmentHashTable[$_.Name] = $_.ID} return $EnvironmentHashTable } #Get-EnvironmentID -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey #$EnvironmentID.get_item("PROD") function Get-EnvironmentTarget { [CmdletBinding()] [Alias()] [OutputType([Hashtable])] Param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey ) Write-Verbose -Message 'Building environment name and Project ID target roles hash table' -Verbose Write-verbose "Retrieving projects" $Projects = Invoke-RestMethod $OctopusURL/api/projects -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select -ExpandProperty Items Write-verbose "Building deployment process API list" $DeploymentProcesses=$Projects.links.DeploymentProcess #Write-Host "Building project ID and target roles hash table" foreach ($Processes in $DeploymentProcesses) { $ProjectNameTargetHash = @{} $ProjectID = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Processes" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }) | select -expand ProjectID $ProjectTargetRole = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Processes" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }).Steps.Properties | select -expand Octopus.Action.TargetRoles -First 1 $ProjectNameTargetHash.Add($ProjectID, $ProjectTargetRole) $ProjectTargerHash += $ProjectNameTargetHash } # Project ID targer Hash tabale return $ProjectTargerHash } #Get-EnvironmentTarget -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey function Get-ProjectIDEnvironment { [CmdletBinding()] [Alias()] [OutputType([Hashtable])] Param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey ) Write-Verbose -Message 'Building project ID and environment ID hash table' -Verbose $Projects = Invoke-RestMethod $OctopusURL/api/projects -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select -ExpandProperty Items $DeploymentProcesses=$Projects.links.DeploymentProcess foreach ($Processes in $DeploymentProcesses) { $ProjectNameEnvironmentsHash = @{} $ProjectID = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Processes" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }) | select -expand ProjectID $ProjectEnvironment = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Processes" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }).Steps.Actions.Environments | sort -Unique $ProjectNameEnvironmentsHash.Add($ProjectID, $ProjectEnvironment) $ProjectEnvironmentHash += $ProjectNameEnvironmentsHash } return $ProjectEnvironmentHash } #Get-ProjectIDEnvironment -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey function Get-OctopusProjectsIISWebSiteNames { Param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey, [parameter(Mandatory = $true)] [System.String] $ProjectTR, [parameter(Mandatory = $true)] [System.String] $ProjectEnv ) $EnvironmentID = Get-EnvironmentID -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey $EnvironmentTarget = Get-EnvironmentTarget -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey $ProjectIDEnvironment = Get-ProjectIDEnvironment -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey $Projects = Invoke-RestMethod $OctopusURL/api/projects -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select -ExpandProperty Items $DeploymentProcesses=$Projects.links.DeploymentProcess foreach ($Processes in $DeploymentProcesses) { $ProjectID = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Processes" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }) | select -expand ProjectID $Projects = Invoke-RestMethod $OctopusURL/api/projects -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select -ExpandProperty Items $DeploymentProcesses=$Projects.links.DeploymentProcess If ($ProjectIDEnvironment.Item($ProjectID) -contains $EnvironmentID.Item($ProjectEnv) -and $EnvironmentTarget.Item($ProjectID) -contains $ProjectTR ) { (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Processes" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }).Steps.Actions.Properties | select Octopus.Action.IISWebSite.WebSiteName } #else {write-host "$IISWebSiteName will be skipped"} } } #Get-OctopusProjectsIISWebSiteNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv function Get-IISWebSiteNamesandProjects { [CmdletBinding()] [Alias()] [OutputType([int])] Param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey, [parameter(Mandatory = $true)] [System.String] $ProjectTR, [parameter(Mandatory = $true)] [System.String] $ProjectEnv ) Begin { $EnvironmentIDHash = Get-EnvironmentID -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey } Process { $Projects = Invoke-RestMethod $OctopusURL/api/projects/all -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } $ProjectList=$Projects.name $DeploymentProcesses = $Projects.links.DeploymentProcess Write-Verbose 'starting foreach loop'-Verbose foreach ($Process in $DeploymentProcesses){ $Steps=Invoke-RestMethod $OctopusURL/$Process -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select-Object -ExpandProperty Steps $StepRole = $steps.properties | Select-Object -ExpandProperty Octopus.Action.TargetRoles | Select-Object -First 1 -Verbose $Actions=Invoke-RestMethod $OctopusURL/$Process -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select-Object -ExpandProperty Steps $Environments = $Actions.actions.environments | Sort-Object -Unique Write-Verbose 'foreach loop before if statement' if ($Environments -contains $EnvironmentIDHash.get_item($ProjectEnv) -and $StepRole -contains $ProjectTR ) { $table = @{} Write-Verbose 'running if statement' $IISName = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Process" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }).Steps.Actions.Properties | select Octopus.Action.IISWebSite.WebSiteName $WebSiteName = $IISName | Select-Object -ExpandProperty Octopus.Action.IISWebSite.WebSiteName #Write-Output $WebSiteName $ProjectID = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Process" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }).ProjectID #Write-Output $ProjectID $table.add($WebSiteName, $ProjectID) $Table01 += $table Continue } else { Write-Verbose 'Failed' -Verbose } # $Table01 | Write-Output #return $Table01 } return $Table01 } } #Get-IISWebSiteNamesandProjects -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv function Get-ProjectIDandNames { [CmdletBinding()] [Alias()] [OutputType([Hashtable])] Param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey ) Write-Verbose -Message 'Building project ID and Project name hash table' -Verbose $Projects = Invoke-RestMethod $OctopusURL/api/projects -Headers @{ "X-Octopus-ApiKey" = $OctopusAPIKey } | Select -ExpandProperty Items $SelfProjects=$Projects.links.self foreach ($Self in $SelfProjects) { $ProjectIDNameHash = @{} $ProjectID = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Self" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }) | select -expand ID $ProjectName = (Invoke-RestMethod -Method Get -Uri "$OctopusURL/$Self" -Header @{ "X-Octopus-ApiKey" = $OctopusAPIKey }) | select -expand Name $ProjectIDNameHash.Add($ProjectID, $ProjectName) $ProjectIDNameHashTable += $ProjectIDNameHash } return $ProjectIDNameHashTable } #Get-ProjectIDandNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey function Set-OctopusProjects { [CmdletBinding()] [OutputType([int])] Param ( [parameter(Mandatory = $true)] [System.String] $OctopusURL, [parameter(Mandatory = $true)] [System.String] $OctopusAPIKey, [parameter(Mandatory = $true)] [System.String] $ProjectTR, [parameter(Mandatory = $true)] [System.String] $ProjectEnv ) Begin { $IISExistingWebSites = Get-Website | Select-Object -ExpandProperty name Set-Location "C:\Temp\OctopusTools\" $ProjectsList = Get-OctopusProjectsIISWebSiteNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv | Select-Object -ExpandProperty Octopus.Action.IISWebSite.WebSiteName $IISProjectID = Get-IISWebSiteNamesandProjects -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv $ProjectIDIISnames= Get-ProjectIDandNames -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey } Process { $websites = @() foreach ($website in $IISExistingWebSites) { if ($website -ne "Default Web Site"){ $websites += $website } } #### Finds out the missing projects### Write-Verbose "Comparing project list" -Verbose $ProjectsMissing = Compare-Object $ProjectsList $websites | Where SideIndicator -EQ "<=" | Select-Object -ExpandProperty InputObject If ($ProjectsMissing -gt 0) { Write-Verbose "Setting Up the following Projects: $ProjectsMissing" -Verbose foreach ($OctopusProject in $ProjectsMissing) { $MissingProjectID = $IISProjectID.get_item($OctopusProject) $MissingProjectName = $ProjectIDIISnames.get_item($MissingProjectID) Invoke-AndAssert { & .\Octo.exe deploy-release --project $MissingProjectName --version=latest --deployto $ProjectEnv --specificmachines=$env:computername --server $OctopusURL --apiKey $OctopusAPIKey} } $IISWebsites = Get-Website | Select-Object -ExpandProperty name Write-Verbose "Websites/Projects running on this node: $IISWebsites " } Else {Write-Verbose -Message 'Nothing to deploy' -Verbose} } End { } } #Set-OctopusProjects -OctopusURL $OctopusURL -OctopusAPIKey $OctopusAPIKey -ProjectTR $ProjectTR -ProjectEnv $ProjectEnv function Invoke-AndAssert { param ($block) & $block | Write-Verbose if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne $null) { throw "Command returned exit code $LASTEXITCODE" } } function Request-File { param ( [string]$url, [string]$saveAs ) Write-Verbose "Downloading $url to $saveAs" $downloader = new-object System.Net.WebClient $downloader.DownloadFile($url, $saveAs) } function Get-OctopusCommandLineTools { [CmdletBinding()] [Alias()] [OutputType([int])] Param ( # Param1 help description $Param1, # Param2 help description $Param2 ) Begin { $CommandLineToolsURL = "https://octopus.com/downloads/latest/CommandLineTools" $CommandLineToolsPath = "$($env:SystemDrive)\temp\OctopusTools.zip" $CommandLineToolsPathUnZipped = "$($env:SystemDrive)\Temp\OctopusTools\octo.exe" } Process { Write-Verbose "Beginning Tentacle installation" -Verbose mkdir "$env:SystemDrive\temp" -ErrorAction SilentlyContinue if (!(test-path $CommandLineToolsPath)) { Write-Verbose "Downloading latest Octopus Tentacle MSI from $CommandLineToolsURL to $CommandLineToolsPath" Request-File $CommandLineToolsURL $CommandLineToolsPath } if(!(Test-Path $CommandLineToolsPathUnZipped)){ Expand-Archive -Path $CommandLineToolsPath -DestinationPath "$env:SystemDrive\temp\OctopusTools" -Verbose} } } Export-ModuleMember -Function *-TargetResource |