Skip to content

Commit 4ffeb83

Browse files
committed
tfexec: Add provided reattach support to all terraform workspace subcommands
1 parent 690e363 commit 4ffeb83

10 files changed

+352
-32
lines changed

tfexec/workspace_delete.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import (
1111
)
1212

1313
type workspaceDeleteConfig struct {
14-
lock bool
15-
lockTimeout string
16-
force bool
14+
lock bool
15+
lockTimeout string
16+
force bool
17+
reattachInfo ReattachInfo
1718
}
1819

1920
var defaultWorkspaceDeleteOptions = workspaceDeleteConfig{
@@ -38,6 +39,10 @@ func (opt *ForceOption) configureWorkspaceDelete(conf *workspaceDeleteConfig) {
3839
conf.force = opt.force
3940
}
4041

42+
func (opt *ReattachOption) configureWorkspaceDelete(conf *workspaceDeleteConfig) {
43+
conf.reattachInfo = opt.info
44+
}
45+
4146
// WorkspaceDelete represents the workspace delete subcommand to the Terraform CLI.
4247
func (tf *Terraform) WorkspaceDelete(ctx context.Context, workspace string, opts ...WorkspaceDeleteCmdOption) error {
4348
cmd, err := tf.workspaceDeleteCmd(ctx, workspace, opts...)
@@ -78,7 +83,16 @@ func (tf *Terraform) workspaceDeleteCmd(ctx context.Context, workspace string, o
7883

7984
args = append(args, workspace)
8085

81-
cmd := tf.buildTerraformCmd(ctx, nil, args...)
86+
mergeEnv := map[string]string{}
87+
if c.reattachInfo != nil {
88+
reattachStr, err := c.reattachInfo.marshalString()
89+
if err != nil {
90+
return nil, err
91+
}
92+
mergeEnv[reattachEnvVar] = reattachStr
93+
}
94+
95+
cmd := tf.buildTerraformCmd(ctx, mergeEnv, args...)
8296

8397
return cmd, nil
8498
}

tfexec/workspace_delete_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,30 @@ func TestWorkspaceDeleteCmd(t *testing.T) {
5050
"workspace-name",
5151
}, nil, workspaceDeleteCmd)
5252
})
53+
54+
t.Run("reattach config", func(t *testing.T) {
55+
workspaceDeleteCmd, err := tf.workspaceDeleteCmd(context.Background(), "workspace-name", Reattach(map[string]ReattachConfig{
56+
"registry.terraform.io/hashicorp/examplecloud": {
57+
Protocol: "grpc",
58+
ProtocolVersion: 6,
59+
Pid: 1234,
60+
Test: true,
61+
Addr: ReattachConfigAddr{
62+
Network: "unix",
63+
String: "/fake_folder/T/plugin123",
64+
},
65+
},
66+
}))
67+
if err != nil {
68+
t.Fatal(err)
69+
}
70+
71+
assertCmd(t, []string{
72+
"workspace", "delete",
73+
"-no-color",
74+
"workspace-name",
75+
}, map[string]string{
76+
"TF_REATTACH_PROVIDERS": `{"registry.terraform.io/hashicorp/examplecloud":{"Protocol":"grpc","ProtocolVersion":6,"Pid":1234,"Test":true,"Addr":{"Network":"unix","String":"/fake_folder/T/plugin123"}}}`,
77+
}, workspaceDeleteCmd)
78+
})
5379
}

tfexec/workspace_list.go

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,35 @@ package tfexec
55

66
import (
77
"context"
8+
"os/exec"
89
"strings"
910
)
1011

12+
type workspaceListConfig struct {
13+
reattachInfo ReattachInfo
14+
}
15+
16+
var defaultWorkspaceListOptions = workspaceListConfig{}
17+
18+
type WorkspaceListOption interface {
19+
configureWorkspaceList(*workspaceListConfig)
20+
}
21+
22+
func (opt *ReattachOption) configureWorkspaceList(conf *workspaceListConfig) {
23+
conf.reattachInfo = opt.info
24+
}
25+
1126
// WorkspaceList represents the workspace list subcommand to the Terraform CLI.
12-
func (tf *Terraform) WorkspaceList(ctx context.Context) ([]string, string, error) {
13-
// TODO: [DIR] param option
14-
wlCmd := tf.buildTerraformCmd(ctx, nil, "workspace", "list", "-no-color")
27+
func (tf *Terraform) WorkspaceList(ctx context.Context, opts ...WorkspaceListOption) ([]string, string, error) {
28+
wlCmd, err := tf.workspaceListCmd(ctx, opts...)
29+
if err != nil {
30+
return nil, "", err
31+
}
1532

1633
var outBuf strings.Builder
1734
wlCmd.Stdout = &outBuf
1835

19-
err := tf.runTerraformCmd(ctx, wlCmd)
36+
err = tf.runTerraformCmd(ctx, wlCmd)
2037
if err != nil {
2138
return nil, "", err
2239
}
@@ -28,6 +45,25 @@ func (tf *Terraform) WorkspaceList(ctx context.Context) ([]string, string, error
2845

2946
const currentWorkspacePrefix = "* "
3047

48+
func (tf *Terraform) workspaceListCmd(ctx context.Context, opts ...WorkspaceListOption) (*exec.Cmd, error) {
49+
c := defaultWorkspaceListOptions
50+
51+
for _, o := range opts {
52+
o.configureWorkspaceList(&c)
53+
}
54+
55+
mergeEnv := map[string]string{}
56+
if c.reattachInfo != nil {
57+
reattachStr, err := c.reattachInfo.marshalString()
58+
if err != nil {
59+
return nil, err
60+
}
61+
mergeEnv[reattachEnvVar] = reattachStr
62+
}
63+
64+
return tf.buildTerraformCmd(ctx, mergeEnv, "workspace", "list", "-no-color"), nil
65+
}
66+
3167
func parseWorkspaceList(stdout string) ([]string, string) {
3268
lines := strings.Split(stdout, "\n")
3369

tfexec/workspace_list_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,61 @@
44
package tfexec
55

66
import (
7+
"context"
78
"fmt"
89
"reflect"
910
"testing"
11+
12+
"github.com/hashicorp/terraform-exec/tfexec/internal/testutil"
1013
)
1114

15+
func TestWorkspaceListCmd(t *testing.T) {
16+
tf, err := NewTerraform(t.TempDir(), tfVersion(t, testutil.Latest_v1))
17+
if err != nil {
18+
t.Fatal(err)
19+
}
20+
21+
// empty env, to avoid environ mismatch in testing
22+
tf.SetEnv(map[string]string{})
23+
24+
t.Run("defaults", func(t *testing.T) {
25+
workspaceListCmd, err := tf.workspaceListCmd(context.Background())
26+
if err != nil {
27+
t.Fatal(err)
28+
}
29+
30+
assertCmd(t, []string{
31+
"workspace", "list",
32+
"-no-color",
33+
}, nil, workspaceListCmd)
34+
})
35+
36+
t.Run("reattach config", func(t *testing.T) {
37+
workspaceListCmd, err := tf.workspaceListCmd(context.Background(), Reattach(map[string]ReattachConfig{
38+
"registry.terraform.io/hashicorp/examplecloud": {
39+
Protocol: "grpc",
40+
ProtocolVersion: 6,
41+
Pid: 1234,
42+
Test: true,
43+
Addr: ReattachConfigAddr{
44+
Network: "unix",
45+
String: "/fake_folder/T/plugin123",
46+
},
47+
},
48+
}))
49+
if err != nil {
50+
t.Fatal(err)
51+
}
52+
53+
assertCmd(t, []string{
54+
"workspace", "list",
55+
"-no-color",
56+
}, map[string]string{
57+
"TF_REATTACH_PROVIDERS": `{"registry.terraform.io/hashicorp/examplecloud":{"Protocol":"grpc","ProtocolVersion":6,"Pid":1234,"Test":true,"Addr":{"Network":"unix","String":"/fake_folder/T/plugin123"}}}`,
58+
}, workspaceListCmd)
59+
})
60+
}
61+
1262
func TestParseWorkspaceList(t *testing.T) {
1363
for i, c := range []struct {
1464
expected []string

tfexec/workspace_new.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import (
1111
)
1212

1313
type workspaceNewConfig struct {
14-
lock bool
15-
lockTimeout string
16-
copyState string
14+
lock bool
15+
lockTimeout string
16+
copyState string
17+
reattachInfo ReattachInfo
1718
}
1819

1920
var defaultWorkspaceNewOptions = workspaceNewConfig{
@@ -38,6 +39,10 @@ func (opt *CopyStateOption) configureWorkspaceNew(conf *workspaceNewConfig) {
3839
conf.copyState = opt.path
3940
}
4041

42+
func (opt *ReattachOption) configureWorkspaceNew(conf *workspaceNewConfig) {
43+
conf.reattachInfo = opt.info
44+
}
45+
4146
// WorkspaceNew represents the workspace new subcommand to the Terraform CLI.
4247
func (tf *Terraform) WorkspaceNew(ctx context.Context, workspace string, opts ...WorkspaceNewCmdOption) error {
4348
cmd, err := tf.workspaceNewCmd(ctx, workspace, opts...)
@@ -48,8 +53,6 @@ func (tf *Terraform) WorkspaceNew(ctx context.Context, workspace string, opts ..
4853
}
4954

5055
func (tf *Terraform) workspaceNewCmd(ctx context.Context, workspace string, opts ...WorkspaceNewCmdOption) (*exec.Cmd, error) {
51-
// TODO: [DIR] param option
52-
5356
c := defaultWorkspaceNewOptions
5457

5558
for _, o := range opts {
@@ -80,7 +83,16 @@ func (tf *Terraform) workspaceNewCmd(ctx context.Context, workspace string, opts
8083

8184
args = append(args, workspace)
8285

83-
cmd := tf.buildTerraformCmd(ctx, nil, args...)
86+
mergeEnv := map[string]string{}
87+
if c.reattachInfo != nil {
88+
reattachStr, err := c.reattachInfo.marshalString()
89+
if err != nil {
90+
return nil, err
91+
}
92+
mergeEnv[reattachEnvVar] = reattachStr
93+
}
94+
95+
cmd := tf.buildTerraformCmd(ctx, mergeEnv, args...)
8496

8597
return cmd, nil
8698
}

tfexec/workspace_new_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,30 @@ func TestWorkspaceNewCmd(t *testing.T) {
5656
"workspace-name",
5757
}, nil, workspaceNewCmd)
5858
})
59+
60+
t.Run("reattach config", func(t *testing.T) {
61+
workspaceNewCmd, err := tf.workspaceNewCmd(context.Background(), "workspace-name", Reattach(map[string]ReattachConfig{
62+
"registry.terraform.io/hashicorp/examplecloud": {
63+
Protocol: "grpc",
64+
ProtocolVersion: 6,
65+
Pid: 1234,
66+
Test: true,
67+
Addr: ReattachConfigAddr{
68+
Network: "unix",
69+
String: "/fake_folder/T/plugin123",
70+
},
71+
},
72+
}))
73+
if err != nil {
74+
t.Fatal(err)
75+
}
76+
77+
assertCmd(t, []string{
78+
"workspace", "new",
79+
"-no-color",
80+
"workspace-name",
81+
}, map[string]string{
82+
"TF_REATTACH_PROVIDERS": `{"registry.terraform.io/hashicorp/examplecloud":{"Protocol":"grpc","ProtocolVersion":6,"Pid":1234,"Test":true,"Addr":{"Network":"unix","String":"/fake_folder/T/plugin123"}}}`,
83+
}, workspaceNewCmd)
84+
})
5985
}

tfexec/workspace_select.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,50 @@
33

44
package tfexec
55

6-
import "context"
6+
import (
7+
"context"
8+
"os/exec"
9+
)
10+
11+
type workspaceSelectConfig struct {
12+
reattachInfo ReattachInfo
13+
}
14+
15+
var defaultWorkspaceSelectOptions = workspaceSelectConfig{}
16+
17+
type WorkspaceSelectOption interface {
18+
configureWorkspaceSelect(*workspaceSelectConfig)
19+
}
20+
21+
func (opt *ReattachOption) configureWorkspaceSelect(conf *workspaceSelectConfig) {
22+
conf.reattachInfo = opt.info
23+
}
724

825
// WorkspaceSelect represents the workspace select subcommand to the Terraform CLI.
9-
func (tf *Terraform) WorkspaceSelect(ctx context.Context, workspace string) error {
10-
// TODO: [DIR] param option
26+
func (tf *Terraform) WorkspaceSelect(ctx context.Context, workspace string, opts ...WorkspaceSelectOption) error {
27+
cmd, err := tf.workspaceSelectCmd(ctx, workspace, opts...)
28+
if err != nil {
29+
return err
30+
}
31+
32+
return tf.runTerraformCmd(ctx, cmd)
33+
}
34+
35+
func (tf *Terraform) workspaceSelectCmd(ctx context.Context, workspace string, opts ...WorkspaceSelectOption) (*exec.Cmd, error) {
36+
c := defaultWorkspaceSelectOptions
37+
38+
for _, o := range opts {
39+
o.configureWorkspaceSelect(&c)
40+
}
41+
42+
mergeEnv := map[string]string{}
43+
if c.reattachInfo != nil {
44+
reattachStr, err := c.reattachInfo.marshalString()
45+
if err != nil {
46+
return nil, err
47+
}
48+
mergeEnv[reattachEnvVar] = reattachStr
49+
}
1150

12-
return tf.runTerraformCmd(ctx, tf.buildTerraformCmd(ctx, nil, "workspace", "select", "-no-color", workspace))
51+
return tf.buildTerraformCmd(ctx, mergeEnv, "workspace", "select", "-no-color", workspace), nil
1352
}

0 commit comments

Comments
 (0)