From 0fc3f2258fbfa58e3a1c2b8b48707b1e05b12a6b Mon Sep 17 00:00:00 2001 From: octopusbob Date: Fri, 18 Sep 2020 09:34:16 -0500 Subject: [PATCH] Fixed version checker, the clonespaceproject script now has explicit default variable settings, added the ability to skip the version check. --- CloneSpace.ps1 | 49 ++++++++++++++-- CloneSpaceProject.ps1 | 65 ++++++++++++++++++++- README.md | 28 ++++----- docs/CloneSpaceParameterReference.md | 6 +- docs/CloneSpaceProjectParameterReference.md | 7 ++- 5 files changed, 131 insertions(+), 24 deletions(-) diff --git a/CloneSpace.ps1 b/CloneSpace.ps1 index 665f0d0..8175631 100644 --- a/CloneSpace.ps1 +++ b/CloneSpace.ps1 @@ -33,7 +33,9 @@ param ( $CloneTeamUserRoleScoping, $CloneProjectChannelRules, $CloneProjectVersioningReleaseCreationSettings, - $CloneProjectDeploymentProcess + $CloneProjectDeploymentProcess, + $IgnoreVersionCheckResult, + $SkipPausingWhenIgnoringVersionCheckResult ) . ($PSScriptRoot + ".\src\Core\Logging.ps1") @@ -124,6 +126,16 @@ if ($null -eq $RunbooksToClone) $RunbooksToClone = "all" } +if ($null -eq $IgnoreVersionCheckResult) +{ + $IgnoreVersionCheckResult = $false +} + +if ($null -eq $SkipPausingWhenIgnoringVersionCheckResult) +{ + $SkipPausingWhenIgnoringVersionCheckResult = $false +} + $CloneScriptOptions = @{ EnvironmentsToClone = $EnvironmentsToClone; WorkerPoolsToClone = $WorkerPoolsToClone; @@ -159,9 +171,37 @@ $CloneScriptOptions = @{ $sourceData = Get-OctopusData -octopusUrl $SourceOctopusUrl -octopusApiKey $SourceOctopusApiKey -spaceName $SourceSpaceName $destinationData = Get-OctopusData -octopusUrl $DestinationOctopusUrl -octopusApiKey $DestinationOctopusApiKey -spaceName $DestinationSpaceName -if ($sourceData.MajorVersion -ne $destinationData.MajorVersion -or $sourceData.MinorVersion -ne $sourceData.MinorVersion) +if ($sourceData.MajorVersion -ne $destinationData.MajorVersion -or $sourceData.MinorVersion -ne $destinationData.MinorVersion) { - Throw "The source $($sourceData.OctopusUrl) is on version $($sourceData.MajorVersion).$($sourceData.MinorVersion).x while the destination $($destinationData.OctopusUrl) is on version $($destinationData.MajorVersion).$($DestinationData.MinorVersion).x. Nothing good will come of this clone. Please upgrade the source or destination to match and try again." + Write-OctopusCritical "The source $($sourceData.OctopusUrl) is on version $($sourceData.MajorVersion).$($sourceData.MinorVersion).x while the destination $($destinationData.OctopusUrl) is on version $($destinationData.MajorVersion).$($DestinationData.MinorVersion).x." + + if ($IgnoreVersionCheckResult -eq $false) + { + Write-OctopusCritical "Nothing good will come of this clone. Please upgrade the source or destination to match and try again. You can ignore this warning by setting the argument IgnoreVersionCheckResult to $true" + Exit 1 + } + + Write-OctopusCritical "You have chosen to ignore that difference. This run may work or it may not work." + + if ($SkipPausingWhenIgnoringVersionCheckResult -eq $false) + { + Write-OctopusCritical "I am pausing for 20 seconds to give you a chance to cancel. If you cloning to a production instance it is highly recommended you cancel this. You can skip this pausing by setting the argument SkipPausingWhenIgnoringVersionCheckResult to $true" + $versionCheckCountDown = 20 + + while ($versionCheckCountDown -gt 0) + { + Write-OctopusCritical "Seconds left: $versionCheckCountDown" + Start-Sleep -Seconds 1 + $versionCheckCountDown -= 1 + } + } + else + { + Write-OctopusCritical "Someone ate their YOLO-flakes today and elected to skip the pause of the version check as well." + } + + + Write-OctopusCritical "Alright, this is a bold choice, I like it. Proceeding." } if ($sourceData.OctopusUrl -eq $destinationData.OctopusUrl -and $SourceSpaceName -eq $DestinationSpaceName) @@ -180,7 +220,8 @@ if ($sourceData.OctopusUrl -eq $destinationData.OctopusUrl -and $SourceSpaceName if ($canProceed -eq $false) { - throw "Invalid parameters detected. Please check log and correct them." + Write-OctopusCritical "Invalid parameters detected. Please check log and correct them." + Exit 1 } } diff --git a/CloneSpaceProject.ps1 b/CloneSpaceProject.ps1 index 0a5367d..0d084eb 100644 --- a/CloneSpaceProject.ps1 +++ b/CloneSpaceProject.ps1 @@ -18,7 +18,9 @@ param ( $CloneTeamUserRoleScoping, $CloneProjectChannelRules, $CloneProjectVersioningReleaseCreationSettings, - $CloneProjectDeploymentProcess + $CloneProjectDeploymentProcess, + $IgnoreVersionCheckResult, + $SkipPausingWhenIgnoringVersionCheckResult ) $ErrorActionPreference = "Stop" @@ -32,6 +34,61 @@ $ErrorActionPreference = "Stop" $sourceData = Get-OctopusData -octopusUrl $SourceOctopusUrl -octopusApiKey $SourceOctopusApiKey -spaceName $SourceSpaceName +if ($null -eq $CloneProjectRunbooks) +{ + $CloneProjectRunbooks = $true +} + +if ($null -eq $CloneTeamUserRoleScoping) +{ + $CloneTeamUserRoleScoping = $false +} + +if ($null -eq $CloneProjectChannelRules) +{ + $CloneProjectChannelRules = $false +} + +if ($null -eq $CloneProjectVersioningReleaseCreationSettings) +{ + $CloneProjectVersioningReleaseCreationSettings = $true +} + +if ($null -eq $CloneProjectDeploymentProcess) +{ + $CloneProjectDeploymentProcess = $true +} + +if ($null -eq $OverwriteExistingVariables) +{ + $OverwriteExistingVariables = $false +} + +if ($null -eq $AddAdditionalVariableValuesOnExistingVariableSets) +{ + $AddAdditionalVariableValuesOnExistingVariableSets = $false +} + +if ($null -eq $OverwriteExistingCustomStepTemplates) +{ + $OverwriteExistingCustomStepTemplates = $false +} + +if ($null -eq $OverwriteExistingLifecyclesPhases) +{ + $OverwriteExistingLifecyclesPhases = $false +} + +if ($null -eq $IgnoreVersionCheckResult) +{ + $IgnoreVersionCheckResult = $false +} + +if ($null -eq $SkipPausingWhenIgnoringVersionCheckResult) +{ + $SkipPausingWhenIgnoringVersionCheckResult = $false +} + $cloneSpaceCommandLineOptions = @{ EnvironmentsToClone = $null; WorkerPoolsToClone = $null; @@ -594,6 +651,8 @@ Write-OctopusSuccess " -CloneProjectChannelRules $CloneProjectChannelRules" Write-OctopusSuccess " -CloneProjectRunbooks $CloneProjectRunbooks" Write-OctopusSuccess " -CloneProjectVersioningReleaseCreationSettings $CloneProjectVersioningReleaseCreationSettings" Write-OctopusSuccess " -CloneProjectDeploymentProcess $CloneProjectDeploymentProcess" +Write-OctopusSuccess " -IgnoreVersionCheckResult $IgnoreVersionCheckResult" +Write-OctopusSuccess " -SkipPausingWhenIgnoringVersionCheckResult $SkipPausingWhenIgnoringVersionCheckResult" $cloneSpaceScript = "$PSScriptRoot\CloneSpace.ps1" & $cloneSpaceScript ` @@ -627,5 +686,7 @@ $cloneSpaceScript = "$PSScriptRoot\CloneSpace.ps1" -CloneProjectChannelRules "$CloneProjectChannelRules" ` -CloneProjectRunbooks "$CloneProjectRunbooks" ` -CloneProjectVersioningReleaseCreationSettings "$CloneProjectVersioningReleaseCreationSettings" ` - -CloneProjectDeploymentProcess "$CloneProjectDeploymentProcess" + -CloneProjectDeploymentProcess "$CloneProjectDeploymentProcess" ` + -IgnoreVersionCheckResult "$IgnoreVersionCheckResult" ` + -SkipPausingWhenIgnoringVersionCheckResult "$SkipPausingWhenIgnoringVersionCheckResult" diff --git a/README.md b/README.md index 763743d..0660a3f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ PowerShell script to help you clone a space using the Octopus Deploy Restful API. # This cloning process is provided as is -This script was developed internally for the Customer Success team at Octopus Deploy to solve specific use cases we encounter each day. We are sharing this script to help other users of Octopus Deploy. To cover as many use cases as we run into as possible, the script has a set of generic comparisons in place. It matches by name, order is tracked via a simple index, etc. We work in Octopus all day every day. As such, we are okay with a script that accomplishes 80-90% of a clone, and then spending a bit of time doing some manual work. +This script was developed internally for the Octopus Advisory Team at Octopus Deploy to solve specific use cases we encounter each day. We are sharing this script to help other users of Octopus Deploy. To cover as many use cases as we run into as possible, the script has a set of generic comparisons in place. It matches by name, order is tracked via a simple index, etc. We work in Octopus all day every day. As such, we are okay with a script that accomplishes 80-90% of a clone, and then spending a bit of time doing some manual work. > **Note:** Owing to the "as is" nature of this script, **Octopus Deploy does not provide any support for this via our support channels.** @@ -14,7 +14,7 @@ As such, we encourage you to fork it, test it out on an empty space or empty ins Issues, bugs, and feature requests will not be accepted. As stated earlier, this repository is [licensed](license) under the Apache license. You are free to fork the repository and fix any issues or add any features you think is useful. -The Customer Success team plans on keeping this script up to date with the latest version of Octopus Deploy. If you do fork this repo, you might want to keep up to date on the latest changes. +The Octopus Advisory Team plans on keeping this script up to date with the latest version of Octopus Deploy. If you do fork this repo, you might want to keep up to date on the latest changes. ## Pull Requests @@ -36,8 +36,9 @@ The source instance and the destination instance **must** be running the same ma This repository contains two scripts: -- [CloneSpace.ps1](CloneSpaceParameterReference.md) - The script to clone a set of items from space to another. -- [CloneSpaceProject.ps1](CloneSpaceProjectParameterReference.md) - Will perform a reverse lookup and determine all the items it needs to clone for you. +- [CloneSpace.ps1](docs/CloneSpaceParameterReference.md) - The script to clone a set of items from space to another. +- [CloneSpaceProject.ps1](docs/CloneSpaceProjectParameterReference.md) - Will perform a reverse lookup and determine all the items it needs to clone for you. +- [ProjectSyncer.ps1](docs/ProjectSyncerParameterReference) - Will sync a parent project with 1 to N child projects. The fastest way to get started is to run this command. It will clone everything in a space for you. @@ -50,11 +51,10 @@ CloneSpaceProject.ps1 -SourceOctopusUrl "https://samples.octopus.app" ` -DestinationSpaceName "Redgate Space" ` -ProjectsToClone "all" ``` -Note: The destination space should be created before running the clone scripts. +**Note**: The destination space should be created before running the clone scripts. # Use cases - -This script was written for the following use cases. +This script was written to cover the following use cases. - As a user, I want to split my one massive default space into [multiple spaces on the same instance](docs/UseCase-BreakUpSpace.md). - As a user, I have two Octopus Deploy instances. One for dev/test deployments. Another for staging/prod deployments. I have the [same set of projects I want to keep in sync](docs/UseCase-KeepInstancesInSync.md). @@ -63,7 +63,6 @@ This script was written for the following use cases. - As a user, I would like to copy my projects from [self-hosted Octopus to Octopus Cloud](docs/UseCase-MigrateFromSelfHostedToCloud.md). ## Possible but not recommended - - As a user, I want to merge multiple Octopus Deploy instances into the same space on a new instance. That scenario, merging multiple disparate instances into one massive space, is not recommended. The chance of overwriting something meaningful is very high. Just like steering a car with your knees, while possible, it is not recommended. # How the space cloner workers @@ -85,19 +84,21 @@ Please see the [example page](docs/Examples.md). Below are questions and answers to common questions we've gotten about this project. ### Why was this script created? -The Customer Success at Octopus Deploy team developed this script. We use it to clone items for our [samples instance](https://samples.octopus.app). +The Octopus Advisory Team at Octopus Deploy team developed this script. We use it to clone items for our [samples instance](https://samples.octopus.app). ### Can I use this to migrate from self-hosted to the cloud? -Yes. However, this script is not a full migration. It will jump-start your migration. This script hits the API, meaning it won't have access to your sensitive variables. See the [how it works](docs/HowItWorks.md) page for details on what it will and won't clone. +Yes. However, this script is not a full migration. It will jump-start your migration. This script hits the API, meaning it won't have access to your sensitive variables. it will not clone releases or deployments. See the [how it works](docs/HowItWorks.md) page for details on what it will and won't clone. ### Is this the space migration / self-hosted to Octopus Cloud migrator tool that has been teased in the past? No. It was designed for specific use cases, and the limits placed on it were intentional. For example, it can't access your Master Key, and without that, it cannot decrypt your sensitive data. It should get you 80-90% of the way there. You are free to fork this repo to modify the scripts to help get you another 5% of the way there. ### Can I use this script to migrate from 2018.10 to 2020.2? -No. The script compares the major and minor versions of the source and destination. +By default, no. The script compares the major and minor versions of the source and destination. **Unless the source and destination [major].[minor] versions are the same; the script will not proceed.** +That can be overridden by setting the parameter `IgnoreVersionCheckResult` to `true`. That should only be set to `true` when cloning to test spaces or test instances. Setting it to `true` when cloning to production instances is asking for trouble. This parameter was added to make it easier for the Octopus Advisory Team to set up test instances of Octopus Deploy with EAP versions. + ### What permissions should the users tied to the API keys have? For the source instance, a user with read-only permissions to all objects copied is required. It will never write anything back to the source. @@ -112,11 +113,10 @@ Honestly, it's a security concern. There are two built-in roles that provide th Yes, you can create a custom role and assign the service account user to that role. The goal of this script is it should "just work" with a minimal amount of configuration on your end. Once you start diving into permissions and custom roles, it is going to be much harder to get working. ### Does the script clone users, teams, and roles? - This script does _**NOT**_ clone users, roles, or system teams. You can tell it to clone space-specific teams only. -When it attempts to set up scoping for a team, it will see if the role exists on the destination; if the role does not exist on the destination instance the scoping will be skipped. +When it attempts to set up scoping for a team, it will skip any missing roles on the destination. Teams that are created have the external groups cleared. -In other words, the clone team functionality will only assign existing users and roles to space teams. It will not attempt to create anything new, which might compromise your security. +In other words, the clone team functionality will only assign existing users and roles to space teams. This is an intentional decision, as creating anything new might compromise your security on the destination instance. diff --git a/docs/CloneSpaceParameterReference.md b/docs/CloneSpaceParameterReference.md index 29eabf1..c621ef0 100644 --- a/docs/CloneSpaceParameterReference.md +++ b/docs/CloneSpaceParameterReference.md @@ -55,10 +55,12 @@ The values for these options are either `True`, `False` or `null`. Null will ca - `OverwriteExistingVariables` - Indicates if all existing variables (except sensitive variables) should be overwritten. The default is `false`. - `CloneProjectChannelRules` - Indicates if the project channel rules should be cloned and overwrite existing channel rules. The default is `false`. - `CloneProjectDeploymentProcess` - Indicates if the project deployment process should be cloned. Set this to `false` to only clone project runbooks. The default is `true`. -- `CloneProjectRunbooks` - Indicates if project runbooks should be cloned. Set this to `false` to only clone the project deployment process. The defaults is `true`. +- `CloneProjectRunbooks` - Indicates if project runbooks should be cloned. Set this to `false` to only clone the project deployment process. The default is `true`. - `CloneProjectVersioningReleaseCreationSettings` - Indicates if the release versioning strategy and release creation strategy should be cloned. The default is `false`. - `CloneTeamUserRoleScoping` - Indicates if the space teams should have their scoping cloned. Will use the same teams based on parameter `SpaceTeamsToClone`. The default is`false`. -- `AddAdditionalVariableValuesOnExistingVariableSets` - Indicates a variable on the destination should only have one value. You would have multiple values if you were scoping variables. The defaults is `false`. +- `AddAdditionalVariableValuesOnExistingVariableSets` - Indicates a variable on the destination should only have one value. You would have multiple values if you were scoping variables. The default is `false`. +- `IgnoreVersionCheckResult` - Indicates if the script should ignore version checks rules and proceed with the clone. This should only be used for cloning to test instances of Octopus Deploy. The default is `false`. +- `SkipPausingWhenIgnoringVersionCheckResult` - When `IgnoreVersionCheckResult` is set to true the script will pause for 20 seconds when it detects a difference to let you cancel. You can skip that check by setting this to `true`. This should only be used for cloning to test instances of Octopus Deploy. The default is `false`. ## AddAdditionalVariableValuesOnExistingVariableSets further detail diff --git a/docs/CloneSpaceProjectParameterReference.md b/docs/CloneSpaceProjectParameterReference.md index a71a3c7..96ed28a 100644 --- a/docs/CloneSpaceProjectParameterReference.md +++ b/docs/CloneSpaceProjectParameterReference.md @@ -48,9 +48,12 @@ The values for these options are either `True`, `False` or `null`. Null will ca - `OverwriteExistingVariables` - Indicates if all existing variables (except sensitive variables) should be overwritten. The default is `false`. - `CloneProjectChannelRules` - Indicates if the project channel rules should be cloned and overwrite existing channel rules. The default is `false`. - `CloneProjectDeploymentProcess` - Indicates if the project deployment process should be cloned. Set this to `false` to only clone project runbooks. The default is `true`. -- `CloneProjectRunbooks` - Indicates if project runbooks should be cloned. Set this to `false` to only clone the project deployment process. The defaults is `true`. +- `CloneProjectRunbooks` - Indicates if project runbooks should be cloned. Set this to `false` to only clone the project deployment process. The default is `true`. +- `CloneProjectVersioningReleaseCreationSettings` - Indicates if the same versioning rules will be applied to the project. The default is `false`. - `CloneTeamUserRoleScoping` - Indicates if the space teams should have their scoping cloned. Will use the same teams based on parameter `SpaceTeamsToClone`. The default is`false`. -- `AddAdditionalVariableValuesOnExistingVariableSets` - Indicates a variable on the destination should only have one value. You would have multiple values if you were scoping variables. The defaults is `false`. +- `AddAdditionalVariableValuesOnExistingVariableSets` - Indicates a variable on the destination should only have one value. You would have multiple values if you were scoping variables. The default is `false`. +- `IgnoreVersionCheckResult` - Indicates if the script should ignore version checks rules and proceed with the clone. This should only be used for cloning to test instances of Octopus Deploy. The default is `false`. +- `SkipPausingWhenIgnoringVersionCheckResult` - When `IgnoreVersionCheckResult` is set to true the script will pause for 20 seconds when it detects a difference to let you cancel. You can skip that check by setting this to `true`. This should only be used for cloning to test instances of Octopus Deploy. The default is `false`. ## AddAdditionalVariableValuesOnExistingVariableSets further detail