Octopus - Wait for Deployment Target registration

Octopus.Script exported 2020-09-03 by harrisonmeister belongs to ‘Octopus’ category.

This step will poll Octopus Deploy until it detects that the expected Deployment Target has been registered.

The goal being that a deployment will be paused until the expected Deployment Target is available (eg Transient Targets). On subsequent deploys, the Deployment Target would quickly be identified as registered, and the deployment would continue as expected.

With a couple of extra step templates you can:

  • Create a new EC2 Instance (AWS - Launch EC2 Instance)
  • Include the new Deployment Target in subsequent deployment steps (Health Check)

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Environment

odEnv =

The Environment you expect the Deployment Target to be registered in.

Expected Display Name

odName =

The Display Name of the expected Deployment Target. Note: Partial matches for the supplied Display Name is enabled (eg “Machine” would match a Target called “Machine01”)

Expected Role (Optional)

odRole =

The Role of the expected Deployment Target. Note: Partial matches for the supplied Role is enabled (eg “Database” would match a Target with the Role “Database01”)

Timeout

odTimeout = 600

The amount of time to wait for the expected Deployment Target to be registered. (aka the Timeout)

Octopus Deploy URL (Kind-of Optional)

odUrl =

The base URL of your Octopus Deploy installation. Note: If empty, this step will attempt to use the value contained in the Machine Environment Variable “OD_API_URL”

API Key (Kind-of Optional)

odApiKey =

An API Key with permissions access the Octopus Deploy API. Note: If empty, this step will attempt to use the value contained in the Machine Environment Variable “OD_API_KEY” Further Reading: https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key

Script body

Steps based on this template will execute the following PowerShell script.

# Running outside octopus
param(
    [string]$odEnv,
    [string]$odName,
    [string]$odRole,
    [int]$odTimeout,
    [string]$odUrl,
    [string]$odApiKey,
    [switch]$whatIf
) 

$ErrorActionPreference = "Stop" 

function Get-Param($Name, [switch]$Required, $Default) {
    $result = $null

    if ($OctopusParameters -ne $null) {
        $result = $OctopusParameters[$Name]
    }

    if ($result -eq $null) {
        $variable = Get-Variable $Name -EA SilentlyContinue   
        if ($variable -ne $null) {
            $result = $variable.Value
        }
    }

    if (!$result -or $result -eq $null) {
        if ($Default) {
            $result = $Default
        } elseif ($Required) {
            throw "Missing parameter value $Name"
        }
    }

    return $result
}

& {
    param(
        [string]$odEnv,
        [string]$odName,
        [string]$odRole,
        [int]$odTimeout,
        [string]$odUrl,
        [string]$odApiKey
    )

    # If Octopus Deploy's URL/API Key are not provided as params, attempt to retrieve them from Environment Variables
    if (!$odUrl) {
        if ([Environment]::GetEnvironmentVariable("OD_API_URL", "Machine")) {
            $odUrl = [Environment]::GetEnvironmentVariable("OD_API_URL", "Machine")
        }
    }
    
    if (!$odUrl) { throw "Octopus Deploy API URL was not available/provided." }

    if (!$odApiKey) {
        if ([Environment]::GetEnvironmentVariable("OD_API_KEY", "Machine")) {
            $odApiKey = [Environment]::GetEnvironmentVariable("OD_API_KEY", "Machine")
        }
    } 
    
    if (!$odApiKey) { throw "Octopus Deploy API key was not available/provided." }

    $header = @{ "X-Octopus-ApiKey" = $odApiKey }
    
    Write-Verbose "Checking API compatibility";
    $rootDocument = Invoke-WebRequest "$odUrl/api/" -Header $header -UseBasicParsing | ConvertFrom-Json;
    if($rootDocument.Links -ne $null -and $rootDocument.Links.Spaces -ne $null) {
      Write-Verbose "Spaces API found"
      $hasSpacesApi = $true;
    } else {
      Write-Verbose "Pre-spaces API found"
      $hasSpacesApi = $false;
    }
    
    if($hasSpacesApi) {
        $spaceId = $OctopusParameters['Octopus.Space.Id'];
        if([string]::IsNullOrWhiteSpace($spaceId)) {
            throw "This step needs to be run in a context that provides a value for the 'Octopus.Space.Id' system variable. In this case, we received a blank value, which isn't expected - please reach out to our support team at https://help.octopus.com if you encounter this error.";
        }
        $baseApiUrl = "/api/$spaceId" ;
    } else {
        $baseApiUrl = "/api" ;
    }    
    
    $environments = (Invoke-WebRequest "$odUrl$baseApiUrl/environments/all" -Headers $header -UseBasicParsing).content | ConvertFrom-Json
    $environment = $environments | Where-Object { $_.Name -contains $odEnv }
    if (@($environment).Count -eq 0) { throw "Could not find environment with the name '$odEnv'" }
    
    $timeout = new-timespan -Seconds $odTimeout
    $sw = [diagnostics.stopwatch]::StartNew()

    Write-Output ("------------------------------")
    Write-Output ("Checking the Deployment Target's registration status:")
    Write-Output ("------------------------------")

    while ($true)
    {
        if ($sw.elapsed -gt $timeout) { throw "Timed out waiting for the Deployment Target to register" }
        
        $machines = ((Invoke-WebRequest ($odUrl + $environment.Links.Self + "/machines") -Headers $header -UseBasicParsing).content | ConvertFrom-Json).items
        if ($odName) { $machines = $machines | Where-Object { $_.Name -like "*$odName*" } }
        if ($odRole) { $machines = $machines | Where-Object { $_.Roles -like "*$odRole*" } }
        if (@($machines).Count -gt 0) { break }

        Write-Output ("$(Get-Date) | Waiting for Deployment Target to register with the name '$odName' and role '$odRole'")

        Start-Sleep -Seconds 5
    }
    
    Write-Output ("$(Get-Date) | Deployment Target registered with the name '$odName' and role '$odRole'!")
 } `
 (Get-Param 'odEnv' -Required) `
 (Get-Param 'odName' -Required) `
 (Get-Param 'odRole') `
 (Get-Param 'odTimeout' -Required) `
 (Get-Param 'odUrl') `
 (Get-Param 'odApiKey')

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "dc573fd6-92be-46fa-aab1-861adcd37d82",
  "Name": "Octopus - Wait for Deployment Target registration",
  "Description": "This step will poll Octopus Deploy until it detects that the expected Deployment Target has been registered.\n\nThe goal being that a deployment will be paused until the expected Deployment Target is available (eg [Transient Targets](https://octopus.com/docs/infrastructure/environments/elastic-and-transient-environments/deploying-to-transient-targets)). On subsequent deploys, the Deployment Target would quickly be identified as registered, and the deployment would continue as expected.\n\nWith a couple of extra step templates you can:\n- Create a new EC2 Instance (_AWS - Launch EC2 Instance_)\n- Include the new Deployment Target in subsequent deployment steps (_Health Check_)",
  "Version": 3,
  "ExportedAt": "2020-09-03T08:23:42.851Z",
  "ActionType": "Octopus.Script",
  "Author": "harrisonmeister",
  "Packages": [],
  "Parameters": [
    {
      "Id": "46d497f7-f297-4329-a5a3-a32e32dfb85b",
      "Name": "odEnv",
      "Label": "Environment",
      "HelpText": "The Environment you expect the Deployment Target to be registered in.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      },
      "Links": {}
    },
    {
      "Id": "28e05635-b343-4a00-a42e-55f5244ddd47",
      "Name": "odName",
      "Label": "Expected Display Name",
      "HelpText": "The Display Name of the expected Deployment Target.\nNote: _Partial matches for the supplied Display Name is enabled (eg \"Machine\" would match a Target called \"Machine01\")_",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      },
      "Links": {}
    },
    {
      "Id": "2df65d31-6a0e-47cb-bcc3-7b5320a23aee",
      "Name": "odRole",
      "Label": "Expected Role (Optional)",
      "HelpText": "The Role of the expected Deployment Target.\nNote: _Partial matches for the supplied Role is enabled (eg \"Database\" would match a Target with the Role \"Database01\")_",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      },
      "Links": {}
    },
    {
      "Id": "ff029a44-af95-4580-95c1-889a06a83f4c",
      "Name": "odTimeout",
      "Label": "Timeout",
      "HelpText": "The amount of time to wait for the expected Deployment Target to be registered. (aka the Timeout)",
      "DefaultValue": "600",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      },
      "Links": {}
    },
    {
      "Id": "9fe91ebb-7521-4a91-9284-8398a8e9ad87",
      "Name": "odUrl",
      "Label": "Octopus Deploy URL (Kind-of Optional)",
      "HelpText": "The base URL of your Octopus Deploy installation.\nNote: If empty, this step will attempt to use the value contained in the Machine Environment Variable \"OD\\_API\\_URL\"",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      },
      "Links": {}
    },
    {
      "Id": "054a2fca-6f12-46b2-a2a3-32045a50ea6a",
      "Name": "odApiKey",
      "Label": "API Key (Kind-of Optional)",
      "HelpText": "An API Key with permissions access the Octopus Deploy API.\nNote: If empty, this step will attempt to use the value contained in the Machine Environment Variable \"OD\\_API\\_KEY\"\nFurther Reading:\nhttps://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      },
      "Links": {}
    }
  ],
  "Properties": {
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.ScriptBody": "# Running outside octopus\nparam(\n    [string]$odEnv,\n    [string]$odName,\n    [string]$odRole,\n    [int]$odTimeout,\n    [string]$odUrl,\n    [string]$odApiKey,\n    [switch]$whatIf\n) \n\n$ErrorActionPreference = \"Stop\" \n\nfunction Get-Param($Name, [switch]$Required, $Default) {\n    $result = $null\n\n    if ($OctopusParameters -ne $null) {\n        $result = $OctopusParameters[$Name]\n    }\n\n    if ($result -eq $null) {\n        $variable = Get-Variable $Name -EA SilentlyContinue   \n        if ($variable -ne $null) {\n            $result = $variable.Value\n        }\n    }\n\n    if (!$result -or $result -eq $null) {\n        if ($Default) {\n            $result = $Default\n        } elseif ($Required) {\n            throw \"Missing parameter value $Name\"\n        }\n    }\n\n    return $result\n}\n\n& {\n    param(\n        [string]$odEnv,\n        [string]$odName,\n        [string]$odRole,\n        [int]$odTimeout,\n        [string]$odUrl,\n        [string]$odApiKey\n    )\n\n    # If Octopus Deploy's URL/API Key are not provided as params, attempt to retrieve them from Environment Variables\n    if (!$odUrl) {\n        if ([Environment]::GetEnvironmentVariable(\"OD_API_URL\", \"Machine\")) {\n            $odUrl = [Environment]::GetEnvironmentVariable(\"OD_API_URL\", \"Machine\")\n        }\n    }\n    \n    if (!$odUrl) { throw \"Octopus Deploy API URL was not available/provided.\" }\n\n    if (!$odApiKey) {\n        if ([Environment]::GetEnvironmentVariable(\"OD_API_KEY\", \"Machine\")) {\n            $odApiKey = [Environment]::GetEnvironmentVariable(\"OD_API_KEY\", \"Machine\")\n        }\n    } \n    \n    if (!$odApiKey) { throw \"Octopus Deploy API key was not available/provided.\" }\n\n    $header = @{ \"X-Octopus-ApiKey\" = $odApiKey }\n    \n    Write-Verbose \"Checking API compatibility\";\n    $rootDocument = Invoke-WebRequest \"$odUrl/api/\" -Header $header -UseBasicParsing | ConvertFrom-Json;\n    if($rootDocument.Links -ne $null -and $rootDocument.Links.Spaces -ne $null) {\n      Write-Verbose \"Spaces API found\"\n      $hasSpacesApi = $true;\n    } else {\n      Write-Verbose \"Pre-spaces API found\"\n      $hasSpacesApi = $false;\n    }\n    \n    if($hasSpacesApi) {\n        $spaceId = $OctopusParameters['Octopus.Space.Id'];\n        if([string]::IsNullOrWhiteSpace($spaceId)) {\n            throw \"This step needs to be run in a context that provides a value for the 'Octopus.Space.Id' system variable. In this case, we received a blank value, which isn't expected - please reach out to our support team at https://help.octopus.com if you encounter this error.\";\n        }\n        $baseApiUrl = \"/api/$spaceId\" ;\n    } else {\n        $baseApiUrl = \"/api\" ;\n    }    \n    \n    $environments = (Invoke-WebRequest \"$odUrl$baseApiUrl/environments/all\" -Headers $header -UseBasicParsing).content | ConvertFrom-Json\n    $environment = $environments | Where-Object { $_.Name -contains $odEnv }\n    if (@($environment).Count -eq 0) { throw \"Could not find environment with the name '$odEnv'\" }\n    \n    $timeout = new-timespan -Seconds $odTimeout\n    $sw = [diagnostics.stopwatch]::StartNew()\n\n    Write-Output (\"------------------------------\")\n    Write-Output (\"Checking the Deployment Target's registration status:\")\n    Write-Output (\"------------------------------\")\n\n    while ($true)\n    {\n        if ($sw.elapsed -gt $timeout) { throw \"Timed out waiting for the Deployment Target to register\" }\n        \n        $machines = ((Invoke-WebRequest ($odUrl + $environment.Links.Self + \"/machines\") -Headers $header -UseBasicParsing).content | ConvertFrom-Json).items\n        if ($odName) { $machines = $machines | Where-Object { $_.Name -like \"*$odName*\" } }\n        if ($odRole) { $machines = $machines | Where-Object { $_.Roles -like \"*$odRole*\" } }\n        if (@($machines).Count -gt 0) { break }\n\n        Write-Output (\"$(Get-Date) | Waiting for Deployment Target to register with the name '$odName' and role '$odRole'\")\n\n        Start-Sleep -Seconds 5\n    }\n    \n    Write-Output (\"$(Get-Date) | Deployment Target registered with the name '$odName' and role '$odRole'!\")\n } `\n (Get-Param 'odEnv' -Required) `\n (Get-Param 'odName' -Required) `\n (Get-Param 'odRole') `\n (Get-Param 'odTimeout' -Required) `\n (Get-Param 'odUrl') `\n (Get-Param 'odApiKey')"
  },
  "Category": "Octopus",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/octopus-wait-for-deployment-target-registration.json",
  "Website": "/step-templates/dc573fd6-92be-46fa-aab1-861adcd37d82",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Thursday, September 3, 2020