Skip to content

Commit

Permalink
add supports for cmd: terraform add (#209)
Browse files Browse the repository at this point in the history
* add supports for cmd: terraform add

* refine per review comments

* tiny fix

* use strings.Builder as writer as we returns string
  • Loading branch information
magodo authored Aug 12, 2021
1 parent 9792c20 commit 38de6f4
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 6 deletions.
101 changes: 101 additions & 0 deletions tfexec/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package tfexec

import (
"context"
"fmt"
"os/exec"
"strconv"
"strings"
)

type addConfig struct {
fromState bool
out string
includeOptional bool
provider string
reattachInfo ReattachInfo
}

var defaultAddOptions = addConfig{}

type AddOption interface {
configureAdd(*addConfig)
}

func (opt *FromStateOption) configureAdd(conf *addConfig) {
conf.fromState = opt.fromState
}

func (opt *OutOption) configureAdd(conf *addConfig) {
conf.out = opt.path
}

func (opt *IncludeOptionalOption) configureAdd(conf *addConfig) {
conf.includeOptional = opt.includeOptional
}

func (opt *ProviderOption) configureAdd(conf *addConfig) {
conf.provider = opt.provider
}

func (opt *ReattachOption) configureAdd(conf *addConfig) {
conf.reattachInfo = opt.info
}

// Add represents the `terraform add` subcommand (added in 1.1.0).
//
// Note that this function signature and behaviour is subject
// to breaking changes including removal of that function
// until final 1.1.0 Terraform version (with this command) is released.
func (tf *Terraform) Add(ctx context.Context, address string, opts ...AddOption) (string, error) {
cmd, err := tf.addCmd(ctx, address, opts...)
if err != nil {
return "", err
}

var outBuf strings.Builder
cmd.Stdout = mergeWriters(cmd.Stdout, &outBuf)

if err := tf.runTerraformCmd(ctx, cmd); err != nil {
return "", err
}

return outBuf.String(), nil
}

func (tf *Terraform) addCmd(ctx context.Context, address string, opts ...AddOption) (*exec.Cmd, error) {
err := tf.compatible(ctx, tf1_1_0, nil)
if err != nil {
return nil, fmt.Errorf("terraform add was added in 1.1.0: %w", err)
}

c := defaultAddOptions

for _, o := range opts {
o.configureAdd(&c)
}

args := []string{"add"}

args = append(args, "-from-state="+strconv.FormatBool(c.fromState))
if c.out != "" {
args = append(args, "-out="+c.out)
}
args = append(args, "-optional="+strconv.FormatBool(c.includeOptional))
if c.provider != "" {
args = append(args, "-provider="+c.provider)
}

args = append(args, address)

mergeEnv := map[string]string{}
if c.reattachInfo != nil {
reattachStr, err := c.reattachInfo.marshalString()
if err != nil {
return nil, err
}
mergeEnv[reattachEnvVar] = reattachStr
}

return tf.buildTerraformCmd(ctx, mergeEnv, args...), nil
}
56 changes: 56 additions & 0 deletions tfexec/add_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package tfexec

import (
"context"
"testing"

"github.com/hashicorp/terraform-exec/tfexec/internal/testutil"
)

func TestAddCmd(t *testing.T) {
td := testTempDir(t)

tf, err := NewTerraform(td, tfVersion(t, testutil.Latest_v1_1))
if err != nil {
t.Fatal(err)
}

// empty env, to avoid environ mismatch in testing
tf.SetEnv(map[string]string{})

t.Run("default", func(t *testing.T) {
addCmd, err := tf.addCmd(context.Background(), "my-addr")
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"add",
"-from-state=false",
"-optional=false",
"my-addr",
}, nil, addCmd)
})

t.Run("override-default", func(t *testing.T) {
addCmd, err := tf.addCmd(context.Background(),
"my-addr",
FromState(true),
Out("out"),
IncludeOptional(true),
Provider("my-provider"),
)
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"add",
"-from-state=true",
"-out=out",
"-optional=true",
"-provider=my-provider",
"my-addr",
}, nil, addCmd)
})
}
13 changes: 7 additions & 6 deletions tfexec/internal/testutil/tfcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import (
)

const (
Latest011 = "0.11.15"
Latest012 = "0.12.31"
Latest013 = "0.13.7"
Latest014 = "0.14.11"
Latest015 = "0.15.5"
Latest_v1 = "1.0.0"
Latest011 = "0.11.15"
Latest012 = "0.12.31"
Latest013 = "0.13.7"
Latest014 = "0.14.11"
Latest015 = "0.15.5"
Latest_v1 = "1.0.0"
Latest_v1_1 = "1.1.0-alpha20210811"
)

const appendUserAgent = "tfexec-testutil"
Expand Down
18 changes: 18 additions & 0 deletions tfexec/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,21 @@ type VerifyPluginsOption struct {
func VerifyPlugins(verifyPlugins bool) *VerifyPluginsOption {
return &VerifyPluginsOption{verifyPlugins}
}

// FromStateOption represents the -from-state option of the "terraform add" command.
type FromStateOption struct {
fromState bool
}

func FromState(fromState bool) *FromStateOption {
return &FromStateOption{fromState}
}

// IncludeOptionalOption represents the -optional option of the "terraform add" command.
type IncludeOptionalOption struct {
includeOptional bool
}

func IncludeOptional(includeOptional bool) *IncludeOptionalOption {
return &IncludeOptionalOption{includeOptional}
}
1 change: 1 addition & 0 deletions tfexec/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var (
tf0_13_0 = version.Must(version.NewVersion("0.13.0"))
tf0_14_0 = version.Must(version.NewVersion("0.14.0"))
tf0_15_0 = version.Must(version.NewVersion("0.15.0"))
tf1_1_0 = version.Must(version.NewVersion("1.1.0"))
)

// Version returns structured output from the terraform version command including both the Terraform CLI version
Expand Down

0 comments on commit 38de6f4

Please sign in to comment.