Skip to content

Commit

Permalink
added copy command
Browse files Browse the repository at this point in the history
  • Loading branch information
eRaMvn committed Jan 2, 2021
1 parent eab006c commit 4a1772f
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 14 deletions.
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ go mod tidy
go build
```

Or you can grab one of the executables under `Releases`

## Usage

There are two main commands:
There are three main commands:

- update: To create/update variables in Terraform Cloud
- delete: To delete variables in Terraform Cloud
- copy: To copy variables from one workspace to another workspace irrespective of the organization in Terraform Cloud

By default, the tool assumes that the variable will be environment variable. It will not marked as sensitive or as HCL value.

Expand Down Expand Up @@ -137,6 +140,31 @@ tfc-helper delete --var some_variable
tfc-helper delete -a
`

**8. Copy all variables from workspace test1 to workspace test2 but ignore the variables that have the same name in test2. Both workspaces are in the same organization:**

The organization have already been set with environment variable TF_CLOUD_ORG_NAME
`
tfc-help copy --src-ws test1 --dst-ws test2
`

OR

`
tfc-help copy --src-ws test1 --src-org org1 --dst-ws test2
`

OR If the source workspace and source organization have already been set with environment variables, but the destination organization is different. We can do:

`
tfc-helper copy --dst-ws test2 --dst-org org2
`

**9. Copy all variables from workspace test1 to workspace test2 but overwrite the variables that have the same name in test2. Other variables from test1 will still be copied over to test2:**

`
tfc-help copy --src-ws test1 --dst-ws test2 -r
`

## TODO:

- Develop test cases
Expand Down
120 changes: 120 additions & 0 deletions cmd/copy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package cmd

import (
"fmt"
"os"
"sync"
"tfc-helper/helper"

"github.com/spf13/cobra"
)

// copyCmd represents the copy command
var copyCmd = &cobra.Command{
Use: "copy",
Short: "Command to duplicate configuration between workspaces",
Long: `Command to copy all variables existed in a workspace to another workspace. The destination workspace
can be the same organization or in a different organization
Examples:
- Copy all variables from workspace test1 to workspace test2 but ignore the variables that have the same name in test2. Both workspaces are in the same organization
tfc-help copy --src-ws test1 --dst-ws test2
OR if the source workspace and source organization have already been set with environment variables. We can do:
tfc-helper copy --dst-ws test2
- Copy all variables from workspace test1 to workspace test2 but overwrite the variables that have the same name in test2:
tfc-help copy --src-ws test1 --dst-ws test2 -r`,
Run: func(cmd *cobra.Command, args []string) {
// Try to get value from command line first then try the environment variable
srcOrgName, _ := cmd.Flags().GetString("src-org")
if srcOrgName == "" {
// Try to get organization value from environment variable
srcOrgName = os.Getenv(OrgVar)
if srcOrgName == "" {
fmt.Println("Please set the source organization with the --src-org flag or use TF_CLOUD_ORG_NAME environment variable")
os.Exit(1)
}
}

dstOrgName, _ := cmd.Flags().GetString("dst-org")

// If dstOrgName is empty, we assume that the organization remains the same
if dstOrgName == "" {
dstOrgName = srcOrgName
}

// Try to get value from command line first then try the environment variable
srcWsName, _ := cmd.Flags().GetString("src-ws")
if srcWsName == "" {
// Try to get workspace value from environment variable
srcWsName = os.Getenv(WorkspaceVar)
if srcWsName == "" {
fmt.Println("Please set the source workspace with the --src-ws flag or use TF_CLOUD_WS_NAME environment variable")
os.Exit(1)
}
}

dstWsName, _ := cmd.Flags().GetString("dst-ws")
shouldReplace, _ := cmd.Flags().GetBool("replace")

srcWorkspaceID := helper.GetWorkspaceID(srcOrgName, srcWsName)
dstWorkspaceID := helper.GetWorkspaceID(dstOrgName, dstWsName)

variablesInDstWs := helper.ListAllVariables(dstWorkspaceID)

var wg sync.WaitGroup
for _, variable := range helper.ListAllVariables(srcWorkspaceID) {
// Check if replace flag is set
if shouldReplace {
wg.Add(1)
newVariable := helper.NewVariable{
ID: "",
Key: variable.Key,
Value: variable.Value,
Description: variable.Description,
Category: variable.Category,
HCL: variable.HCL,
Sensitive: variable.Sensitive,
}
// If a variable already exists, delete it and create a new one
if helper.CheckIfVariableExistInWs(variablesInDstWs, variable.Key) {
// Try to get the variable ID
variableToReplace, _ := helper.GetVar(dstWorkspaceID, variable.Key)
newVariable.ID = variableToReplace.ID
go helper.RecreateVariable(dstWorkspaceID, newVariable, &wg)
} else {
go helper.CreateVariable(dstWorkspaceID, newVariable, &wg)
}
} else {
// If a variable already exists -- having the same name, skip
if helper.CheckIfVariableExistInWs(variablesInDstWs, variable.Key) {
continue
} else {
wg.Add(1)
newVariable := helper.NewVariable{
ID: "",
Key: variable.Key,
Value: variable.Value,
Description: variable.Description,
Category: variable.Category,
HCL: variable.HCL,
Sensitive: variable.Sensitive,
}
go helper.CreateVariable(dstWorkspaceID, newVariable, &wg)
}
}
}
wg.Wait()
},
}

func init() {
rootCmd.AddCommand(copyCmd)
copyCmd.PersistentFlags().String("src-org", "", "Specify the source organization")
copyCmd.PersistentFlags().String("dst-org", "", "Specify the destination organization")
copyCmd.PersistentFlags().String("src-ws", "", "Specify the source workspace")
copyCmd.PersistentFlags().String("dst-ws", "", "Specify the destination workspace")
_ = copyCmd.MarkPersistentFlagRequired("dst-ws")
copyCmd.PersistentFlags().BoolP("replace", "r", false, "Specify whether to overwrite the existing variables or not")
}
23 changes: 10 additions & 13 deletions cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,18 @@ tfc-help update --env -r -w ws-K33Rp -o big-corp
- Create/Update only new variables found in the current workspace:
tfc-help update --env -w ws-K33Rp -o big-corp`,
Run: func(cmd *cobra.Command, args []string) {
// Try to get workspace value from environment variable
wsName := os.Getenv(WorkspaceVar)
if wsName != "" {
workspaceName = wsName
} else {
workspaceName, _ = cmd.Flags().GetString("workspace")
// Try to get value from command line first then try the environment variable
workspaceName, _ = cmd.Flags().GetString("workspace")
if workspaceName == "" {
// Try to get workspace value from environment variable
workspaceName = os.Getenv(WorkspaceVar)
}

// Try to get organization value from environment variable
orgName := os.Getenv(OrgVar)

if orgName != "" {
organizationName = orgName
} else {
organizationName, _ = cmd.Flags().GetString("organization")
// Try to get value from command line first then try the environment variable
organizationName, _ = cmd.Flags().GetString("organization")
if organizationName == "" {
// Try to get organization value from environment variable
organizationName = os.Getenv(OrgVar)
}

keyPairs, _ := cmd.Flags().GetStringSlice("var")
Expand Down
10 changes: 10 additions & 0 deletions helper/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ func ListAllVariables(workspaceID string) []*tfe.Variable {
return variableList.Items
}

// CheckIfVariableExistInWs checks if a variable is in a workspace or not
func CheckIfVariableExistInWs(wsVariableList []*tfe.Variable, variableName string) bool {
for _, variable := range wsVariableList {
if variable.Key == variableName {
return true
}
}
return false
}

// GetVar gets the variable that matches the variable name in the list of variable
func GetVar(workspaceID string, varName string) (variable *tfe.Variable, err error) {
for _, variable := range ListAllVariables(workspaceID) {
Expand Down

0 comments on commit 4a1772f

Please sign in to comment.