Clone Tenant

Octopus.Script exported 2021-08-23 by benjimac93 belongs to ‘Octopus’ category.

Clone an Octopus tenant. The project connections and tenant tags will be cloned and the non-sensitive variables can optionally be cloned.

Parameters

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

Octopus URL

CloneTenantStep_OctopusUrl = #{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}

The URL of the Octopus Server to clone the tenant to.

Octopus API Key

CloneTenantStep_ApiKey =

The Octopus API Key to use for the API requests

Id of Tenant to Clone

CloneTenantStep_TenantIdToClone =

The Id of the tenant to clone. This will be in the format of Tenants-1

New Tenant Name

CloneTenantStep_TenantName =

The name of the tenant to create. Note this must be unique

Clone Variables?

CloneTenantStep_CloneVariables =

Flag indicating whether the source tenant’s variables should be cloned to the new tenant. Note this does not copy sensitive variables

Clone Tags?

CloneTenantStep_CloneTags = True

Flag indicating whether the source tenant’s tags should be cloned.

Space Id

CloneTenantStep_SpaceId =

The Id of the Space used to clone the tenant. Leave blank if you are using an Octopus version earlier than 2019.1 or if you wish to use the Octopus.Space.Id variable value.

Script body

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

$securityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
[Net.ServicePointManager]::SecurityProtocol = $securityProtocol

$octopusBaseUrl = $CloneTenantStep_OctopusUrl.Trim('/')
$apiKey = $CloneTenantStep_ApiKey
$tenantToClone = $CloneTenantStep_TenantIdToClone
$tenantName = $CloneTenantStep_TenantName
$cloneVariables = $CloneTenantStep_CloneVariables
$cloneTags = $CloneTenantStep_CloneTags
$spaceId = $CloneTenantStep_SpaceId

$ErrorActionPreference = 'Stop'

if ([string]::IsNullOrWhiteSpace($octopusBaseUrl)) {
    throw "The step parameter 'Octopus Base Url' was not found. This step requires the Octopus Server URL to function, please provide one and try again."
}

if ([string]::IsNullOrWhiteSpace($apiKey)) {
    throw "The step parameter 'Octopus API Key' was not found. This step requires an API Key to function, please provide one and try again."
}

if ([string]::IsNullOrWhiteSpace($tenantToClone)) {
    throw "The step parameter 'Id of Tenant to Clone' was not found. Please provide one and try again."
}

if ([string]::IsNullOrWhiteSpace($tenantName)) {
    throw "The step parameter 'New Tenant Name' was not found. Please provide one and try again."
}

function Invoke-OctopusApi {
    param(
        [Parameter(Position = 0, Mandatory)]$Uri,
        [ValidateSet("Get", "Post", "Put", "Delete")]$Method = 'Get',
        $Body
    )
    
    $uriParts = @($octopusBaseUrl, $Uri.TrimStart('/'))    
    $uri = ($uriParts -join '/')

    Write-Verbose "Uri: $uri"
    
    $requestParameters = @{
        Uri = $uri
        Method = $Method
        Headers = @{ "X-Octopus-ApiKey" = $apiKey }
        UseBasicParsing = $true
    }
    
    if ($null -ne $Body) { $requestParameters.Add('Body', ($Body | ConvertTo-Json -Depth 10)) }
    
    return Invoke-WebRequest @requestParameters | % Content | ConvertFrom-Json
}

function Test-SpacesApi {
	Write-Verbose "Checking API compatibility";
	$rootDocument = Invoke-OctopusApi 'api/';
    if($rootDocument.Links -ne $null -and $rootDocument.Links.Spaces -ne $null) {
    	Write-Verbose "Spaces API found"
    	return $true;
    }
    Write-Verbose "Pre-spaces API found"
    return $false;
}

if([string]::IsNullOrWhiteSpace($spaceId)) {
	if(Test-SpacesApi) {
      	$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 or try providing the Space Id parameter.";
      	}
	}
}

$apiPrefix = "api/"
$tenantUrlBase = @($octopusBaseUrl, 'app#')

if ($spaceId) {
	$apiPrefix += $spaceId
    $tenantUrlBase += $spaceId
}

Write-Host "Fetching source tenant"
$tenant = Invoke-OctopusApi "$apiPrefix/tenants/$tenantToClone"

$sourceTenantId = $tenant.Id
$sourceTenantName = $tenant.Name
$tenant.Id = $null
$tenant.Name = $tenantName

if ($cloneTags -ne $true) {
	Write-Host "Clearing tenant tags"
    $tenant.TenantTags = @()
}

Write-Host "Creating new tenant"
$newTenant = Invoke-OctopusApi "$apiPrefix/tenants" -Method Post -Body $tenant

if ($cloneVariables -eq $true) {
	Write-Host "Cloning variables"
    $variables = Invoke-OctopusApi $tenant.Links.Variables
    $variables.TenantId = $newTenant.Id
    $variables.TenantName = $tenantName

    Invoke-OctopusApi $newTenant.Links.Variables -Method Put -Body $variables | Out-Null
}

$tenantUrl = ($tenantUrlBase + "tenants" + $newTenant.Id + "overview") -join '/'
$sourceTenantUrl = ($tenantUrlBase + "tenants" + $sourceTenantId + "overview") -join '/'

Write-Highlight "New tenant [$tenantName]($tenantUrl) has been cloned from [$sourceTenantName]($sourceTenantUrl)"

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": "3b0f8df0-93b8-44eb-86dd-264d1283ae70",
  "Name": "Clone Tenant",
  "Description": "Clone an Octopus [tenant](https://octopus.com/docs/deployment-patterns/multi-tenant-deployments). The project connections and tenant tags will be cloned and the non-sensitive variables can optionally be cloned.",
  "Version": 4,
  "ExportedAt": "2021-08-23T12:40:10.975Z",
  "ActionType": "Octopus.Script",
  "Author": "benjimac93",
  "Packages": [],
  "Parameters": [
    {
      "Id": "cbedd129-210e-4bab-a446-3f89192653c7",
      "Name": "CloneTenantStep_OctopusUrl",
      "Label": "Octopus URL",
      "HelpText": "The URL of the Octopus Server to clone the tenant to.",
      "DefaultValue": "#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "ea2614f0-bd41-4011-b263-7d2b12af5977",
      "Name": "CloneTenantStep_ApiKey",
      "Label": "Octopus API Key",
      "HelpText": "The Octopus API Key to use for the API requests",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "b29e27fb-362e-45e2-a244-6d590875fb68",
      "Name": "CloneTenantStep_TenantIdToClone",
      "Label": "Id of Tenant to Clone",
      "HelpText": "The Id of the tenant to clone. This will be in the format of *Tenants-1*",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "b9b3a6c7-6c83-4a79-9a94-febc6c5818d3",
      "Name": "CloneTenantStep_TenantName",
      "Label": "New Tenant Name",
      "HelpText": "The name of the tenant to create. *Note this must be unique*",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "be821ad4-b195-4b11-81c2-f432ff05b86d",
      "Name": "CloneTenantStep_CloneVariables",
      "Label": "Clone Variables?",
      "HelpText": "Flag indicating whether the source tenant's variables should be cloned to the new tenant. *Note this does not copy sensitive variables*",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "831db28c-edc2-496b-b082-e6de827ca5df",
      "Name": "CloneTenantStep_CloneTags",
      "Label": "Clone Tags?",
      "HelpText": "Flag indicating whether the source tenant's tags should be cloned.",
      "DefaultValue": "True",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "f9320a59-9752-43a5-b46a-a4d1486cfced",
      "Name": "CloneTenantStep_SpaceId",
      "Label": "Space Id",
      "HelpText": "The Id of the Space used to clone the tenant. **Leave blank if you are using an Octopus version earlier than 2019.1 or if you wish to use the Octopus.Space.Id variable value.**",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "$securityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12\n[Net.ServicePointManager]::SecurityProtocol = $securityProtocol\n\n$octopusBaseUrl = $CloneTenantStep_OctopusUrl.Trim('/')\n$apiKey = $CloneTenantStep_ApiKey\n$tenantToClone = $CloneTenantStep_TenantIdToClone\n$tenantName = $CloneTenantStep_TenantName\n$cloneVariables = $CloneTenantStep_CloneVariables\n$cloneTags = $CloneTenantStep_CloneTags\n$spaceId = $CloneTenantStep_SpaceId\n\n$ErrorActionPreference = 'Stop'\n\nif ([string]::IsNullOrWhiteSpace($octopusBaseUrl)) {\n    throw \"The step parameter 'Octopus Base Url' was not found. This step requires the Octopus Server URL to function, please provide one and try again.\"\n}\n\nif ([string]::IsNullOrWhiteSpace($apiKey)) {\n    throw \"The step parameter 'Octopus API Key' was not found. This step requires an API Key to function, please provide one and try again.\"\n}\n\nif ([string]::IsNullOrWhiteSpace($tenantToClone)) {\n    throw \"The step parameter 'Id of Tenant to Clone' was not found. Please provide one and try again.\"\n}\n\nif ([string]::IsNullOrWhiteSpace($tenantName)) {\n    throw \"The step parameter 'New Tenant Name' was not found. Please provide one and try again.\"\n}\n\nfunction Invoke-OctopusApi {\n    param(\n        [Parameter(Position = 0, Mandatory)]$Uri,\n        [ValidateSet(\"Get\", \"Post\", \"Put\", \"Delete\")]$Method = 'Get',\n        $Body\n    )\n    \n    $uriParts = @($octopusBaseUrl, $Uri.TrimStart('/'))    \n    $uri = ($uriParts -join '/')\n\n    Write-Verbose \"Uri: $uri\"\n    \n    $requestParameters = @{\n        Uri = $uri\n        Method = $Method\n        Headers = @{ \"X-Octopus-ApiKey\" = $apiKey }\n        UseBasicParsing = $true\n    }\n    \n    if ($null -ne $Body) { $requestParameters.Add('Body', ($Body | ConvertTo-Json -Depth 10)) }\n    \n    return Invoke-WebRequest @requestParameters | % Content | ConvertFrom-Json\n}\n\nfunction Test-SpacesApi {\n\tWrite-Verbose \"Checking API compatibility\";\n\t$rootDocument = Invoke-OctopusApi 'api/';\n    if($rootDocument.Links -ne $null -and $rootDocument.Links.Spaces -ne $null) {\n    \tWrite-Verbose \"Spaces API found\"\n    \treturn $true;\n    }\n    Write-Verbose \"Pre-spaces API found\"\n    return $false;\n}\n\nif([string]::IsNullOrWhiteSpace($spaceId)) {\n\tif(Test-SpacesApi) {\n      \t$spaceId = $OctopusParameters['Octopus.Space.Id'];\n      \tif([string]::IsNullOrWhiteSpace($spaceId)) {\n          \tthrow \"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 or try providing the Space Id parameter.\";\n      \t}\n\t}\n}\n\n$apiPrefix = \"api/\"\n$tenantUrlBase = @($octopusBaseUrl, 'app#')\n\nif ($spaceId) {\n\t$apiPrefix += $spaceId\n    $tenantUrlBase += $spaceId\n}\n\nWrite-Host \"Fetching source tenant\"\n$tenant = Invoke-OctopusApi \"$apiPrefix/tenants/$tenantToClone\"\n\n$sourceTenantId = $tenant.Id\n$sourceTenantName = $tenant.Name\n$tenant.Id = $null\n$tenant.Name = $tenantName\n\nif ($cloneTags -ne $true) {\n\tWrite-Host \"Clearing tenant tags\"\n    $tenant.TenantTags = @()\n}\n\nWrite-Host \"Creating new tenant\"\n$newTenant = Invoke-OctopusApi \"$apiPrefix/tenants\" -Method Post -Body $tenant\n\nif ($cloneVariables -eq $true) {\n\tWrite-Host \"Cloning variables\"\n    $variables = Invoke-OctopusApi $tenant.Links.Variables\n    $variables.TenantId = $newTenant.Id\n    $variables.TenantName = $tenantName\n\n    Invoke-OctopusApi $newTenant.Links.Variables -Method Put -Body $variables | Out-Null\n}\n\n$tenantUrl = ($tenantUrlBase + \"tenants\" + $newTenant.Id + \"overview\") -join '/'\n$sourceTenantUrl = ($tenantUrlBase + \"tenants\" + $sourceTenantId + \"overview\") -join '/'\n\nWrite-Highlight \"New tenant [$tenantName]($tenantUrl) has been cloned from [$sourceTenantName]($sourceTenantUrl)\""
  },
  "Category": "Octopus",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/clone-tenant.json",
  "Website": "/step-templates/3b0f8df0-93b8-44eb-86dd-264d1283ae70",
  "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 Monday, August 23, 2021