PipelinesAzureAgent.psm1
[DscResource()] class PipelinesAzureAgent { [DscProperty(Key)] [String] $Name [DscProperty(Mandatory)] [String] $DevOpsInstanceURL [DscProperty(Mandatory)] [String] $DevOpsInstanceName [DscProperty(Mandatory)] [String] $PoolName [DscProperty()] [String] $AgentRootPath = 'C:\' [DscProperty()] [String] $CertificateBundlePath [DscProperty(Mandatory)] [String] $Authentication [DscProperty()] [PSCredential] $Token [DscProperty()] [String] $AgentDownloadUrl [PipelinesAzureAgent] Get() { $result = [PipelinesAzureAgent]::new() Write-Verbose "Getting list of existing agents." $agents = Get-CimInstance -ClassName win32_Service -Filter "Name LIKE 'vstsagent.%'" Write-Verbose "Found $($agents.Name -join ',')" $thisOne = $agents | Where-Object { $parts = $_.Name -split '\.' # Windows service name is 'vstsagent.[devops instance name].[agent name] return $parts[1] -eq $DevOpsInstanceName -and $parts[2] -eq $Name } if($thisOne) { Write-Verbose 'Found this agent' Write-Verbose 'Getting agent config data' $base = Split-Path $thisOne.PathName.Replace('"','') -Parent $parent = Split-Path $base -Parent $agentConfigPath = Join-Path $parent '.agent' $config = ConvertFrom-Json (Get-Content -Path $agentConfigPath | Out-String) $result.DevOpsInstanceURL = $config.serverUrl $result.Name = $config.agentName } return $result } [bool] Test() { $state = $this.Get() return $state.Name -eq $this.Name } [void] Set() { $agentZipPath = (Join-Path $ENV:TEMP ([System.GUID]::NewGuid().Guid)) + '.zip' [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 Write-Verbose 'Downloading agent' Invoke-WebRequest $this.AgentDownloadUrl -OutFile $agentZipPath Write-Verbose 'Extracting agent' $agentPath = Join-Path $this.AgentRootPath $this.Name Expand-Archive -LiteralPath $agentZipPath -DestinationPath $agentPath -Force Remove-Item $agentZipPath -Force Write-Verbose 'Configuring agent' $cmdArgs = @( '--sslcacert', $this.CertificateBundlePath, '--url', $this.DevOpsInstanceURL, '--pool', "`"$($this.PoolName)`"", '--replace', '--agent', $this.Name, '--auth', $this.Authentication, '--runAsService', '--unattended' ) $cmdArgs | ConvertTo-Json | Out-String | Write-Verbose $cmdArgs += '--token', $this.Token.GetNetworkCredential().Password # Exclude sensitive data from logs. $cmdArgs += '2>&1' # Redirect the errors to the standard output for capturing and logging. $outputLogPath = (Join-Path $ENV:TEMP ([System.GUID]::NewGuid().Guid)) + '.txt' Start-Process -FilePath $AgentPath/config.cmd -ArgumentList $cmdArgs -Wait -NoNewWindow -RedirectStandardOutput $outputLogPath Get-Content -Path $outputLogPath | Write-Verbose Remove-Item $outputLogPath } } |