Octopus - Lookup Space ID

Octopus.Script exported 09/11/2023 by mcasperson belongs to 'Octopus' category.

This step queries an Octopus server to return the ID of a named space. The ID is captured in an output variables called SpaceID.

Parameters

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

Server URL

SpaceLookup.ThisInstance.Server.Url = #{Octopus.Web.ServerUri}

The URL of the Octopus Server hosting the space to resolved.

Server API Key

SpaceLookup.ThisInstance.Api.Key

The Octopus API Key

Space Name

SpaceLookup.Lookup.Space.Name

The name of the space return the ID of

Script body

Steps based on this template will execute the following Python script.
Show script
# This script exists for those scenarios where the tenant space is created as part of the same process that
# attempts to populate the space. The tenant space ID variable, saved when the space is created, won't be refreshed
# in the middle of the deployment, so we query it directly.

import argparse
import json
import urllib.request
import urllib.parse
import os
import sys
import time

# If this script is not being run as part of an Octopus step, return variables from environment variables.
# Periods are replaced with underscores, and the variable name is converted to uppercase
if "get_octopusvariable" not in globals():
    def get_octopusvariable(variable):
        return os.environ[re.sub('\\.', '_', variable.upper())]

# If this script is not being run as part of an Octopus step, just print any set variable to std out.
if "set_octopusvariable" not in globals():
    def set_octopusvariable(name, variable):
        print(variable)


def get_octopusvariable_quiet(variable):
    """
    Gets an octopus variable, or an empty string if it does not exist.
    :param variable: The variable name
    :return: The variable value, or an empty string if the variable does not exist
    """
    try:
        return get_octopusvariable(variable)
    except:
        return ''


def init_argparse():
    parser = argparse.ArgumentParser(
        usage='%(prog)s [OPTION] [FILE]...',
        description='Lookup a space ID from the name'
    )
    parser.add_argument('--server-url',
                        action='store',
                        default=get_octopusvariable_quiet(
                            'SpaceLookup.ThisInstance.Server.Url') or get_octopusvariable_quiet(
                            'ThisInstance.Server.Url'),
                        help='Sets the Octopus server URL.')
    parser.add_argument('--api-key',
                        action='store',
                        default=get_octopusvariable_quiet(
                            'SpaceLookup.ThisInstance.Api.Key') or get_octopusvariable_quiet('ThisInstance.Api.Key'),
                        help='Sets the Octopus API key.')
    parser.add_argument('--space-name',
                        action='store',
                        default=get_octopusvariable_quiet('SpaceLookup.Lookup.Space.Name') or get_octopusvariable_quiet(
                            'Lookup.Space.Name') or get_octopusvariable_quiet('Octopus.Deployment.Tenant.Name'),
                        help='The name of the space to lookup.')

    return parser.parse_known_args()


parser, _ = init_argparse()

# Variable precondition checks
if len(parser.server_url) == 0:
    print("--server-url, ThisInstance.Server.Url, or SerializeProject.ThisInstance.Server.Url must be defined")
    sys.exit(1)

if len(parser.api_key) == 0:
    print("--api-key, ThisInstance.Api.Key, or ThisInstance.Api.Key must be defined")
    sys.exit(1)

if len(parser.space_name) == 0:
    print("--space-name, Lookup.Space.Name, SpaceLookup.Lookup.Space.Name, or Octopus.Deployment.Tenant.Name must be defined")
    sys.exit(1)

url = parser.server_url + '/api/Spaces?partialName=' + urllib.parse.quote(parser.space_name) + "&take=1000"
headers = {
    'X-Octopus-ApiKey': parser.api_key,
    'Accept': 'application/json'
}
request = urllib.request.Request(url, headers=headers)

# Retry the request for up to a minute.
response = None
for x in range(12):
    response = urllib.request.urlopen(request)
    if response.getcode() == 200:
        break
    time.sleep(5)

if not response or not response.getcode() == 200:
    print('The API query failed')
    sys.exit(1)

data = json.loads(response.read().decode("utf-8"))

space = [x for x in data['Items'] if x['Name'] == parser.space_name]

if len(space) != 0:
    print('Space ' + parser.space_name + ' has ID ' + space[0]['Id'])
    print('The space ID is available as the output variable #{Octopus.Action[' + get_octopusvariable_quiet('Octopus.Action.Name') + '].Output.SpaceID}')
    set_octopusvariable("SpaceID", space[0]['Id'])
else:
    print('Failed to find space called ' + parser.space_name)
    sys.exit(1)

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

Show JSON
{
  "Id": "324f747e-e2cd-439d-a660-774baf4991f2",
  "Name": "Octopus - Lookup Space ID",
  "Description": "This step queries an Octopus server to return the ID of a named space. The ID is captured in an output variables called `SpaceID`.",
  "Version": 2,
  "ExportedAt": "2023-09-11T21:15:03.881Z",
  "ActionType": "Octopus.Script",
  "Author": "mcasperson",
  "Packages": [],
  "Parameters": [
    {
      "Id": "69b98409-b4ba-401f-8986-042b6d58584f",
      "Name": "SpaceLookup.ThisInstance.Server.Url",
      "Label": "Server URL",
      "HelpText": "The URL of the Octopus Server hosting the space to resolved.",
      "DefaultValue": "#{Octopus.Web.ServerUri}",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "9089cd55-75d6-4e91-a390-d7a3359e3c59",
      "Name": "SpaceLookup.ThisInstance.Api.Key",
      "Label": "Server API Key",
      "HelpText": "The Octopus API Key",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "4f5d46a5-ea76-478f-a5fa-0bacad6afa5b",
      "Name": "SpaceLookup.Lookup.Space.Name",
      "Label": "Space Name",
      "HelpText": "The name of the space return the ID of",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.RunOnServer": "true",
    "Octopus.Action.Script.ScriptBody": "# This script exists for those scenarios where the tenant space is created as part of the same process that\n# attempts to populate the space. The tenant space ID variable, saved when the space is created, won't be refreshed\n# in the middle of the deployment, so we query it directly.\n\nimport argparse\nimport json\nimport urllib.request\nimport urllib.parse\nimport os\nimport sys\nimport time\n\n# If this script is not being run as part of an Octopus step, return variables from environment variables.\n# Periods are replaced with underscores, and the variable name is converted to uppercase\nif \"get_octopusvariable\" not in globals():\n    def get_octopusvariable(variable):\n        return os.environ[re.sub('\\\\.', '_', variable.upper())]\n\n# If this script is not being run as part of an Octopus step, just print any set variable to std out.\nif \"set_octopusvariable\" not in globals():\n    def set_octopusvariable(name, variable):\n        print(variable)\n\n\ndef get_octopusvariable_quiet(variable):\n    \"\"\"\n    Gets an octopus variable, or an empty string if it does not exist.\n    :param variable: The variable name\n    :return: The variable value, or an empty string if the variable does not exist\n    \"\"\"\n    try:\n        return get_octopusvariable(variable)\n    except:\n        return ''\n\n\ndef init_argparse():\n    parser = argparse.ArgumentParser(\n        usage='%(prog)s [OPTION] [FILE]...',\n        description='Lookup a space ID from the name'\n    )\n    parser.add_argument('--server-url',\n                        action='store',\n                        default=get_octopusvariable_quiet(\n                            'SpaceLookup.ThisInstance.Server.Url') or get_octopusvariable_quiet(\n                            'ThisInstance.Server.Url'),\n                        help='Sets the Octopus server URL.')\n    parser.add_argument('--api-key',\n                        action='store',\n                        default=get_octopusvariable_quiet(\n                            'SpaceLookup.ThisInstance.Api.Key') or get_octopusvariable_quiet('ThisInstance.Api.Key'),\n                        help='Sets the Octopus API key.')\n    parser.add_argument('--space-name',\n                        action='store',\n                        default=get_octopusvariable_quiet('SpaceLookup.Lookup.Space.Name') or get_octopusvariable_quiet(\n                            'Lookup.Space.Name') or get_octopusvariable_quiet('Octopus.Deployment.Tenant.Name'),\n                        help='The name of the space to lookup.')\n\n    return parser.parse_known_args()\n\n\nparser, _ = init_argparse()\n\n# Variable precondition checks\nif len(parser.server_url) == 0:\n    print(\"--server-url, ThisInstance.Server.Url, or SerializeProject.ThisInstance.Server.Url must be defined\")\n    sys.exit(1)\n\nif len(parser.api_key) == 0:\n    print(\"--api-key, ThisInstance.Api.Key, or ThisInstance.Api.Key must be defined\")\n    sys.exit(1)\n\nif len(parser.space_name) == 0:\n    print(\"--space-name, Lookup.Space.Name, SpaceLookup.Lookup.Space.Name, or Octopus.Deployment.Tenant.Name must be defined\")\n    sys.exit(1)\n\nurl = parser.server_url + '/api/Spaces?partialName=' + urllib.parse.quote(parser.space_name) + \"&take=1000\"\nheaders = {\n    'X-Octopus-ApiKey': parser.api_key,\n    'Accept': 'application/json'\n}\nrequest = urllib.request.Request(url, headers=headers)\n\n# Retry the request for up to a minute.\nresponse = None\nfor x in range(12):\n    response = urllib.request.urlopen(request)\n    if response.getcode() == 200:\n        break\n    time.sleep(5)\n\nif not response or not response.getcode() == 200:\n    print('The API query failed')\n    sys.exit(1)\n\ndata = json.loads(response.read().decode(\"utf-8\"))\n\nspace = [x for x in data['Items'] if x['Name'] == parser.space_name]\n\nif len(space) != 0:\n    print('Space ' + parser.space_name + ' has ID ' + space[0]['Id'])\n    print('The space ID is available as the output variable #{Octopus.Action[' + get_octopusvariable_quiet('Octopus.Action.Name') + '].Output.SpaceID}')\n    set_octopusvariable(\"SpaceID\", space[0]['Id'])\nelse:\n    print('Failed to find space called ' + parser.space_name)\n    sys.exit(1)\n",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "Python"
  },
  "Category": "Octopus",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates/octopus-lookup-space-id.json",
  "Website": "/step-templates/324f747e-e2cd-439d-a660-774baf4991f2",
  "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 »