Giter Site home page Giter Site logo

octopusdeploylabs / spacecloner Goto Github PK

View Code? Open in Web Editor NEW
21.0 4.0 18.0 2.09 MB

A tool to clone/sync a space, project, and/or other items between different spaces in the same Octopus Deploy instances or spaces in different instances.

License: Apache License 2.0

PowerShell 100.00%

spacecloner's Introduction

Space Cloner

PowerShell script to help you clone a space using the Octopus Deploy Restful API.

The cloning process won't cover all use cases

This script was developed internally by the Customer Solutions 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. It won't cover all use cases, and that is by design. It is limited by the fact it is a CLI tool going against a REST API. It doesn't have direct DB acces.

Note: if you have questions on how to use this script please reach out to [email protected]

This repository is licensed under the Apache license. While it covers a variety of use cases, we know it can't cover every last hyper-specific use case. As such, we encourage you to fork it, test it out on an empty space or empty instance, look at the results and modify the script to meet your needs. If you feel your change can benefit the community, please submit a pull request!

Issues and Feature Requests

Issues, bugs, and feature requests are accepted. Please create an issue in this repo and we will address it when we can. We will do our best to accomodate your request, however, this tool was written for specific use cases in mind and it might not match your specific use case. It is licensed 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 Solutions Team at Octopus Deploy plans on keeping this tool 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.

Support

The space cloner is not shy about logging. Everything it does is logged into the log.txt file. We encourage you to review the logs before submitting an issue. Often times it is a missing command line option or a mis-spelling. For example, you might be getting a 400 bad request when trying to create a lifecycle, but that is a result of a missing environment for a phase.

If you do need help, please zip up your log files and send them to [email protected] along with a description on what you are trying to do with the tool.

Pull Requests

Pull Requests are accepted on this repository. See Contributing guidelines.

Tested Octopus Deploy Versions

This script has been tested against the following versions of Octopus Deploy:

  • 2020.1.x
  • 2020.2.x
  • 2020.3.x
  • 2020.4.x
  • 2020.5.x
  • 2020.6.x
  • 2021.1.x
  • 2021.2.x
  • 2021.3.x
  • 2022.1.x
  • 2022.2.x
  • 2022.3.x
  • 2022.4.x

It should work with 3.4.x+ release of Octopus Deploy. The script will run some version checks to ensure it doesn't call the wrong API endpoint. There is a far better chance the script will work using a 2020.x or higher release of Octopus Deploy.

The source instance and the destination instance must be running the same major/minor (2020.1, 2020.2) release. The script will check the version of the source instance and destination instance to ensure this rule is met. It is possible to override that requirement by setting the IgnoreVersionCheckResult to $true, however you run the risk of something not working or cloning correctly.

Just Get Me Going!

This repository contains multiple scripts:

  • CloneSpace.ps1 - The script to clone a set of items from space to another.
  • CloneSpaceProject.ps1 - Will perform a reverse lookup and determine all the items it needs to clone for you.
  • CloneLibraryVariableSet.ps1 - To be used when you want to copy a library variable set in the same space or different spaces.
  • ProjectSyncer.ps1 - Will sync a parent project with 1 to N child projects in the same space on the same instance.
  • CloneTentacleInstance.ps1 - Run this script on deployment targets or workers and it will create a cloned tentacle instance pointing to the destination

The fastest way to get started is to run this command. It will clone everything in a space for you.

CloneSpaceProject.ps1 -SourceOctopusUrl "https://samples.octopus.app" `
    -SourceOctopusApiKey "SOME KEY" `
    -SourceSpaceName "Target - SQL Server" `
    -DestinationOctopusUrl "https://samples.octopus.app" `
    -DestinationOctopusApiKey "My Key" `
    -DestinationSpaceName "Redgate Space" `    
    -ProjectsToClone "all"

Note: The destination space should be created before running the clone scripts.

What If Mode

It can be scary to run a random script off the internet. All the scripts in this repository include a WhatIf parameter. Set that parameter to $true and the scripts will do everything up to the point of making changes to your destination.

All the changes the script will do (or has done) is saved to the ChangeLog.txt file in the root directory.

Use cases

Space Cloner was written to cover the following use cases.

The Space Cloner leverages the Octopus Deploy API. That limits what it can and cannot do.

  • It cannot clone deployments or releases. If it did a POST to copy over a release all the audit records would show the release was created at the time the space cloner ran not the original release date on the source. A POST to the deployment API would perform an actual deployment, not copy over deployment information such as task logs, artifacts, etc.
  • It cannot clone sensitive variables, accounts, or anything else encrypted in the database. Those are never returned in the API anyway.

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.

Unsupported

The use cases for the space cloner is centered around repeately running the cloning script. However, it wasn't intended to keep two instances fully in sync.

It won't clone:

  • Users
  • User Roles
  • Server Settings (folders, JIRA, auth options, etc).
  • Releases, Deployments, Runbook Snapshots, and Runbook Runs.

That is due to a few reasons.

  • Octopus Deploy REST API Limits
    • Sensitive values, such as passwords, are not returned from the REST API.
    • Creating releases and runbook snapshots snapshots the process and variables as it exists today. That means it cannot copy a release created six months ago on the source instance.
    • Task logs, artifacts, and task history cannot be cloned, they are created during a runbook run or deployment.
    • Creating a deployment or runbook run will cause an actual runbook run or deployment to occur.
  • Security Concerns
    • Server Manager or higher permissions are required to create users, user roles and modify server settings. Server managers can also modify any space or project. That means sharing an API key of a user who has that permission, which is not recommended.

How the space cloner works

Please see the how it works page.

How matching works

Please see the how matching works page.

Sensitive variables

Please see the page sensitive variables to see how sensitive variables are handled.

Debugging and logging

Please see the debugging and logging page.

Reference

Please see parameter reference page.

Examples

Please see the example page.

FAQ

Below are questions and answers to common questions we've gotten about this project.

Why was this script created?

The Customer Solutions Team at Octopus Deploy team developed this script. We use it to clone items for our samples instance.

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. it will not clone releases or deployments. See the how it works 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?

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.

For the destination instance, we recommend a user with Space Manager or higher. You can go through and lock down permissions as you see fit, but Space Manager will get you going.

Can I use this in an Octopus Deploy runbook?

Yes! It is a PowerShell script. It calls the APIs, so you should be fine in using it in an Octopus Deploy runbook.

Why doesn't this script create the destination space?

Honestly, it's a security concern. There are two built-in roles that provide the space create permission, System Manager and System Administrator. We recommend using the API key of a service account user when running the script. That service account user would either need to be added to Octopus Managers or Octopus Administrators teams. That user would also have permissions to create users and update other settings on your instance. We want you to feel comfortable using the script as-is. Requiring elevated permissions is a concern, and it isn't something we felt good about asking our users to do.

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 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. This is an intentional decision, as creating anything new might compromise your security on the destination instance.

It doesn't appear like all my variables were cloned, what gives?

The cloner defaults to leaving variables on the destination instance as-is.

On your source space you have the variable Testing.Variable and it is set to Test. On the destination instance that same variable exists and it is set to Super Test. By default the cloner will leave the value on the destination instance as Super Test. To update that value to match the source you will have to set the parameter OverwriteExistingVariables to $true.

The default for the paramter OverwriteExistingVariables is $false.

The space cloner will never overwrite a sensitive variable.

The space cloner matches variables by comparing:

  • Names
  • Sensitive Values vs Non Sensitive Values
  • Environment Scoping
  • Channel Scoping
  • Process Scoping
  • Machine Scoping
  • Step Scoping
  • Role Scoping

If you add a scope, the space cloner will see that as a new variable value and add it. Same is true for changing from sensitive to non-sensitive or vice versa.

What if I have dev and test in one instance and production in another and I have variable scoped to dev

By default the space cloner will skip that variable. The space cloner allows you to throw an error on mismatch, skip unless everything is matched, throw an error unless there is a partial match, skip unless there is a partial match, or ignore the mismatch and clone whatever is there.

You have flexibility with each scoping option.

  • Deployment Process (both runbook and deployment process)
    • Environments
    • Channels
  • Variables (both project and library variable set)
    • Environments
    • Channels
    • Process Owners (deployment process or runbook)
    • Deployment Process Steps
    • Deployment Targets
    • Accounts
    • Certificates
  • Infrastructure (targets and certificates)
    • Environments
    • Tenants

Why doesn't the space cloner clone deployments and releases?

It is a limitation of the space cloner going through the API. You might have releases 1.1.0, 1.2.1, and 1.4.5 all created months apart. If the space cloner were to clone those releases it would snapshot the existing deployment process and variables as they exist today AND set the release creation date to be today. It wouldn't be a true clone.

For deployments, Octopus would do the actual deployment. Which means it would first deploy 1.1.0, then 1.2.1 and then 1.4.5, but each one would use the deployment process and variables as they exist today.

In a nutshell, it would be a big mess and not an accurate representation of your releases or deployments.

spacecloner's People

Contributors

bobjwalker avatar cathalmchale avatar harrisonmeister avatar iguyking avatar jchatmasoctopus avatar justin-walsh avatar mcandersdk avatar mudra-octopus avatar paulgrav avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

spacecloner's Issues

Re-running same script is failing

Re-running same script failing.
"ErrorMessage": "A package reference with the ID 'ca503692-1e2e-453c-a1b0-ed7adecf5aeb' already exists"
are we doing any check if things are already available then don't create?

PowerShell arrays simply being added to

PowerShell arrays are finicky at best. When empty they could be null or plain empty. When a single item, they only return that single item. Part of what the space cloner does is it will add item to internal arrays (such as environment lists) when a new item is created. There is a util function Update-OctopusList that makes adding to those lists much easier. Several of the cloners are not using them, but they should be.

Step templates cannot be cloned when package is deferred with a feedid

In newer versions of Octopus Deploy, a step template a package can be deferred until it is added to a process. Some more recent versions have set a value for feed-id, but include the term NonExisting. The package conversion process is only expecting nulls, so that needs to be accounted for.

Step Template Cloning Fails when Properties.'Octopus.Action.Package.FeedId' parameter exists

When the step template has the following JSON only the Packages[index].FeedId is getting translated. The property Properties.'Octopus.Action.Package.FeedId' is never getting translated.

"Packages":  [
                     {
                         "Name":  "",
                         "Id":  null,
                         "PackageId":  "MyPackage",
                         "FeedId":  "Feeds-1003",
                         "AcquisitionLocation":  "Server",
                         "Properties":  {
                                            "SelectionMode":  "immediate"
                                        }
                     }
                 ],
    "Properties":  {
                       "Octopus.Action.Script.ScriptSource":  "Package",
                       "Octopus.Action.Script.ScriptFileName":  "Octopus.StepTemplate.AWS.ALB.SplashScreenManagement.ps1",
                       "Octopus.Action.Script.ScriptParameters":  "MyParameters",
                       "Octopus.Action.Package.PackageId":  "Octopus.StepTemplate.AWS.ALB.SplashScreenManagement",
                       "Octopus.Action.Package.FeedId":  "feeds-builtin",
                       "Octopus.Action.Package.DownloadOnTentacle":  "False"
                   },

Script Modules Cause Tenant Variable Cloning To Fail

When a tenant is tied to a project with a script module associated with it the variable cloning for that tenant will fail. This is because script modules are stored as library variable sets under the covers. The tenant cloner attempts to convert the variable set id to the destination, it cannot find it and it throws an error and stops the clone.

Spaces in filters cause items not to be picked up

If you set you project filter to be "testing, testing 2" the space cloner will not find "testing 2" even if it exists. Humans are used to adding spaces after commas. The space cloner should account for that.

Cannot call method on null value expression when cloning variables

When cloning variables sometimes a user will run into this error:

InvalidOperation: C:\Users\Administrator\Downloads\SpaceCloner-3.0.4\src\Cloners\VariableSetValuesCloner.ps1:223

Line |

223 | if ($destinationVariable.IsSensitive -eq $false -and $sourceVaria โ€ฆ

 |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 | You cannot call a method on a null-valued expression.

Script Modules Cause Project Cloning Error

If a project has a script module you'll get an error that states something like this:

Critical Message: Unable to find the library variable set (or script module) LibraryVariableSets-241 assigned to project OctoFX - Simple Rollback

Recently a rule was added where all the library variable sets and script modules had to exist, however that rule only checked library variable sets for existence. Library variable sets and script modules are both "variable sets" but are stored in different lists. That project check needs to check both lists before throwing an error.

Join-Path : A positional parameter cannot be found that accepts argument 'Core'.

When trying to execute CloneSpaceProject.ps1, it errors with the below:

Join-Path : A positional parameter cannot be found that accepts argument 'Core'.
At C:\Users\derek\Downloads\SpaceCloner-1.8.2\CloneSpaceProject.ps1:27 char:4

  • . (Join-Path $PSScriptRoot "src" "Core" "Logging.ps1")
+ CategoryInfo          : InvalidArgument: (:) [Join-Path], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.JoinPathCommand

Command run with values changed

.\CloneSpaceProject.ps1 -SourceOctopusUrl "URLOFSPACE" -SourceOctopusApiKey "SECUREAPIKEY"
-SourceSpaceName "SpaceName -DestinationOctopusUrl "DestinationURL"
-DestinationOctopusApiKey "SECUREAPIKEY" -DestinationSpaceName "Default"
-ProjectsToClone "all"

This issue has been confirmed by additional users.

Deploy A Release Steps not translating correctly

If the project is leveraging the Deploy a Release step it needs to translate the project ids currently being stored in the package ids correctly. Right now it is not and a missing resource error is appearing for any cloned project.

What if fails if there is a community step template that needs to be cloned

The what if fails when there is a community step template to clone. This is due to how community step templates are installed into Octopus. Rather than posting an body to the API, the API expects an empty body POST call to the endpoint ommunityactiontemplates/$($communityStepTemplate.Id)/installation/$($destinationData.SpaceId). This caused a problem with the what-if command as it is expected that when doing a POST or a PUT the body will have a value.

Invalid Operation when running CloneSpace.ps1

An error with version 3.0.0 when running CloneSpace.ps1

Command line call is

./CloneSpace.ps1 -SourceOctopusUrl "https://octopus.mysite.com/" -SourceOctopusApiKey "API-12345678" -SourceSpaceName "Development" -DestinationOctopusUrl "https://octopus.mysite.com" -DestinationOctopusApiKey "API-12345678" -DestinationSpaceName "NextApp" -WorkerPoolsToClone "Prod Linux Docker Workers"    
InvalidOperation: C:\[...]\SpaceCloner\src\Core\Util.ps1:663                                                                                                             Line |                                                                                                                   663 |      $lowerParameterValue = $parameterValue.ToLower().Trim()                                                          |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                                          | You cannot call a method on a null-valued expression.                                                                                                                                 

API error messages are not super useful

When an error occurs calling the API the space cloner will log the exception to the log, but not write it out on the screen for the user to read through. This requires the user to go through the log and find where the exception occurs.

In addition, the script throws an exception instead of writing a useful error message and stopping.

Project Variable Templates are not getting cloned when updating an existing project

The process to clone project variable templates only runs when a new project is created. Pre-existing projects will never have their project variable template list. This is due to a different code branch getting run when updating an existing project because of release versioning rules. A new project is basically a blind clone, while an existing project has specific properties copied over from the source.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.