Skip to content

Commit

Permalink
Merge pull request #65 from silinternational/develop
Browse files Browse the repository at this point in the history
Release 3.3.0 - add remote state consumers
  • Loading branch information
briskt authored Jun 15, 2023
2 parents 4e2572e + 880034b commit 6b65ad8
Show file tree
Hide file tree
Showing 18 changed files with 172 additions and 27 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ Global Flags:
-r, --read-only-mode read-only mode (e.g. "-r")
```

### Workspace Consumers Help
```text
$ tfc-ops workspaces consumers -h
Add to workspace remote state consumers. (Possible future capability: list, replace, delete)
Usage:
tfc-ops workspaces consumers [flags]
Flags:
--consumers string required - List of remote state consumer workspaces, comma-separated
-h, --help help for consumers
-w, --workspace string required - Partial workspace name to search across all workspaces
Global Flags:
-o, --organization string required - Name of Terraform Cloud Organization
-r, --read-only-mode read-only mode (e.g. "-r")
```

### Workspace List Help

Any workspace attribute that can be read by the Terraform API can be retrieved
Expand Down Expand Up @@ -285,6 +303,23 @@ Global Flags:
-r, --read-only-mode read-only mode (e.g. "-r")
```

### Variable Sets List Help
```text
List variable sets applied to a workspace
Usage:
tfc-ops varsets list [flags]
Flags:
-h, --help help for list
-w, --workspace string Name of the Workspace in Terraform Cloud
--workspace-filter string Partial workspace name to search across all workspaces
Global Flags:
-o, --organization string required - Name of Terraform Cloud Organization
-r, --read-only-mode read-only mode (e.g. "-r")
```

## License
tfc-ops is released under the Apache 2.0 license. See
[LICENSE](https://github.com/silinternational/tfc-ops/blob/main/LICENSE)
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

const requiredPrefix = "required - "
Expand Down
12 changes: 5 additions & 7 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmd

import (
"reflect"
"testing"
)

Expand Down Expand Up @@ -33,12 +32,11 @@ func Test_stringMapToSlice(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1 := stringMapToSlice(tt.input)
if !reflect.DeepEqual(got, tt.wantKeys) {
t.Errorf("stringMapToSlice() got = %v, want %v", got, tt.wantKeys)
}
if !reflect.DeepEqual(got1, tt.wantValues) {
t.Errorf("stringMapToSlice() got1 = %v, want %v", got1, tt.wantValues)
keys, values := stringMapToSlice(tt.input)
for i := range keys {
if tt.input[keys[i]] != values[i] {
t.Errorf("stringMapToSlice() got = %v, want %v", values[i], tt.input[keys[i]])
}
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/variablesAdd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (

"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

var variablesAddCmd = &cobra.Command{
Expand Down
2 changes: 1 addition & 1 deletion cmd/variablesDelete.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (

"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

var key string
Expand Down
2 changes: 1 addition & 1 deletion cmd/variablesList.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (

"github.com/spf13/cobra"

api "github.com/silinternational/tfc-ops/lib"
api "github.com/silinternational/tfc-ops/v3/lib"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion cmd/variablesUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion cmd/varsetsApply.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (

"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

var varsetsApplyCmd = &cobra.Command{
Expand Down
2 changes: 1 addition & 1 deletion cmd/varsetsList.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (

"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

var varsetsListCmd = &cobra.Command{
Expand Down
1 change: 1 addition & 0 deletions cmd/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ var workspaceCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(workspaceCmd)
addGlobalFlags(workspaceCmd)
addConsumersCommand(workspaceCmd)
}
2 changes: 1 addition & 1 deletion cmd/workspacesClone.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

"github.com/spf13/cobra"

cloner "github.com/silinternational/tfc-ops/lib"
cloner "github.com/silinternational/tfc-ops/v3/lib"
)

var (
Expand Down
82 changes: 82 additions & 0 deletions cmd/workspacesConsumers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright © 2023 SIL International
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"log"
"strings"

"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/v3/lib"
)

const (
flagConsumers = "consumers"
flagWorkspace = "workspace"
)

func addConsumersCommand(parentCommand *cobra.Command) {
var consumers string
workspaceConsumersCmd := &cobra.Command{
Use: flagConsumers,
Short: "Manage workspace remote state consumers",
Long: `Add to workspace remote state consumers. (Possible future capability: list, replace, delete)`,
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, args []string) {
runWorkspaceConsumers(consumers)
},
}

parentCommand.AddCommand(workspaceConsumersCmd)

workspaceConsumersCmd.Flags().StringVarP(&workspace, flagWorkspace, "w", "",
requiredPrefix+"Partial workspace name to search across all workspaces")

workspaceConsumersCmd.Flags().StringVar(&consumers, flagConsumers, "",
requiredPrefix+"List of remote state consumer workspaces, comma-separated")

requiredFlags := []string{flagConsumers, flagWorkspace}
for _, flag := range requiredFlags {
if err := workspaceConsumersCmd.MarkFlagRequired(flag); err != nil {
panic("MarkFlagRequired failed with error: " + err.Error())
}
}
}

func runWorkspaceConsumers(consumers string) {
workspaceData, err := lib.GetWorkspaceData(organization, workspace)
if err != nil {
log.Fatalln("workspace consumers", err)
}

consumersList := strings.Split(consumers, ",")
consumerIDs := make([]string, len(consumersList))
for i, consumer := range consumersList {
consumerData, err := lib.GetWorkspaceData(organization, consumer)
if err != nil {
log.Fatalln("workspace consumers", err)
}
consumerIDs[i] = consumerData.Data.ID
}

fmt.Printf("Adding to %s: %s", workspace, consumers)
if !readOnlyMode {
if err := lib.AddRemoteStateConsumers(workspaceData.Data.ID, consumerIDs); err != nil {
log.Fatalln("workspace consumers", err)
}
}
}
2 changes: 1 addition & 1 deletion cmd/workspacesList.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

var attributes string
Expand Down
2 changes: 1 addition & 1 deletion cmd/workspacesUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

"github.com/spf13/cobra"

"github.com/silinternational/tfc-ops/lib"
"github.com/silinternational/tfc-ops/v3/lib"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.19
require (
github.com/Jeffail/gabs/v2 v2.7.0
github.com/manifoldco/promptui v0.9.0
github.com/silinternational/tfc-ops v0.0.0-20230615063809-ce4eb07ae327
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.15.0
)
Expand All @@ -25,6 +24,7 @@ require (
github.com/subosito/gotenv v1.4.2 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
Expand All @@ -159,8 +160,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/silinternational/tfc-ops v0.0.0-20230615063809-ce4eb07ae327 h1:FIjLOT+xVLBUFpRoYknW0mRSSX4ceA6aOqqaSVr9fqY=
github.com/silinternational/tfc-ops v0.0.0-20230615063809-ce4eb07ae327/go.mod h1:RMRC4iOQ+/KmPXqbeMOqEKGZQp/15oswaIHVlyoa1kU=
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
Expand Down Expand Up @@ -483,6 +482,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
Expand Down
41 changes: 35 additions & 6 deletions lib/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,12 @@ func getWorkspacePage(url string) (WorkspaceList, error) {
}

func GetWorkspaceData(organization, workspaceName string) (WorkspaceJSON, error) {
if organization == "" {
return WorkspaceJSON{}, fmt.Errorf("GetWorkspaceData: organization is required")
}
if workspaceName == "" {
return WorkspaceJSON{}, fmt.Errorf("GetWorkspaceData: workspace is required")
}
u := NewTfcUrl(fmt.Sprintf(
"/organizations/%s/workspaces/%s",
organization,
Expand Down Expand Up @@ -520,7 +526,7 @@ func AssignTeamAccess(workspaceID string, allTeamData AllTeamWorkspaceData) {
teamData.Relationships.Team.Data.ID,
)

resp := callAPI("POST", url, postData, nil)
resp := callAPI(http.MethodPost, url, postData, nil)
defer resp.Body.Close()
}
return
Expand All @@ -535,7 +541,7 @@ func CreateVariable(organization, workspaceName string, tfVar TFVar) {

postData := GetCreateVariablePayload(organization, workspaceName, tfVar)

resp := callAPI("POST", url, postData, nil)
resp := callAPI(http.MethodPost, url, postData, nil)

defer resp.Body.Close()
// bodyBytes, _ := ioutil.ReadAll(resp.Body)
Expand Down Expand Up @@ -584,7 +590,7 @@ func UpdateVariable(organization, workspaceName, variableID string, tfVar TFVar)

patchData := GetUpdateVariablePayload(organization, workspaceName, variableID, tfVar)

resp := callAPI("PATCH", url, patchData, nil)
resp := callAPI(http.MethodPatch, url, patchData, nil)

defer resp.Body.Close()
// bodyBytes, _ := ioutil.ReadAll(resp.Body)
Expand All @@ -602,7 +608,7 @@ func CreateWorkspace(oc OpsConfig, vcsTokenID string) (string, error) {

postData := GetCreateWorkspacePayload(oc, vcsTokenID)

resp := callAPI("POST", url, postData, nil)
resp := callAPI(http.MethodPost, url, postData, nil)

defer resp.Body.Close()
// bodyBytes, _ := ioutil.ReadAll(resp.Body)
Expand All @@ -626,7 +632,7 @@ func CreateWorkspace2(oc OpsConfig, vcsTokenID string) (Workspace, error) {

postData := GetCreateWorkspacePayload(oc, vcsTokenID)

resp := callAPI("POST", url, postData, nil)
resp := callAPI(http.MethodPost, url, postData, nil)

defer resp.Body.Close()
// bodyBytes, _ := ioutil.ReadAll(resp.Body)
Expand Down Expand Up @@ -981,7 +987,7 @@ func UpdateWorkspace(params WorkspaceUpdateParams) error {
}
for id, name := range foundWs {
url := fmt.Sprintf(baseURL+"/workspaces/%s", id)
resp := callAPI("PATCH", url, postData, nil)
resp := callAPI(http.MethodPatch, url, postData, nil)
bodyBytes, _ := ioutil.ReadAll(resp.Body)
_ = resp.Body.Close()

Expand Down Expand Up @@ -1247,3 +1253,26 @@ func ListWorkspaceVariableSets(workspaceID string) (VariableSetList, error) {

return variableSetList, nil
}

func AddRemoteStateConsumers(workspaceID string, consumerIDs []string) error {
u := NewTfcUrl(fmt.Sprintf("/workspaces/%s/relationships/remote-state-consumers", workspaceID))

data := gabs.New()
_, err := data.ArrayOfSize(len(consumerIDs), "data")
if err != nil {
return fmt.Errorf("ArrayOfSize failed in AddRemoteStateConsumers: %w", err)
}
for i, id := range consumerIDs {
if _, err := data.S("data").SetIndex(map[string]any{
"type": "workspaces",
"id": id,
}, i); err != nil {
return fmt.Errorf("SetIndex failed in AddRemoteStateConsumers: %w", err)
}
}
postData := data.String()

_ = callAPI(http.MethodPost, u.String(), postData, nil)

return nil
}
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

package main

import "github.com/silinternational/tfc-ops/cmd"
import "github.com/silinternational/tfc-ops/v3/cmd"

func main() {
cmd.Execute()
Expand Down

0 comments on commit 6b65ad8

Please sign in to comment.