Skip to content

Commit

Permalink
add ReattachOption
Browse files Browse the repository at this point in the history
  • Loading branch information
kmoe committed Sep 9, 2020
1 parent a04c890 commit 80cb85a
Show file tree
Hide file tree
Showing 23 changed files with 330 additions and 83 deletions.
36 changes: 27 additions & 9 deletions tfexec/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ type applyConfig struct {
lock bool

// LockTimeout must be a string with time unit, e.g. '10s'
lockTimeout string
parallelism int
refresh bool
state string
stateOut string
targets []string
lockTimeout string
parallelism int
reattachInfo ReattachInfo
refresh bool
state string
stateOut string
targets []string

// Vars: each var must be supplied as a single string, e.g. 'foo=bar'
vars []string
Expand Down Expand Up @@ -80,12 +81,20 @@ func (opt *DirOrPlanOption) configureApply(conf *applyConfig) {
conf.dirOrPlan = opt.path
}

func (opt *ReattachOption) configureApply(conf *applyConfig) {
conf.reattachInfo = opt.info
}

// Apply represents the terraform apply subcommand.
func (tf *Terraform) Apply(ctx context.Context, opts ...ApplyOption) error {
return tf.runTerraformCmd(tf.applyCmd(ctx, opts...))
cmd, err := tf.applyCmd(ctx, opts...)
if err != nil {
return err
}
return tf.runTerraformCmd(cmd)
}

func (tf *Terraform) applyCmd(ctx context.Context, opts ...ApplyOption) *exec.Cmd {
func (tf *Terraform) applyCmd(ctx context.Context, opts ...ApplyOption) (*exec.Cmd, error) {
c := defaultApplyOptions

for _, o := range opts {
Expand Down Expand Up @@ -133,5 +142,14 @@ func (tf *Terraform) applyCmd(ctx context.Context, opts ...ApplyOption) *exec.Cm
args = append(args, c.dirOrPlan)
}

return tf.buildTerraformCmd(ctx, args...)
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
}
5 changes: 4 additions & 1 deletion tfexec/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestApplyCmd(t *testing.T) {
tf.SetEnv(map[string]string{})

t.Run("basic", func(t *testing.T) {
applyCmd := tf.applyCmd(context.Background(),
applyCmd, err := tf.applyCmd(context.Background(),
Backup("testbackup"),
LockTimeout("200s"),
State("teststate"),
Expand All @@ -37,6 +37,9 @@ func TestApplyCmd(t *testing.T) {
Var("var2=bar"),
DirOrPlan("testfile"),
)
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"apply",
Expand Down
12 changes: 10 additions & 2 deletions tfexec/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,20 @@ func (tf *Terraform) buildEnv(mergeEnv map[string]string) []string {
// force usage of workspace methods for switching
env[workspaceEnvVar] = ""

if tf.disablePluginTLS {
env[disablePluginTLSEnvVar] = "1"
}

if tf.skipProviderVerify {
env[skipProviderVerifyEnvVar] = "1"
}

return envSlice(env)
}

func (tf *Terraform) buildTerraformCmd(ctx context.Context, args ...string) *exec.Cmd {
func (tf *Terraform) buildTerraformCmd(ctx context.Context, mergeEnv map[string]string, args ...string) *exec.Cmd {
cmd := exec.CommandContext(ctx, tf.execPath, args...)
cmd.Env = tf.buildEnv(nil)
cmd.Env = tf.buildEnv(mergeEnv)
cmd.Dir = tf.workingDir

tf.logger.Printf("[INFO] running Terraform command: %s", cmdString(cmd))
Expand Down
36 changes: 27 additions & 9 deletions tfexec/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ type destroyConfig struct {
lock bool

// LockTimeout must be a string with time unit, e.g. '10s'
lockTimeout string
parallelism int
refresh bool
state string
stateOut string
targets []string
lockTimeout string
parallelism int
reattachInfo ReattachInfo
refresh bool
state string
stateOut string
targets []string

// Vars: each var must be supplied as a single string, e.g. 'foo=bar'
vars []string
Expand Down Expand Up @@ -81,12 +82,20 @@ func (opt *VarOption) configureDestroy(conf *destroyConfig) {
conf.vars = append(conf.vars, opt.assignment)
}

func (opt *ReattachOption) configureDestroy(conf *destroyConfig) {
conf.reattachInfo = opt.info
}

// Destroy represents the terraform destroy subcommand.
func (tf *Terraform) Destroy(ctx context.Context, opts ...DestroyOption) error {
return tf.runTerraformCmd(tf.destroyCmd(ctx, opts...))
cmd, err := tf.destroyCmd(ctx, opts...)
if err != nil {
return err
}
return tf.runTerraformCmd(cmd)
}

func (tf *Terraform) destroyCmd(ctx context.Context, opts ...DestroyOption) *exec.Cmd {
func (tf *Terraform) destroyCmd(ctx context.Context, opts ...DestroyOption) (*exec.Cmd, error) {
c := defaultDestroyOptions

for _, o := range opts {
Expand Down Expand Up @@ -134,5 +143,14 @@ func (tf *Terraform) destroyCmd(ctx context.Context, opts ...DestroyOption) *exe
args = append(args, c.dir)
}

return tf.buildTerraformCmd(ctx, args...)
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
}
10 changes: 8 additions & 2 deletions tfexec/destroy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ func TestDestroyCmd(t *testing.T) {
tf.SetEnv(map[string]string{})

t.Run("defaults", func(t *testing.T) {
destroyCmd := tf.destroyCmd(context.Background())
destroyCmd, err := tf.destroyCmd(context.Background())
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"destroy",
Expand All @@ -36,7 +39,10 @@ func TestDestroyCmd(t *testing.T) {
})

t.Run("override all defaults", func(t *testing.T) {
destroyCmd := tf.destroyCmd(context.Background(), Backup("testbackup"), LockTimeout("200s"), State("teststate"), StateOut("teststateout"), VarFile("testvarfile"), Lock(false), Parallelism(99), Refresh(false), Target("target1"), Target("target2"), Var("var1=foo"), Var("var2=bar"), Dir("destroydir"))
destroyCmd, err := tf.destroyCmd(context.Background(), Backup("testbackup"), LockTimeout("200s"), State("teststate"), StateOut("teststateout"), VarFile("testvarfile"), Lock(false), Parallelism(99), Refresh(false), Target("target1"), Target("target2"), Var("var1=foo"), Var("var2=bar"), Dir("destroydir"))
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"destroy",
Expand Down
24 changes: 21 additions & 3 deletions tfexec/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type importConfig struct {
allowMissingConfig bool
lock bool
lockTimeout string
reattachInfo ReattachInfo
state string
stateOut string
vars []string
Expand Down Expand Up @@ -51,6 +52,10 @@ func (opt *LockTimeoutOption) configureImport(conf *importConfig) {
conf.lockTimeout = opt.timeout
}

func (opt *ReattachOption) configureImport(conf *importConfig) {
conf.reattachInfo = opt.info
}

func (opt *StateOption) configureImport(conf *importConfig) {
conf.state = opt.path
}
Expand All @@ -69,10 +74,14 @@ func (opt *VarFileOption) configureImport(conf *importConfig) {

// Import represents the terraform import subcommand.
func (tf *Terraform) Import(ctx context.Context, address, id string, opts ...ImportOption) error {
return tf.runTerraformCmd(tf.importCmd(ctx, address, id, opts...))
cmd, err := tf.importCmd(ctx, address, id, opts...)
if err != nil {
return err
}
return tf.runTerraformCmd(cmd)
}

func (tf *Terraform) importCmd(ctx context.Context, address, id string, opts ...ImportOption) *exec.Cmd {
func (tf *Terraform) importCmd(ctx context.Context, address, id string, opts ...ImportOption) (*exec.Cmd, error) {
c := defaultImportOptions

for _, o := range opts {
Expand Down Expand Up @@ -119,5 +128,14 @@ func (tf *Terraform) importCmd(ctx context.Context, address, id string, opts ...
// required args, always pass
args = append(args, address, id)

return tf.buildTerraformCmd(ctx, args...)
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
}
10 changes: 8 additions & 2 deletions tfexec/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ func TestImportCmd(t *testing.T) {
tf.SetEnv(map[string]string{})

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

assertCmd(t, []string{
"import",
Expand All @@ -35,7 +38,7 @@ func TestImportCmd(t *testing.T) {
})

t.Run("override all defaults", func(t *testing.T) {
importCmd := tf.importCmd(context.Background(), "my-addr2", "my-id2",
importCmd, err := tf.importCmd(context.Background(), "my-addr2", "my-id2",
Backup("testbackup"),
LockTimeout("200s"),
State("teststate"),
Expand All @@ -46,6 +49,9 @@ func TestImportCmd(t *testing.T) {
Var("var2=bar"),
AllowMissingConfig(true),
)
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"import",
Expand Down
24 changes: 21 additions & 3 deletions tfexec/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type initConfig struct {
lock bool
lockTimeout string
pluginDir []string
reattachInfo ReattachInfo
reconfigure bool
upgrade bool
verifyPlugins bool
Expand Down Expand Up @@ -75,6 +76,10 @@ func (opt *PluginDirOption) configureInit(conf *initConfig) {
conf.pluginDir = append(conf.pluginDir, opt.pluginDir)
}

func (opt *ReattachOption) configureInit(conf *initConfig) {
conf.reattachInfo = opt.info
}

func (opt *ReconfigureOption) configureInit(conf *initConfig) {
conf.reconfigure = opt.reconfigure
}
Expand All @@ -89,10 +94,14 @@ func (opt *VerifyPluginsOption) configureInit(conf *initConfig) {

// Init represents the terraform init subcommand.
func (tf *Terraform) Init(ctx context.Context, opts ...InitOption) error {
return tf.runTerraformCmd(tf.initCmd(ctx, opts...))
cmd, err := tf.initCmd(ctx, opts...)
if err != nil {
return err
}
return tf.runTerraformCmd(cmd)
}

func (tf *Terraform) initCmd(ctx context.Context, opts ...InitOption) *exec.Cmd {
func (tf *Terraform) initCmd(ctx context.Context, opts ...InitOption) (*exec.Cmd, error) {
c := defaultInitOptions

for _, o := range opts {
Expand Down Expand Up @@ -139,5 +148,14 @@ func (tf *Terraform) initCmd(ctx context.Context, opts ...InitOption) *exec.Cmd
args = append(args, c.dir)
}

return tf.buildTerraformCmd(ctx, args...)
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
}
7 changes: 5 additions & 2 deletions tfexec/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestInitCmd(t *testing.T) {

t.Run("defaults", func(t *testing.T) {
// defaults
initCmd := tf.initCmd(context.Background())
initCmd, err := tf.initCmd(context.Background())
if err != nil {
t.Fatal(err)
}
Expand All @@ -43,7 +43,10 @@ func TestInitCmd(t *testing.T) {
})

t.Run("override all defaults", func(t *testing.T) {
initCmd := tf.initCmd(context.Background(), Backend(false), BackendConfig("confpath1"), BackendConfig("confpath2"), FromModule("testsource"), Get(false), GetPlugins(false), Lock(false), LockTimeout("999s"), PluginDir("testdir1"), PluginDir("testdir2"), Reconfigure(true), Upgrade(true), VerifyPlugins(false), Dir("initdir"))
initCmd, err := tf.initCmd(context.Background(), Backend(false), BackendConfig("confpath1"), BackendConfig("confpath2"), FromModule("testsource"), Get(false), GetPlugins(false), Lock(false), LockTimeout("999s"), PluginDir("testdir1"), PluginDir("testdir2"), Reconfigure(true), Upgrade(true), VerifyPlugins(false), Dir("initdir"))
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"init",
Expand Down
37 changes: 37 additions & 0 deletions tfexec/options.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package tfexec

import (
"encoding/json"
)

// AllowMissingConfigOption represents the -allow-missing-config flag.
type AllowMissingConfigOption struct {
allowMissingConfig bool
Expand Down Expand Up @@ -172,6 +176,39 @@ func PluginDir(pluginDir string) *PluginDirOption {
return &PluginDirOption{pluginDir}
}

type ReattachInfo map[string]ReattachConfig

// ReattachConfig holds the information Terraform needs to be able to attach
// itself to a provider process, so it can drive the process.
type ReattachConfig struct {
Protocol string
Pid int
Test bool
Addr ReattachConfigAddr
}

// ReattachConfigAddr is a JSON-encoding friendly version of net.Addr.
type ReattachConfigAddr struct {
Network string
String string
}

type ReattachOption struct {
info ReattachInfo
}

func (info ReattachInfo) marshalString() (string, error) {
reattachStr, err := json.Marshal(info)
if err != nil {
return "", err
}
return string(reattachStr), nil
}

func Reattach(info ReattachInfo) *ReattachOption {
return &ReattachOption{info}
}

type ReconfigureOption struct {
reconfigure bool
}
Expand Down
2 changes: 1 addition & 1 deletion tfexec/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ func (tf *Terraform) outputCmd(ctx context.Context, opts ...OutputOption) *exec.
args = append(args, "-state="+c.state)
}

return tf.buildTerraformCmd(ctx, args...)
return tf.buildTerraformCmd(ctx, nil, args...)
}
Loading

0 comments on commit 80cb85a

Please sign in to comment.