Automate Manual Intervention Response

Octopus.Script exported 2021-10-01 by twerthi belongs to ‘Octopus’ category.

This template will search for deployments that have been paused due to Manual Intervention or Guided Failure and automate the response.

Parameters

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

Octopus Server Url

AutomateResponse.Octopus.Url = #{Octopus.Web.ServerUri}

The Url to your Octopus Server instance.

API Key

AutomateResponse.Api.Key =

API Key of the account you want to use for the automatic response.

Reason Notes

AutomateResponse.Reason.Notes =

This is the Notes input for manual intervention.

Manual Intervention Response Type

AutomateResponse.ManualIntervention =

Select the response type for the Manual Intervention. Click Default Value to reset to none

Guided Failure Response Type

AutomateResponse.GuidedFailure =

Select the automated response for a Guided Failure. Click Default Value to reset to none.

Script body

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

function Get-OctopusItems
{
 # Define parameters
    param(
        $OctopusUri,
        $ApiKey,
        $SkipCount = 0
    )

    # Define working variables
    $items = @()
    $skipQueryString = ""
    $headers = @{"X-Octopus-ApiKey"="$ApiKey"}

    # Check to see if there there is already a querystring
    if ($octopusUri.Contains("?"))
    {
        $skipQueryString = "&skip="
    }
    else
    {
        $skipQueryString = "?skip="
    }

    $skipQueryString += $SkipCount

    # Get intial set
    $resultSet = Invoke-RestMethod -Uri "$($OctopusUri)$skipQueryString" -Method GET -Headers $headers

    # Check to see if it returned an item collection
    if ($resultSet.Items)
    {
        # Store call results
        $items += $resultSet.Items

        # Check to see if resultset is bigger than page amount
        if (($resultSet.Items.Count -gt 0) -and ($resultSet.Items.Count -eq $resultSet.ItemsPerPage))
        {
            # Increment skip count
            $SkipCount += $resultSet.ItemsPerPage

            # Recurse
            $items += Get-OctopusItems -OctopusUri $OctopusUri -ApiKey $ApiKey -SkipCount $SkipCount
        }
    }
    else
    {
        return $resultSet
    }


    # Return results
    return ,$items
}

$automaticResponseOctopusUrl = $OctopusParameters['AutomateResponse.Octopus.Url']
$automaticResponseApiKey = $OctopusParameters['AutomateResponse.Api.Key']
$automaticResponseReasonNotes = $OctopusParameters['AutomateResponse.Reason.Notes']
$automaticResponseManualInterventionResponseType = $OctopusParameters['AutomateResponse.ManualIntervention']
$automaticResponseGuidedFailureResponseType = $OctopusParameters['AutomateResponse.GuidedFailure']
$header = @{ "X-Octopus-ApiKey" = $automaticResponseApiKey }

# Validate response type input
if (![string]::IsNullOrWhitespace($automaticResponseManualInterventionResponseType) -and ![string]::IsNullOrWhitespace($automaticResponseGuidedFailureResponseType))
{
	# Fail step
    Write-Error "Cannot have both a Manual Intervention and Guided Failure selections."
}

if ([string]::IsNullOrWhitespace($automaticResponseManualInterventionResponseType) -and [string]::IsNullOrWhitespace($automaticResponseGuidedFailureResponseType))
{
	# Fail step
    Write-Error "Please select either a Manual Intervention or Guidded Failure response type."
}

# Get space
$spaceId = $OctopusParameters['Octopus.Space.Id']

# Get project
$projectId = $OctopusParameters['Octopus.Project.Id']

# Get the environemtn
$environmentId = $OctopusParameters['Octopus.Environment.Id']

# Get currently executing deployments for project
Write-Host "Searching for executing deployments ..."
$executingDeployments = Get-OctopusItems -OctopusUri "$automaticResponseOctopusUrl/api/$($spaceId)/deployments?projects=$($projectId)&taskState=Executing&environments=$($environmentId)" -ApiKey $automaticResponseApiKey

# Check to see if anything was returned for the environment
if ($executingDeployments -is [array])
{
  # Loop through executing deployments
  foreach ($deployment in $executingDeployments)
  {
      # Get object for manual intervention
      Write-Host "Checking $($deployment.Id) for manual interventions ..."
      $manualIntervention = Get-OctopusItems -OctopusUri "$automaticResponseOctopusUrl/api/$($spaceId)/interruptions?regarding=$($deployment.Id)&pendingOnly=true" -ApiKey $automaticResponseApiKey

      # Check to see if a manual intervention was returned
      if ($null -ne $manualIntervention.Id)
      {
          # Take responsibility
          Write-Host "Auto taking resonsibility for manual intervention ..."
          Invoke-RestMethod -Method Put -Uri "$automaticResponseOctopusUrl/api/$($spaceId)/interruptions/$($manualIntervention.Id)/responsible" -Headers $header

          # Create response object
          $jsonBody = @{
              Notes = $automaticResponseReasonNotes
          }

          # Check to see if manual intervention is empty
          if (![string]::IsNullOrWhiteSpace($automaticResponseManualInterventionResponseType))
          {
              # Add the manual intervention type
              Write-Host "Submitting $automaticResponseManualInterventionResponseType as response ..."
              $jsonBody.Add("Result", $automaticResponseManualInterventionResponseType)
          }

          # Check to see if the guided failure is empty
          if (![string]::IsNullOrWhiteSpace($automaticResponseGuidedFailureResponseType))
          {
              # Add the guided failure response
              Write-Host "Submitting $automaticResponseGuidedFailureResponseType as response ..."
              $jsonBody.Add("Guidance", $automaticResponseGuidedFailureResponseType)
          }

          # Post to server
          Invoke-RestMethod -Method Post -Uri "$automaticResponseOctopusUrl/api/$($spaceId)/interruptions/$($manualIntervention.Id)/submit" -Body ($jsonBody | ConvertTo-Json -Depth 10) -Headers $header
      }
  }
}

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": "54f95528-aa1e-4c97-8c16-b2e0d737c43e",
  "Name": "Automate Manual Intervention Response",
  "Description": "This template will search for deployments that have been paused due to Manual Intervention or Guided Failure and automate the response.",
  "Version": 2,
  "ExportedAt": "2021-10-01T17:52:01.610Z",
  "ActionType": "Octopus.Script",
  "Author": "twerthi",
  "Packages": [],
  "Parameters": [
    {
      "Id": "f5961f82-66a5-4219-a15c-f4a9feb68904",
      "Name": "AutomateResponse.Octopus.Url",
      "Label": "Octopus Server Url",
      "HelpText": "The Url to your Octopus Server instance.",
      "DefaultValue": "#{Octopus.Web.ServerUri}",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "3752c78e-4df8-4261-bdff-906bed063b12",
      "Name": "AutomateResponse.Api.Key",
      "Label": "API Key",
      "HelpText": "API Key of the account you want to use for the automatic response.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "be44e98e-13a8-4f4e-9b51-99920dfcf763",
      "Name": "AutomateResponse.Reason.Notes",
      "Label": "Reason Notes",
      "HelpText": "This is the `Notes` input for manual intervention.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "1bfbcc18-7ed9-4fce-88d1-0b4ab76d2623",
      "Name": "AutomateResponse.ManualIntervention",
      "Label": "Manual Intervention Response Type",
      "HelpText": "Select the response type for the Manual Intervention.  Click Default Value to reset to none",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "Abort|Abort\nProceed|Proceed"
      }
    },
    {
      "Id": "30405062-6bb6-499f-85ef-78bd378684ba",
      "Name": "AutomateResponse.GuidedFailure",
      "Label": "Guided Failure Response Type",
      "HelpText": "Select the automated response for a Guided Failure.  Click Default Value to reset to none.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "Fail|Fail\nExclude|Exclude Machine From Deployment\nIgnore|Ignore\nRetry|Retry"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "function Get-OctopusItems\n{\n # Define parameters\n    param(\n        $OctopusUri,\n        $ApiKey,\n        $SkipCount = 0\n    )\n\n    # Define working variables\n    $items = @()\n    $skipQueryString = \"\"\n    $headers = @{\"X-Octopus-ApiKey\"=\"$ApiKey\"}\n\n    # Check to see if there there is already a querystring\n    if ($octopusUri.Contains(\"?\"))\n    {\n        $skipQueryString = \"&skip=\"\n    }\n    else\n    {\n        $skipQueryString = \"?skip=\"\n    }\n\n    $skipQueryString += $SkipCount\n\n    # Get intial set\n    $resultSet = Invoke-RestMethod -Uri \"$($OctopusUri)$skipQueryString\" -Method GET -Headers $headers\n\n    # Check to see if it returned an item collection\n    if ($resultSet.Items)\n    {\n        # Store call results\n        $items += $resultSet.Items\n\n        # Check to see if resultset is bigger than page amount\n        if (($resultSet.Items.Count -gt 0) -and ($resultSet.Items.Count -eq $resultSet.ItemsPerPage))\n        {\n            # Increment skip count\n            $SkipCount += $resultSet.ItemsPerPage\n\n            # Recurse\n            $items += Get-OctopusItems -OctopusUri $OctopusUri -ApiKey $ApiKey -SkipCount $SkipCount\n        }\n    }\n    else\n    {\n        return $resultSet\n    }\n\n\n    # Return results\n    return ,$items\n}\n\n$automaticResponseOctopusUrl = $OctopusParameters['AutomateResponse.Octopus.Url']\n$automaticResponseApiKey = $OctopusParameters['AutomateResponse.Api.Key']\n$automaticResponseReasonNotes = $OctopusParameters['AutomateResponse.Reason.Notes']\n$automaticResponseManualInterventionResponseType = $OctopusParameters['AutomateResponse.ManualIntervention']\n$automaticResponseGuidedFailureResponseType = $OctopusParameters['AutomateResponse.GuidedFailure']\n$header = @{ \"X-Octopus-ApiKey\" = $automaticResponseApiKey }\n\n# Validate response type input\nif (![string]::IsNullOrWhitespace($automaticResponseManualInterventionResponseType) -and ![string]::IsNullOrWhitespace($automaticResponseGuidedFailureResponseType))\n{\n\t# Fail step\n    Write-Error \"Cannot have both a Manual Intervention and Guided Failure selections.\"\n}\n\nif ([string]::IsNullOrWhitespace($automaticResponseManualInterventionResponseType) -and [string]::IsNullOrWhitespace($automaticResponseGuidedFailureResponseType))\n{\n\t# Fail step\n    Write-Error \"Please select either a Manual Intervention or Guidded Failure response type.\"\n}\n\n# Get space\n$spaceId = $OctopusParameters['Octopus.Space.Id']\n\n# Get project\n$projectId = $OctopusParameters['Octopus.Project.Id']\n\n# Get the environemtn\n$environmentId = $OctopusParameters['Octopus.Environment.Id']\n\n# Get currently executing deployments for project\nWrite-Host \"Searching for executing deployments ...\"\n$executingDeployments = Get-OctopusItems -OctopusUri \"$automaticResponseOctopusUrl/api/$($spaceId)/deployments?projects=$($projectId)&taskState=Executing&environments=$($environmentId)\" -ApiKey $automaticResponseApiKey\n\n# Check to see if anything was returned for the environment\nif ($executingDeployments -is [array])\n{\n  # Loop through executing deployments\n  foreach ($deployment in $executingDeployments)\n  {\n      # Get object for manual intervention\n      Write-Host \"Checking $($deployment.Id) for manual interventions ...\"\n      $manualIntervention = Get-OctopusItems -OctopusUri \"$automaticResponseOctopusUrl/api/$($spaceId)/interruptions?regarding=$($deployment.Id)&pendingOnly=true\" -ApiKey $automaticResponseApiKey\n\n      # Check to see if a manual intervention was returned\n      if ($null -ne $manualIntervention.Id)\n      {\n          # Take responsibility\n          Write-Host \"Auto taking resonsibility for manual intervention ...\"\n          Invoke-RestMethod -Method Put -Uri \"$automaticResponseOctopusUrl/api/$($spaceId)/interruptions/$($manualIntervention.Id)/responsible\" -Headers $header\n\n          # Create response object\n          $jsonBody = @{\n              Notes = $automaticResponseReasonNotes\n          }\n\n          # Check to see if manual intervention is empty\n          if (![string]::IsNullOrWhiteSpace($automaticResponseManualInterventionResponseType))\n          {\n              # Add the manual intervention type\n              Write-Host \"Submitting $automaticResponseManualInterventionResponseType as response ...\"\n              $jsonBody.Add(\"Result\", $automaticResponseManualInterventionResponseType)\n          }\n\n          # Check to see if the guided failure is empty\n          if (![string]::IsNullOrWhiteSpace($automaticResponseGuidedFailureResponseType))\n          {\n              # Add the guided failure response\n              Write-Host \"Submitting $automaticResponseGuidedFailureResponseType as response ...\"\n              $jsonBody.Add(\"Guidance\", $automaticResponseGuidedFailureResponseType)\n          }\n\n          # Post to server\n          Invoke-RestMethod -Method Post -Uri \"$automaticResponseOctopusUrl/api/$($spaceId)/interruptions/$($manualIntervention.Id)/submit\" -Body ($jsonBody | ConvertTo-Json -Depth 10) -Headers $header\n      }\n  }\n}"
  },
  "Category": "Octopus",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/automate-manual-intervention-response.json",
  "Website": "/step-templates/54f95528-aa1e-4c97-8c16-b2e0d737c43e",
  "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 Friday, October 1, 2021