Upgrade To Latest Tentacle

Octopus.Script exported 2023-11-21 by REOScotte belongs to ‘Octopus’ category.

Upgrades a list of machines to the latest version of Tentacle. Machines can be targeted by Environment and/or Role or Machine Name.

This needs to be run directly on a worker or the octopus server itself.

Parameters

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

Octopus Url

UpdateTentacles.OctopusUrl = #{Octopus.Web.ServerUri}

Required

The url of the server where the upgrades will be performed.

e.g. https://octopus.server.com

API Key

UpdateTentacles.ApiKey =

Required

The api key of a user permitted to perform tentacle upgrades.

Space

UpdateTentacles.SpaceName = #{Octopus.Space.Name}

The space to use when targeting machines.

Environments

UpdateTentacles.EnvironmentNames = #{Octopus.Environment.Name}

A list of environments to be used for targeting machines. If no environments are specified, only Machines Names will be targeted.

Multiple environments can be specified, one per line.

Roles

UpdateTentacles.RoleNames =

A list of roles to filter the machines found in the specified Environments. Only machines that are members of a specified role will be targeted.

Multiple roles can be specified, one per line.

Machine Names

UpdateTentacles.MachineNames =

Additional machine names to upgrade. These will be added to the list after Environments and Roles have been processed.

Multiple machines can be specified, one per line.

What If

UpdateTentacles.WhatIf = False

This can be used to test the targeting parameters. When selected, a list of target machines will be listed, but no machines will be upgraded.

Wait

UpdateTentacles.Wait = True

Wait until the upgrade is finished.

Script body

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

# Define working variables
$OctopusUrl       = [string]$OctopusParameters['UpdateTentacles.OctopusUrl'].Trim()
$ApiKey           = [string]$OctopusParameters['UpdateTentacles.ApiKey'].Trim()
$SpaceName        = [string]$OctopusParameters['UpdateTentacles.SpaceName'].Trim()
$EnvironmentNames = [string[]]$OctopusParameters['UpdateTentacles.EnvironmentNames']
$RoleNames        = [string[]]$OctopusParameters['UpdateTentacles.RoleNames']
$MachineNames     = [string[]]$OctopusParameters['UpdateTentacles.MachineNames']
$WhatIf           = [bool]::Parse($OctopusParameters['UpdateTentacles.WhatIf'])
$Wait             = [bool]::Parse($OctopusParameters['UpdateTentacles.Wait'])

# Remove white space and blank lines.
if ($null -ne $EnvironmentNames) {
    $EnvironmentNames = $EnvironmentNames.Split("`n").Trim().Where({$_}) # Trim white space and blank lines.
}
if ($null -ne $RoleNames) {
    $RoleNames = $RoleNames.Split("`n").Trim().Where({$_}) # Trim white space and blank lines.
}
if ($null -ne $MachineNames) {
    $MachineNames = $MachineNames.Split("`n").Trim().Where({$_}) # Trim white space and blank lines.
}

[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
$ErrorActionPreference = "Stop"

$header = @{ "X-Octopus-ApiKey" = $ApiKey }

if ($null -eq $SpaceName) {
    $baseUri = "$OctopusUrl/api"
} else {
    $space = (Invoke-RestMethod -Method Get -Uri "$OctopusUrl/api/spaces/all" -Headers $header) | Where-Object { $_.Name -eq $SpaceName }

    if ($null -eq $space) {
        throw "Space Name $SpaceName does not exist."
    } else {
        Write-Verbose "Using Space $SpaceName."
    }

    $baseUri = "$OctopusUrl/api/$($space.Id)"
}

# Start with no machines
$allMachines = @()

# Add machines for each requested environment.
foreach ($environmentName in $EnvironmentNames) {
    $environment = (Invoke-RestMethod -Method Get -Uri "$baseUri/environments/all" -Headers $header) | Where-Object { $_.Name -eq $environmentName }

    if ($null -eq $environment) {
        throw "Environment $environmentName does not exist."
    } else {
        Write-Verbose "Adding machines from Environment $environmentName."
    }

    $allMachines += (Invoke-RestMethod -Method Get -Uri "$baseUri/environments/$($environment.Id)/machines?take=$([int32]::MaxValue)" -Headers $header).Items
}

# If roles are specifed, include only machines in the specicied roles. Otherwise don't filter.
if ($null -eq $RoleNames) {
    $roleFilteredMachines += $allMachines
} else {
    $roleFilteredMachines = @()
    foreach ($roleName in $RoleNames) {
        $roleFilteredMachines += $allMachines | Where-Object { $_.Roles -contains $roleName }
    }
}

# Add each specific machine requested.
$roleFilteredMachines += (Invoke-RestMethod -Method Get -Uri "$baseUri/machines/all" -Headers $header) | Where-Object { $_.Name -in $MachineNames }

# Create array of unique IDs to target.
$uniqueIDs = [array]($roleFilteredMachines.Id | Sort-Object -Unique)

if (-not $uniqueIDs) {
    Write-Highlight "No machines were targeted. Exiting..."
    exit
}

# Build json payload, targeting unique machine IDs.
$jsonPayload = @{
    Arguments = @{
        MachineIds = $uniqueIDs
    }
    Description = "Upgrade Tentacle version."
    Name = "Upgrade"
}

if ($WhatIf) {
    Write-Host "Upgrading tentacles on:"
    Write-Host $(($roleFilteredMachines.Name | Sort-Object -Unique) -join "`r")
} else {
    Write-Verbose "Upgrading tentacles on:"
    Write-Verbose $(($roleFilteredMachines.Name | Sort-Object -Unique) -join "`r")
    $task = Invoke-RestMethod -Method Post -Uri "$baseUri/tasks" -Headers $header -Body ($jsonPayload | ConvertTo-Json -Depth 10)
    Write-Highlight "$($task.Id) started. Progress can be monitored [here]($OctopusUrl$($task.Links.Web)?activeTab=taskLog)"
    
    if ($Wait) {
        do {
        	# Output the current state of the task every five seconds.
            $task = Invoke-RestMethod -Method Get -Uri "$baseUri/tasks/$($task.Id)" -Headers $header
            $task
            Start-Sleep -Seconds 5
        } while ($task.IsCompleted -eq $false)
    }
}

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": "349c64f5-c9bd-4b55-bff7-cc497a1f898e",
  "Name": "Upgrade To Latest Tentacle",
  "Description": "Upgrades a list of machines to the latest version of Tentacle. Machines can be targeted by Environment and/or Role or Machine Name.\n\nThis needs to be run directly on a worker or the octopus server itself.",
  "Version": 1,
  "ExportedAt": "2023-11-21T00:42:08.257Z",
  "ActionType": "Octopus.Script",
  "Author": "REOScotte",
  "Packages": [],
  "Parameters": [
    {
      "Id": "51ea8dde-8df6-4621-8c8a-f5cacf485c5e",
      "Name": "UpdateTentacles.OctopusUrl",
      "Label": "Octopus Url",
      "HelpText": "**Required**\n\nThe url of the server where the upgrades will be performed.\n\ne.g. `https://octopus.server.com`",
      "DefaultValue": "#{Octopus.Web.ServerUri}",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "b8d147e0-de55-488e-a69f-9b212fd99559",
      "Name": "UpdateTentacles.ApiKey",
      "Label": "API Key",
      "HelpText": "**Required**\n\nThe api key of a user permitted to perform tentacle upgrades.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "e0d7450e-01de-47b2-abd2-3b22aa12a295",
      "Name": "UpdateTentacles.SpaceName",
      "Label": "Space",
      "HelpText": "The space to use when targeting machines.",
      "DefaultValue": "#{Octopus.Space.Name}",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "fb2c3110-d597-4729-9c86-d6dc5314dfb7",
      "Name": "UpdateTentacles.EnvironmentNames",
      "Label": "Environments",
      "HelpText": "A list of environments to be used for targeting machines. If no environments are specified, only `Machines Names` will be targeted.\n\nMultiple environments can be specified, one per line.",
      "DefaultValue": "#{Octopus.Environment.Name}",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Id": "2ec7ff8e-6dd3-46a8-9ef6-5869d14b6a03",
      "Name": "UpdateTentacles.RoleNames",
      "Label": "Roles",
      "HelpText": "A list of roles to filter the machines found in the specified `Environments`. Only machines that are members of a specified role will be targeted.\n\nMultiple roles can be specified, one per line.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Id": "e68ee3f0-bf4b-47ce-bba2-9a2e50c80595",
      "Name": "UpdateTentacles.MachineNames",
      "Label": "Machine Names",
      "HelpText": "Additional machine names to upgrade. These will be added to the list after `Environments` and `Roles` have been processed.\n\nMultiple machines can be specified, one per line.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Id": "9e742501-e215-4217-8e32-a6fb5ac16b6d",
      "Name": "UpdateTentacles.WhatIf",
      "Label": "What If",
      "HelpText": "This can be used to test the targeting parameters. When selected, a list of target machines will be listed, but no machines will be upgraded.",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "8e3f8d65-c117-40b6-b654-93f8ab65776d",
      "Name": "UpdateTentacles.Wait",
      "Label": "Wait",
      "HelpText": "Wait until the upgrade is finished.",
      "DefaultValue": "True",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "# Define working variables\n$OctopusUrl       = [string]$OctopusParameters['UpdateTentacles.OctopusUrl'].Trim()\n$ApiKey           = [string]$OctopusParameters['UpdateTentacles.ApiKey'].Trim()\n$SpaceName        = [string]$OctopusParameters['UpdateTentacles.SpaceName'].Trim()\n$EnvironmentNames = [string[]]$OctopusParameters['UpdateTentacles.EnvironmentNames']\n$RoleNames        = [string[]]$OctopusParameters['UpdateTentacles.RoleNames']\n$MachineNames     = [string[]]$OctopusParameters['UpdateTentacles.MachineNames']\n$WhatIf           = [bool]::Parse($OctopusParameters['UpdateTentacles.WhatIf'])\n$Wait             = [bool]::Parse($OctopusParameters['UpdateTentacles.Wait'])\n\n# Remove white space and blank lines.\nif ($null -ne $EnvironmentNames) {\n    $EnvironmentNames = $EnvironmentNames.Split(\"`n\").Trim().Where({$_}) # Trim white space and blank lines.\n}\nif ($null -ne $RoleNames) {\n    $RoleNames = $RoleNames.Split(\"`n\").Trim().Where({$_}) # Trim white space and blank lines.\n}\nif ($null -ne $MachineNames) {\n    $MachineNames = $MachineNames.Split(\"`n\").Trim().Where({$_}) # Trim white space and blank lines.\n}\n\n[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12\n$ErrorActionPreference = \"Stop\"\n\n$header = @{ \"X-Octopus-ApiKey\" = $ApiKey }\n\nif ($null -eq $SpaceName) {\n    $baseUri = \"$OctopusUrl/api\"\n} else {\n    $space = (Invoke-RestMethod -Method Get -Uri \"$OctopusUrl/api/spaces/all\" -Headers $header) | Where-Object { $_.Name -eq $SpaceName }\n\n    if ($null -eq $space) {\n        throw \"Space Name $SpaceName does not exist.\"\n    } else {\n        Write-Verbose \"Using Space $SpaceName.\"\n    }\n\n    $baseUri = \"$OctopusUrl/api/$($space.Id)\"\n}\n\n# Start with no machines\n$allMachines = @()\n\n# Add machines for each requested environment.\nforeach ($environmentName in $EnvironmentNames) {\n    $environment = (Invoke-RestMethod -Method Get -Uri \"$baseUri/environments/all\" -Headers $header) | Where-Object { $_.Name -eq $environmentName }\n\n    if ($null -eq $environment) {\n        throw \"Environment $environmentName does not exist.\"\n    } else {\n        Write-Verbose \"Adding machines from Environment $environmentName.\"\n    }\n\n    $allMachines += (Invoke-RestMethod -Method Get -Uri \"$baseUri/environments/$($environment.Id)/machines?take=$([int32]::MaxValue)\" -Headers $header).Items\n}\n\n# If roles are specifed, include only machines in the specicied roles. Otherwise don't filter.\nif ($null -eq $RoleNames) {\n    $roleFilteredMachines += $allMachines\n} else {\n    $roleFilteredMachines = @()\n    foreach ($roleName in $RoleNames) {\n        $roleFilteredMachines += $allMachines | Where-Object { $_.Roles -contains $roleName }\n    }\n}\n\n# Add each specific machine requested.\n$roleFilteredMachines += (Invoke-RestMethod -Method Get -Uri \"$baseUri/machines/all\" -Headers $header) | Where-Object { $_.Name -in $MachineNames }\n\n# Create array of unique IDs to target.\n$uniqueIDs = [array]($roleFilteredMachines.Id | Sort-Object -Unique)\n\nif (-not $uniqueIDs) {\n    Write-Highlight \"No machines were targeted. Exiting...\"\n    exit\n}\n\n# Build json payload, targeting unique machine IDs.\n$jsonPayload = @{\n    Arguments = @{\n        MachineIds = $uniqueIDs\n    }\n    Description = \"Upgrade Tentacle version.\"\n    Name = \"Upgrade\"\n}\n\nif ($WhatIf) {\n    Write-Host \"Upgrading tentacles on:\"\n    Write-Host $(($roleFilteredMachines.Name | Sort-Object -Unique) -join \"`r\")\n} else {\n    Write-Verbose \"Upgrading tentacles on:\"\n    Write-Verbose $(($roleFilteredMachines.Name | Sort-Object -Unique) -join \"`r\")\n    $task = Invoke-RestMethod -Method Post -Uri \"$baseUri/tasks\" -Headers $header -Body ($jsonPayload | ConvertTo-Json -Depth 10)\n    Write-Highlight \"$($task.Id) started. Progress can be monitored [here]($OctopusUrl$($task.Links.Web)?activeTab=taskLog)\"\n    \n    if ($Wait) {\n        do {\n        \t# Output the current state of the task every five seconds.\n            $task = Invoke-RestMethod -Method Get -Uri \"$baseUri/tasks/$($task.Id)\" -Headers $header\n            $task\n            Start-Sleep -Seconds 5\n        } while ($task.IsCompleted -eq $false)\n    }\n}"
  },
  "Category": "Octopus",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/upgrade_to_latest_tentacle.json",
  "Website": "/step-templates/349c64f5-c9bd-4b55-bff7-cc497a1f898e",
  "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 Tuesday, November 21, 2023