From 4c7dde421b086bf83f47aaa0a402690e099150b5 Mon Sep 17 00:00:00 2001 From: IsaacCalligeros95 Date: Tue, 19 Nov 2024 12:22:44 +1030 Subject: [PATCH 1/4] Include tenant enabled/disabled state --- .../tenants/enable-disable-tenant.mdx | 27 ++ .../enable-disable-tenant-scripts.include.md | 247 ++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx create mode 100644 src/shared-content/scripts/enable-disable-tenant-scripts.include.md diff --git a/src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx b/src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx new file mode 100644 index 0000000000..d6c0b70457 --- /dev/null +++ b/src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx @@ -0,0 +1,27 @@ +--- +layout: src/layouts/Default.astro +pubDate: 2024-11-18 +modDate: 2024-11-18 +title: Enable/disable tenants +description: An example script that enables or disables a tenant in Octopus. +--- +import EnableDisableTenantScripts from 'src/shared-content/scripts/enable-disable-tenant-scripts.include.md'; + +In 2025.1 Octopus has added support for disabling tenants. Disabled tenants do not allow deployments or runbook runs but are able to be edited. They are also removed from license calculations allowing you to effectively archive unused tenants and re-enable them in the future. +Disabled tenants are highlighted with grayed out text and are not available for selection on the deployment or runbook run pages. If deployments are created for disabled tenants via the API or CLI an exception will be thrown. + +This script demonstrates how to programmatically enable or disable a tenant. + +## Usage + +Provide values for the following: + +- Octopus URL +- Octopus API Key +- Name of the space to use +- Name of the tenant +- Boolean value for enabled + +## Script + + \ No newline at end of file diff --git a/src/shared-content/scripts/enable-disable-tenant-scripts.include.md b/src/shared-content/scripts/enable-disable-tenant-scripts.include.md new file mode 100644 index 0000000000..ffc18b6386 --- /dev/null +++ b/src/shared-content/scripts/enable-disable-tenant-scripts.include.md @@ -0,0 +1,247 @@ +
+PowerShell (REST API) + +```powershell +$ErrorActionPreference = "Stop"; + +# Define working variables +$octopusURL = "https://your-octopus-url" +$octopusAPIKey = "API-YOUR-KEY" +$header = @{ "X-Octopus-ApiKey" = $octopusAPIKey } +$tenantName = "MyTenant" +$tenantEnabled = $true + +# Get space +$space = (Invoke-RestMethod -Method Get -Uri "$octopusURL/api/spaces/all" -Headers $header) | Where-Object {$_.Name -eq $spaceName} + +# Get tenant +$tenant = (Invoke-RestMethod -Method Get -Uri "$octopusURL/api/$($space.Id)/tenants/all" -Headers $header) | Where-Object {$_.Name -eq $tenantName} + +# Enable/disable tenant +$tenant.IsDisabled = !$tenantEnabled + +# Update tenant +Invoke-RestMethod -Method Put -Uri "$octopusURL/api/$($space.Id)/tenants/$($tenant.Id)" -Headers $header -Body ($tenant | ConvertTo-Json -Depth 10) +``` + +
+
+PowerShell (Octopus.Client) + +```powershell +# Load octopus.client assembly +Add-Type -Path "c:\octopus.client\Octopus.Client.dll" + +# Octopus variables +$octopusURL = "https://your-octopus-url" +$octopusAPIKey = "API-YOUR-KEY" +$spaceName = "default" +$tenantName = "MyTenant" +$tenantEnabled = $true + +$endpoint = New-Object Octopus.Client.OctopusServerEndpoint $octopusURL, $octopusAPIKey +$repository = New-Object Octopus.Client.OctopusRepository $endpoint +$client = New-Object Octopus.Client.OctopusClient $endpoint + +try +{ + # Get space + $space = $repository.Spaces.FindByName($spaceName) + $repositoryForSpace = $client.ForSpace($space) + + # Get tenant + $tenant = $repositoryForSpace.Tenants.FindByName($tenantName) + + # Enable/disable tenant + $tenant.IsDisabled = !$tenantEnabled + + # Update tenant + $repositoryForSpace.Tenants.Modify($tenant) +} +catch +{ + Write-Host $_.Exception.Message +} +``` + +
+
+C# + +```csharp +// If using .net Core, be sure to add the NuGet package of System.Security.Permissions +#r "path\to\Octopus.Client.dll" + +using Octopus.Client; +using Octopus.Client.Model; + +// Declare working variables +var octopusURL = "https://your-octopus-url"; +var octopusAPIKey = "API-YOUR-KEY"; +var spaceName = "default"; +var tenantName = "MyTenant"; +bool enabled = false; + +// Create repository object +var endpoint = new OctopusServerEndpoint(octopusURL, octopusAPIKey); +var repository = new OctopusRepository(endpoint); +var client = new OctopusClient(endpoint); + +try +{ + // Get space + var space = repository.Spaces.FindByName(spaceName); + var repositoryForSpace = client.ForSpace(space); + + // Get tenant + var tenant = repositoryForSpace.Tenants.FindByName(tenantName); + + // Enable/disable tenant + tenant.IsDisabled = !enabled; + + //update tenant + repositoryForSpace.Tenants.Modify(tenant); +} +catch (Exception ex) +{ + Console.WriteLine(ex.Message); + return; +} +``` + +
+
+Python3 + +```python +import json +import requests + +octopus_server_uri = 'https://your-octopus-url/api' +octopus_api_key = 'API-YOUR-KEY' +headers = {'X-Octopus-ApiKey': octopus_api_key} + + +def get_octopus_resource(uri): + response = requests.get(uri, headers=headers) + response.raise_for_status() + + return json.loads(response.content.decode('utf-8')) + + +def get_by_name(uri, name): + resources = get_octopus_resource(uri) + return next((x for x in resources if x['Name'] == name), None) + + +space_name = 'Default' +target_name = 'Your Target Name' +disable_target = False + +space = get_by_name('{0}/spaces/all'.format(octopus_server_uri), space_name) +target = get_by_name('{0}/{1}/tenants/all'.format(octopus_server_uri, space['Id']), target_name) + +target['IsDisabled'] = disable_target + +uri = '{0}/{1}/tenants/{2}'.format(octopus_server_uri, space['Id'], target['Id']) +response = requests.put(uri, headers=headers, json=target) +response.raise_for_status() +``` + +
+
+Go + +```go +package main + +import ( + "log" + "net/url" + + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/spaces" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/tenants" +) + +func main() { + apiURL, err := url.Parse("http://localhost:8066") + if err != nil { + log.Fatalf("Error parsing API URL: %v", err) + } + + APIKey := "API-K6JR7YR2UTPH2BQZH1INRZUICEXHDF" + spaceName := "Another One" + tenantName := "Another Tenant" + enabled := true + + space := GetSpace(apiURL, APIKey, spaceName) + if space == nil { + log.Fatalf("Space '%s' not found", spaceName) + } + + client := octopusAuth(apiURL, APIKey, space.ID) + + tenant := GetTenantByName(client, tenantName) + if tenant == nil { + log.Fatalf("Tenant '%s' not found", tenantName) + } + + tenant.IsDisabled = !enabled + updatedTenant, err := client.Tenants.Update(tenant) + if err != nil { + log.Fatalf("Error updating tenant: %v", err) + } + + log.Printf("Tenant '%s' updated successfully. IsDisabled: %v", updatedTenant.Name, updatedTenant.IsDisabled) +} + +func octopusAuth(octopusURL *url.URL, APIKey string, spaceID string) *client.Client { + client, err := client.NewClient(nil, octopusURL, APIKey, spaceID) + if err != nil { + log.Fatalf("Error creating Octopus client: %v", err) + } + return client +} + +func GetSpace(octopusURL *url.URL, APIKey string, spaceName string) *spaces.Space { + client := octopusAuth(octopusURL, APIKey, "") + + spaceQuery := spaces.SpacesQuery{ + PartialName: spaceName, + } + + spaces, err := client.Spaces.Get(spaceQuery) + if err != nil { + log.Fatalf("Error retrieving spaces: %v", err) + } + + for _, space := range spaces.Items { + if space.Name == spaceName { + return space + } + } + + return nil +} + +func GetTenantByName(client *client.Client, tenantName string) *tenants.Tenant { + tenantQuery := tenants.TenantsQuery{ + Name: tenantName, + } + + tenants, err := client.Tenants.Get(tenantQuery) + if err != nil { + log.Fatalf("Error retrieving tenants: %v", err) + } + + if len(tenants.Items) == 1 { + return tenants.Items[0] + } + + return nil +} + +``` + +
From 68325f8bce41c329d24dbf9688084e324843a013 Mon Sep 17 00:00:00 2001 From: IsaacCalligeros95 Date: Tue, 19 Nov 2024 12:40:34 +1030 Subject: [PATCH 2/4] Fix example scripts --- .../enable-disable-tenant-scripts.include.md | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/shared-content/scripts/enable-disable-tenant-scripts.include.md b/src/shared-content/scripts/enable-disable-tenant-scripts.include.md index ffc18b6386..841bf5e987 100644 --- a/src/shared-content/scripts/enable-disable-tenant-scripts.include.md +++ b/src/shared-content/scripts/enable-disable-tenant-scripts.include.md @@ -135,16 +135,16 @@ def get_by_name(uri, name): space_name = 'Default' -target_name = 'Your Target Name' -disable_target = False +tenant_name = 'Your Tenant Name' +disable_tenant = False space = get_by_name('{0}/spaces/all'.format(octopus_server_uri), space_name) -target = get_by_name('{0}/{1}/tenants/all'.format(octopus_server_uri, space['Id']), target_name) +tenant = get_by_name('{0}/{1}/tenants/all'.format(octopus_server_uri, space['Id']), tenant_name) -target['IsDisabled'] = disable_target +tenant['IsDisabled'] = disable_tenant -uri = '{0}/{1}/tenants/{2}'.format(octopus_server_uri, space['Id'], target['Id']) -response = requests.put(uri, headers=headers, json=target) +uri = '{0}/{1}/tenants/{2}'.format(octopus_server_uri, space['Id'], tenant['Id']) +response = requests.put(uri, headers=headers, json=tenant) response.raise_for_status() ``` @@ -165,32 +165,31 @@ import ( ) func main() { - apiURL, err := url.Parse("http://localhost:8066") + apiURL, err := url.Parse("https://your-octopus-url") if err != nil { - log.Fatalf("Error parsing API URL: %v", err) + log.Println(err) } - - APIKey := "API-K6JR7YR2UTPH2BQZH1INRZUICEXHDF" - spaceName := "Another One" - tenantName := "Another Tenant" + APIKey := "API-YOUR-KEY" + spaceName := "Default" + tenantName := "MyTenant" enabled := true space := GetSpace(apiURL, APIKey, spaceName) if space == nil { - log.Fatalf("Space '%s' not found", spaceName) + log.Println(err) } client := octopusAuth(apiURL, APIKey, space.ID) tenant := GetTenantByName(client, tenantName) if tenant == nil { - log.Fatalf("Tenant '%s' not found", tenantName) + log.Println(err) } tenant.IsDisabled = !enabled updatedTenant, err := client.Tenants.Update(tenant) if err != nil { - log.Fatalf("Error updating tenant: %v", err) + log.Println(err) } log.Printf("Tenant '%s' updated successfully. IsDisabled: %v", updatedTenant.Name, updatedTenant.IsDisabled) @@ -199,7 +198,7 @@ func main() { func octopusAuth(octopusURL *url.URL, APIKey string, spaceID string) *client.Client { client, err := client.NewClient(nil, octopusURL, APIKey, spaceID) if err != nil { - log.Fatalf("Error creating Octopus client: %v", err) + log.Println(err) } return client } @@ -213,7 +212,7 @@ func GetSpace(octopusURL *url.URL, APIKey string, spaceName string) *spaces.Spac spaces, err := client.Spaces.Get(spaceQuery) if err != nil { - log.Fatalf("Error retrieving spaces: %v", err) + log.Println(err) } for _, space := range spaces.Items { @@ -232,7 +231,7 @@ func GetTenantByName(client *client.Client, tenantName string) *tenants.Tenant { tenants, err := client.Tenants.Get(tenantQuery) if err != nil { - log.Fatalf("Error retrieving tenants: %v", err) + log.Println(err) } if len(tenants.Items) == 1 { @@ -242,6 +241,7 @@ func GetTenantByName(client *client.Client, tenantName string) *tenants.Tenant { return nil } + ``` From 8b5f316d46f8b0f3a4aa76a6e5ceaf38b7a0c16c Mon Sep 17 00:00:00 2001 From: IsaacCalligeros95 Date: Wed, 20 Nov 2024 10:39:28 +1030 Subject: [PATCH 3/4] Update wording --- .../enable-disable-machine.mdx | 2 +- .../projects/enable-disable-project.mdx | 2 +- .../examples/tenants/deactivate-tenant.mdx | 27 +++++++++++++++++++ .../tenants/enable-disable-tenant.mdx | 27 ------------------- .../examples/tenants/index.md | 3 ++- ...d => deactivate-tenant-scripts.include.md} | 10 +++---- 6 files changed, 36 insertions(+), 35 deletions(-) create mode 100644 src/pages/docs/octopus-rest-api/examples/tenants/deactivate-tenant.mdx delete mode 100644 src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx rename src/shared-content/scripts/{enable-disable-tenant-scripts.include.md => deactivate-tenant-scripts.include.md} (95%) diff --git a/src/pages/docs/octopus-rest-api/examples/deployment-targets/enable-disable-machine.mdx b/src/pages/docs/octopus-rest-api/examples/deployment-targets/enable-disable-machine.mdx index ed1b4c5fbd..a819f16360 100644 --- a/src/pages/docs/octopus-rest-api/examples/deployment-targets/enable-disable-machine.mdx +++ b/src/pages/docs/octopus-rest-api/examples/deployment-targets/enable-disable-machine.mdx @@ -2,7 +2,7 @@ layout: src/layouts/Default.astro pubDate: 2023-01-01 modDate: 2023-01-01 -title: Enable/disable machine +title: Deactivate machines description: An example script that enables or disables a machine in Octopus. --- import EnableDisableMachineScripts from 'src/shared-content/scripts/enable-disable-machine-scripts.include.md'; diff --git a/src/pages/docs/octopus-rest-api/examples/projects/enable-disable-project.mdx b/src/pages/docs/octopus-rest-api/examples/projects/enable-disable-project.mdx index 82e8ec2f24..766adaa01d 100644 --- a/src/pages/docs/octopus-rest-api/examples/projects/enable-disable-project.mdx +++ b/src/pages/docs/octopus-rest-api/examples/projects/enable-disable-project.mdx @@ -2,7 +2,7 @@ layout: src/layouts/Default.astro pubDate: 2023-01-01 modDate: 2023-01-01 -title: Enable/disable project +title: Deactivate projects description: An example script that enables or disables a project in Octopus. --- import EnableDisableProjectScripts from 'src/shared-content/scripts/enable-disable-project-scripts.include.md'; diff --git a/src/pages/docs/octopus-rest-api/examples/tenants/deactivate-tenant.mdx b/src/pages/docs/octopus-rest-api/examples/tenants/deactivate-tenant.mdx new file mode 100644 index 0000000000..89cb2bda31 --- /dev/null +++ b/src/pages/docs/octopus-rest-api/examples/tenants/deactivate-tenant.mdx @@ -0,0 +1,27 @@ +--- +layout: src/layouts/Default.astro +pubDate: 2024-11-18 +modDate: 2024-11-18 +title: Deactivate tenants +description: An example script that activates or deactivates a tenant in Octopus. +--- +import DeactivateTenantScripts from 'src/shared-content/scripts/deactivate-tenant-scripts.include.md'; + +In 2025.1 Octopus has added support for deactivating tenants. Inactive tenants do not allow deployments or runbook runs but are able to be edited. They are also removed from license calculations allowing you to effectively archive unused tenants and re-enable them in the future. +Inactive tenants are highlighted with grayed out text and are not available for selection on the deployment or runbook run pages. If deployments are created for inactive tenants via the API or CLI an exception will be thrown. + +This script demonstrates how to programmatically deactivate a tenant. + +## Usage + +Provide values for the following: + +- Octopus URL +- Octopus API Key +- Name of the space to use +- Name of the tenant +- Boolean value for enabled + +## Script + + \ No newline at end of file diff --git a/src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx b/src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx deleted file mode 100644 index d6c0b70457..0000000000 --- a/src/pages/docs/octopus-rest-api/examples/tenants/enable-disable-tenant.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: src/layouts/Default.astro -pubDate: 2024-11-18 -modDate: 2024-11-18 -title: Enable/disable tenants -description: An example script that enables or disables a tenant in Octopus. ---- -import EnableDisableTenantScripts from 'src/shared-content/scripts/enable-disable-tenant-scripts.include.md'; - -In 2025.1 Octopus has added support for disabling tenants. Disabled tenants do not allow deployments or runbook runs but are able to be edited. They are also removed from license calculations allowing you to effectively archive unused tenants and re-enable them in the future. -Disabled tenants are highlighted with grayed out text and are not available for selection on the deployment or runbook run pages. If deployments are created for disabled tenants via the API or CLI an exception will be thrown. - -This script demonstrates how to programmatically enable or disable a tenant. - -## Usage - -Provide values for the following: - -- Octopus URL -- Octopus API Key -- Name of the space to use -- Name of the tenant -- Boolean value for enabled - -## Script - - \ No newline at end of file diff --git a/src/pages/docs/octopus-rest-api/examples/tenants/index.md b/src/pages/docs/octopus-rest-api/examples/tenants/index.md index 0ded7f5a61..84d44c685f 100644 --- a/src/pages/docs/octopus-rest-api/examples/tenants/index.md +++ b/src/pages/docs/octopus-rest-api/examples/tenants/index.md @@ -10,4 +10,5 @@ hideInThisSectionHeader: true You can use the REST API to create and manage Server tasks in Octopus. Typical tasks might include: - [Create a tenant](/docs/octopus-rest-api/examples/tenants/create-tenant) -- [Update tenant variables](/docs/octopus-rest-api/examples/tenants/update-tenant-variable) \ No newline at end of file +- [Update tenant variables](/docs/octopus-rest-api/examples/tenants/update-tenant-variable) +- [Deactivate tenants](/docs/octopus-rest-api/examples/projects/deactivate-tenant) \ No newline at end of file diff --git a/src/shared-content/scripts/enable-disable-tenant-scripts.include.md b/src/shared-content/scripts/deactivate-tenant-scripts.include.md similarity index 95% rename from src/shared-content/scripts/enable-disable-tenant-scripts.include.md rename to src/shared-content/scripts/deactivate-tenant-scripts.include.md index 841bf5e987..2128747f45 100644 --- a/src/shared-content/scripts/enable-disable-tenant-scripts.include.md +++ b/src/shared-content/scripts/deactivate-tenant-scripts.include.md @@ -1,4 +1,4 @@ -
+
PowerShell (REST API) ```powershell @@ -25,7 +25,7 @@ Invoke-RestMethod -Method Put -Uri "$octopusURL/api/$($space.Id)/tenants/$($tena ```
-
+
PowerShell (Octopus.Client) ```powershell @@ -65,7 +65,7 @@ catch ```
-
+
C# ```csharp @@ -110,7 +110,7 @@ catch (Exception ex) ```
-
+
Python3 ```python @@ -149,7 +149,7 @@ response.raise_for_status() ```
-
+
Go ```go From c9cc72a00fd4fac51270b4ecd836bb39beb66eac Mon Sep 17 00:00:00 2001 From: IsaacCalligeros95 Date: Wed, 20 Nov 2024 12:26:11 +1030 Subject: [PATCH 4/4] Fix deactivate tenant path --- src/pages/docs/octopus-rest-api/examples/tenants/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/docs/octopus-rest-api/examples/tenants/index.md b/src/pages/docs/octopus-rest-api/examples/tenants/index.md index 84d44c685f..b669f7a920 100644 --- a/src/pages/docs/octopus-rest-api/examples/tenants/index.md +++ b/src/pages/docs/octopus-rest-api/examples/tenants/index.md @@ -11,4 +11,4 @@ You can use the REST API to create and manage Server tasks in Octopus. Typical t - [Create a tenant](/docs/octopus-rest-api/examples/tenants/create-tenant) - [Update tenant variables](/docs/octopus-rest-api/examples/tenants/update-tenant-variable) -- [Deactivate tenants](/docs/octopus-rest-api/examples/projects/deactivate-tenant) \ No newline at end of file +- [Deactivate tenants](/docs/octopus-rest-api/examples/tenants/deactivate-tenant) \ No newline at end of file