I’m using your script to remove variables, I would like to be able to remove variables filtered by environment. Is this possible? This is what I’ve added but the script stopped removing variables so just need to see where I’ve gone wrong.
TIA
Function Get-OctopusProject {
# Define parameters
param(
$OctopusServerUrl,
$ApiKey,
$ProjectName,
$SpaceId
)
# Call API to get all projects, then filter on name
$octopusProject = Invoke-RestMethod -Method "get" -Uri "$OctopusServerUrl/api/$spaceId/projects/all" -Headers @{"X-Octopus-ApiKey" = "$ApiKey" }
# return the specific project
return ($octopusProject | Where-Object { $_.Name -eq $ProjectName })
}
Function Get-OctopusProjectVariables {
# Define parameters
param(
$OctopusDeployProject,
$OctopusServerUrl,
$ApiKey,
$SpaceId
)
# Get reference to the variable list
return (Invoke-RestMethod -Method "get" -Uri "$OctopusServerUrl/api/$spaceId/variables/$($OctopusDeployProject.VariableSetId)" -Headers @{"X-Octopus-ApiKey" = "$ApiKey" })
}
Function Get-SpaceId {
# Define parameters
param(
$Space
)
$spaceName = $Space
$spaceList = Invoke-RestMethod "$OctopusServerUrl/api/spaces?partialName=$([uri]::EscapeDataString($spaceName))&skip=0&take=100" -Headers @{"X-Octopus-ApiKey" = $ApiKey }
$spaceFilter = @($spaceList.Items | Where-Object { $_.Name -eq $spaceName })
$spaceId = $spaceFilter[0].Id
return $spaceId
}
Function Get-EnvironmentId {
# Define parameters
param(
$EnvironmentName,
$SpaceId
)
$environmentList = Invoke-RestMethod "$OctopusServerUrl/api/$spaceId/environments?skip=0&take=1000&name=$environmentName" -Headers @{"X-Octopus-ApiKey" = $ApiKey }
$environmentFilter = @($environmentList.Items | Where-Object { $_.Name -eq $environmentName })
$environmentId = $environmentFilter[0].Id
return $environmentId
}
Function Remove-Variable {
param(
$VariableSet,
$VariableName,
$EnvironmentName
)
$environmentList = Invoke-RestMethod "$OctopusServerUrl/api/$spaceId/environments?skip=0&take=1000&name=$environmentName" -Headers @{"X-Octopus-ApiKey" = $ApiKey }
$environmentFilter = @($environmentList.Items | Where-Object { $_.Name -eq $environmentName })
$environmentId = $environmentFilter[0].Id
return $environmentId
$tempVars = @()
#Create the variable object
$obj = New-Object -Type PSObject -Property @{
'Name' = $($VariableName)
'Value' = $($VariableValue)
'Type' = 'String'
'IsSensitive' = $IsSensitive
'Scope' = @{
'Environment' = @($environmentId)
'Role' = @()
}
}
foreach ($variable in $VariableSet.Variables) {
if ($variable.Name -ne $VariableName -and $variable.Scope.Environment -eq $environmentId) {
$tempVars += $variable
}
}
$variableset.Variables = $tempVars
}
### INPUT THESE VALUES ####
$OctopusServerUrl = "XXXX" #PUT YOUR SERVER LOCATION HERE. (e.g. http://localhost)
$ApiKey = "XXXXX" #PUT YOUR API KEY HERE
$ProjectName = "XXXXX" #PUT THE NAME OF THE PROJECT THAT HOUSES THE VARIABLES HERE
$SpaceName = "Default" #PUT THE NAME OF THE SPACE THAT HOUSES THE PROJECT HERE
### INPUT THESE VALUES ####
try {
# Convert SpaceName to SpaceId
$SpaceId = Get-SpaceId -Space $SpaceName
# Get reference to project
$octopusProject = Get-OctopusProject -OctopusServerUrl $OctopusServerUrl -ApiKey $ApiKey -ProjectName $ProjectName -SpaceId $SpaceId
# Get list of existing variables
$octopusProjectVariables = Get-OctopusProjectVariables -OctopusDeployProject $octopusProject -OctopusServerUrl $OctopusServerUrl -ApiKey $ApiKey -SpaceId $SpaceId
#--------------------------
#Remove-Variable Information
#--------------------------
#Remove-Variable will delete any variable with the name regardless of scoping
#Remove-Variable -VariableSet $octopusProjectVariables -VariableName "RemoveThis"
##### PUT ANY MODIFY AND ADD COMMANDS HERE #####
Remove-Variable -VariableSet $octopusProjectVariables -VariableName "Test_Variable" -EnvironmentName "test_env"
##### PUT ANY MODIFY AND ADD COMMANDS HERE #####
# Convert object to json to upload it
#$octopusProjectVariables.Version++
$jsonBody = $octopusProjectVariables | ConvertTo-Json -Depth 10
#Write-Host $jsonBody
# Save the variables to the variable set
Invoke-RestMethod -Method "put" -Uri "$OctopusServerUrl/api/$spaceId/variables/$($octopusProjectVariables.Id)" -Body $jsonBody -Headers @{"X-Octopus-ApiKey" = $ApiKey }
}
catch {
Write-Error $_.Exception.Message
throw
}```
At a glance, I don’t see anything wrong with the way you have it set up (assuming you’ve filled out the ### INPUT THESE VALUES #### section).
Can you provide additional details about where the script is stopping? Are you getting an error? Is this working for some Variable/Environment/Project combinations, but not others?
There’s no error the script runs but doesn’t remove any variables, correct I am filling in the input values. If you run the script do you get the same?
I ran the script on my end and that particular section of the script does not appear to be functional. Unfortunately, the script’s author is no longer with Octopus and after a bit of tinkering it was clear that this will need more of a deep dive to either fix the existing script or craft a new one entirely.
I likely won’t have a chance today to spend any more time on this. However, I’ll do my best to have another crack at it in the morning (UK time). In the meantime, I don’t recommend trying to run this script in its current form.
Quick question, are you looking to remove Project Variables scoped to Environments in all Projects or just certain ones?
Thank you for your patience. Apologies for the delay in getting back to you.
Below is a simple script you may use to remove Variables from a Project scoped to a particular Environment:
# =======================================================
# Delete Project Variables scoped to an Environment
# =======================================================
$ErrorActionPreference = "Stop";
# Define working variables
$OctopusURL = "https://Your_Octopus_URL" # no trailing /
$octopusAPIKey = "API-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$Header = @{ "X-Octopus-ApiKey" = $octopusAPIKey }
$SpaceId = "Spaces-XXX"
$ProjectName = "Some Project"
$EnvironmentName = "Some Environment"
# Get Environment ID
$Environment = (Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/environments/all" -Headers $Header) | Where-Object {$_.Name -eq $EnvironmentName}
# Get Project ID
$Project = (Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/projects/all" -Headers $Header) | Where-Object {$_.Name -eq $ProjectName}
# Get Project Variables
$ProjectVariablesJSON = Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/variables/$($Project.VariableSetId)" -Headers $Header
$ProjectVariables = $ProjectVariablesJSON.Variables
# Filter Variables based on $EnvironmentName
$ModifiedProjectVariables = @()
Foreach ($ProjectVariable in $ProjectVariables) {
$ModifiedProjectVariables += $ProjectVariable | Where-Object {$_.Scope.Environment -ne $($Environment.Id)}
}
$ModifiedProjectVariablesJSON = $ProjectVariablesJSON
$ModifiedProjectVariablesJSON.variables = $ModifiedProjectVariables
# Swap the comment from line 38 to line 37 after you have tested the script is working the way you want
$ModifiedProjectVariables | ConvertTo-Json -depth 10
# Invoke-RestMethod -Method PUT "$OctopusURL/api/$($SpaceId)/variables/$($Project.VariableSetId)" -Body ($ModifiedProjectVariablesJSON | ConvertTo-Json -Depth 10) -Headers $Header
I’ve set it up to print the filtered Variables before committing this change to your Project. Just swap the # comment hash once you are happy with what you are seeing.
Let me know if this works for you once you get a chance to try it.
I’ve amended the script so that is loops through every project and remove all the environment variables. We have 432 projects and for some reason it’s only finding 409 projects so some projects are being missed and I’m not sure why as I do a get call to get all the projects.
This is my script below can you see why that would be?
# =======================================================
# Bulk Delete all Variables scoped to an Environment
# =======================================================
$ErrorActionPreference = "continue";
# Define working variables
$OctopusURL = "XXXX" # no trailing /
$octopusAPIKey = "XXXX"
$Header = @{ "X-Octopus-ApiKey" = $octopusAPIKey }
$SpaceId = "Spaces-1"
$EnvironmentName = "XXX" # Enter Environment
# Get Environment ID
$Environment = (Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/environments/all" -Headers $Header) | Where-Object {$_.Name -eq $EnvironmentName}
$AllProjects = Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/projects/all" -Headers $Header
try{
foreach($ProjectName in $AllProjects)
{
# Get Project ID
#$Name = $ProjectName.Name
$Project = (Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/projects/all" -Headers $Header) | Where-Object {$_.Name -eq $ProjectName.Name}
# Get Project Variables
$ProjectVariablesJSON = Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/variables/$($Project.VariableSetId)" -Headers $Header
$ProjectVariables = $ProjectVariablesJSON.Variables
# Filter Variables based on $EnvironmentName
$ModifiedProjectVariables = @()
Foreach ($ProjectVariable in $ProjectVariables) {
$ModifiedProjectVariables += $ProjectVariable | Where-Object {$_.Scope.Environment -ne $($Environment.Id)}
}
$ModifiedProjectVariablesJSON = $ProjectVariablesJSON
$ModifiedProjectVariablesJSON.variables = $ModifiedProjectVariables
# Swap the comment from line 38 to line 37 after you have tested the script is working the way you want
#$ModifiedProjectVariables | ConvertTo-Json -depth 10
Invoke-RestMethod -Method PUT "$OctopusURL/api/$($SpaceId)/variables/$($Project.VariableSetId)" -Body ($ModifiedProjectVariablesJSON | ConvertTo-Json -Depth 10) -Headers $Header
}
}
catch
{
Write-Host $Name
$output = $Name | Out-File failed_projects.txt -Append
}
Are these other Projects in a different Space? If you navigate in your browser to http://YOUR_OCTOPUS_URL/api/Spaces-XX/projects, does the “TotalResults” returned in the JSON match $AllProjects.count in the script?
Nope we’ve only got 1 space and the all projects count is saying 432. I add an outfile for the projects for the $ProjectName.Name and it’s only counting 409
If you just run the following, how many Projects does it detect?
$ErrorActionPreference = "continue";
# Define working variables
$OctopusURL = "XXXX" # no trailing /
$octopusAPIKey = "XXXX"
$Header = @{ "X-Octopus-ApiKey" = $octopusAPIKey }
$SpaceId = "Spaces-1"
$EnvironmentName = "XXX" # Enter Environment
# Get Environment ID
$Environment = (Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/environments/all" -Headers $Header) | Where-Object {$_.Name -eq $EnvironmentName}
$AllProjects = Invoke-RestMethod -Method GET "$OctopusURL/api/$($SpaceId)/projects/all" -Headers $Header
$AllProjects.count
If it is 432, this might mean these “failing” Projects may have scoping that your API key does not have permissions for. If the count returns as 409, it means the API key does not have access to these Projects at all.
Let me know what you find once you get a chance to look at it again.
I’m assuming you’ve created the API key against your own account. If this is the case, can you browse to one of the Projects in question and check to see if there are Variables in the Project’s VariableSet? If so, can you see any Variables that are Scoped with something that you may not have permissions for, such as a particular Environment or Tenant?
Also, can you confirm if anyone of these Projects in question have a Variable scoped to the Environment specified in the script parameters?
I have full admin permissions, so I can see everything there are some projects which don’t have the environment scoped but they’re not the ones being missed. I have some which I’ve been able to scope using script and manually being cut out.
I’m debugging line by line so far I’ve got up to this section and it’s looping through to 432 as I’ve added a count.
# Filter Variables based on $EnvironmentName
$ModifiedProjectVariables = @()
Foreach ($ProjectVariable in $ProjectVariables) {
$ModifiedProjectVariables += $ProjectVariable | Where-Object {$_.Scope.Environment -ne $($Environment.Id)}
}
$ModifiedProjectVariablesJSON = $ProjectVariablesJSON
$ModifiedProjectVariablesJSON.variables = $ModifiedProjectVariables
# Swap the comment from line 38 to line 37 after you have tested the script is working the way you want
#$ModifiedProjectVariables | ConvertTo-Json -depth 10
Invoke-RestMethod -Method PUT "$OctopusURL/api/$($SpaceId)/variables/$($Project.VariableSetId)" -Body ($ModifiedProjectVariablesJSON | ConvertTo-Json -Depth 10) -Headers $Header
This must be the problem section, will be going through this section shortly.
Thank you for getting back to me and confirming. I don’t see anything else obvious as to why you are getting the discrepancy. Maybe you can remove the try/catch and see if you get more information if something is failing on the Invoke-RestMethod -Method PUT.
As much as I wish I could keep working on this with you, we simply don’t have the capacity to debug scripts and typically only provide general guidance. However, I’m happy to continue to assist if you have any additional questions.