Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tfexec: Initial support for Terraform 0.14 -chdir global option #100

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 30 additions & 1 deletion tfexec/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import (

type applyConfig struct {
backup string
chdir string
dirOrPlan string
lock bool

// LockTimeout must be a string with time unit, e.g. '10s'
lockTimeout string
parallelism int
planArg string
reattachInfo ReattachInfo
refresh bool
state string
Expand Down Expand Up @@ -77,10 +79,18 @@ func (opt *VarOption) configureApply(conf *applyConfig) {
conf.vars = append(conf.vars, opt.assignment)
}

func (opt *ChdirOption) configureApply(conf *applyConfig) {
conf.chdir = opt.path
}

func (opt *DirOrPlanOption) configureApply(conf *applyConfig) {
conf.dirOrPlan = opt.path
}

func (opt *PlanArgOption) configureApply(conf *applyConfig) {
conf.planArg = opt.path
}

func (opt *ReattachOption) configureApply(conf *applyConfig) {
conf.reattachInfo = opt.info
}
Expand All @@ -98,10 +108,25 @@ func (tf *Terraform) applyCmd(ctx context.Context, opts ...ApplyOption) (*exec.C
c := defaultApplyOptions

for _, o := range opts {
switch o.(type) {
case *ChdirOption:
err := tf.compatible(ctx, tf0_14_0, nil)
if err != nil {
return nil, fmt.Errorf("-chdir was added in Terraform 0.14: %w", err)
}
}

o.configureApply(&c)
}

args := []string{"apply", "-no-color", "-auto-approve", "-input=false"}
var args []string

// global opts
if c.chdir != "" {
args = append(args, "-chdir="+c.chdir)
}

args = append(args, []string{"apply", "-no-color", "-auto-approve", "-input=false"}...)

// string opts: only pass if set
if c.backup != "" {
Expand Down Expand Up @@ -142,6 +167,10 @@ func (tf *Terraform) applyCmd(ctx context.Context, opts ...ApplyOption) (*exec.C
args = append(args, c.dirOrPlan)
}

if c.planArg != "" {
args = append(args, c.planArg)
}

mergeEnv := map[string]string{}
if c.reattachInfo != nil {
reattachStr, err := c.reattachInfo.marshalString()
Expand Down
44 changes: 43 additions & 1 deletion tfexec/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func TestApplyCmd(t *testing.T) {
td := testTempDir(t)

tf, err := NewTerraform(td, tfVersion(t, testutil.Latest012))
tf, err := NewTerraform(td, tfVersion(t, testutil.Latest014))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -60,4 +60,46 @@ func TestApplyCmd(t *testing.T) {
"testfile",
}, nil, applyCmd)
})

t.Run("chdir", func(t *testing.T) {
applyCmd, err := tf.applyCmd(context.Background(),
Chdir("testpath"),
)

if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"-chdir=testpath",
"apply",
"-no-color",
"-auto-approve",
"-input=false",
"-lock=true",
"-parallelism=10",
"-refresh=true",
}, nil, applyCmd)
})

t.Run("plan", func(t *testing.T) {
applyCmd, err := tf.applyCmd(context.Background(),
PlanArg("testplan"),
)

if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"apply",
"-no-color",
"-auto-approve",
"-input=false",
"-lock=true",
"-parallelism=10",
"-refresh=true",
"testplan",
}, nil, applyCmd)
})
}
22 changes: 21 additions & 1 deletion tfexec/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

type destroyConfig struct {
backup string
chdir string
dir string
lock bool

Expand Down Expand Up @@ -38,6 +39,10 @@ type DestroyOption interface {
configureDestroy(*destroyConfig)
}

func (opt *ChdirOption) configureDestroy(conf *destroyConfig) {
conf.chdir = opt.path
}

func (opt *DirOption) configureDestroy(conf *destroyConfig) {
conf.dir = opt.path
}
Expand Down Expand Up @@ -99,10 +104,25 @@ func (tf *Terraform) destroyCmd(ctx context.Context, opts ...DestroyOption) (*ex
c := defaultDestroyOptions

for _, o := range opts {
switch o.(type) {
case *ChdirOption:
err := tf.compatible(ctx, tf0_14_0, nil)
if err != nil {
return nil, fmt.Errorf("-chdir was added in Terraform 0.14: %w", err)
}
}

o.configureDestroy(&c)
}

args := []string{"destroy", "-no-color", "-auto-approve", "-input=false"}
var args []string

// global opts
if c.chdir != "" {
args = append(args, "-chdir="+c.chdir)
}

args = append(args, []string{"destroy", "-no-color", "-auto-approve", "-input=false"}...)

// string opts: only pass if set
if c.backup != "" {
Expand Down
24 changes: 23 additions & 1 deletion tfexec/destroy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func TestDestroyCmd(t *testing.T) {
td := testTempDir(t)

tf, err := NewTerraform(td, tfVersion(t, testutil.Latest012))
tf, err := NewTerraform(td, tfVersion(t, testutil.Latest014))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -62,4 +62,26 @@ func TestDestroyCmd(t *testing.T) {
"destroydir",
}, nil, destroyCmd)
})

t.Run("chdir", func(t *testing.T) {
destroyCmd, err := tf.destroyCmd(context.Background(),
Chdir("testpath"),
)

if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"-chdir=testpath",
"destroy",
"-no-color",
"-auto-approve",
"-input=false",
"-lock-timeout=0s",
"-lock=true",
"-parallelism=10",
"-refresh=true",
}, nil, destroyCmd)
})
}
21 changes: 18 additions & 3 deletions tfexec/fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import (
)

type formatConfig struct {
recursive bool
chdir string
dir string
recursive bool
}

var defaultFormatConfig = formatConfig{
Expand All @@ -23,14 +24,18 @@ type FormatOption interface {
configureFormat(*formatConfig)
}

func (opt *RecursiveOption) configureFormat(conf *formatConfig) {
conf.recursive = opt.recursive
func (opt *ChdirOption) configureFormat(conf *formatConfig) {
conf.chdir = opt.path
}

func (opt *DirOption) configureFormat(conf *formatConfig) {
conf.dir = opt.path
}

func (opt *RecursiveOption) configureFormat(conf *formatConfig) {
conf.recursive = opt.recursive
}

// FormatString formats a passed string, given a path to Terraform.
func FormatString(ctx context.Context, execPath string, content string) (string, error) {
tf, err := NewTerraform(filepath.Dir(execPath), execPath)
Expand Down Expand Up @@ -136,6 +141,11 @@ func (tf *Terraform) formatCmd(ctx context.Context, args []string, opts ...Forma

for _, o := range opts {
switch o.(type) {
case *ChdirOption:
err := tf.compatible(ctx, tf0_14_0, nil)
if err != nil {
return nil, fmt.Errorf("-chdir was added in Terraform 0.14: %w", err)
}
case *RecursiveOption:
err := tf.compatible(ctx, tf0_12_0, nil)
if err != nil {
Expand All @@ -148,6 +158,11 @@ func (tf *Terraform) formatCmd(ctx context.Context, args []string, opts ...Forma

args = append([]string{"fmt", "-no-color"}, args...)

// global opts
if c.chdir != "" {
args = append([]string{"-chdir=" + c.chdir}, args...)
}

if c.recursive {
args = append(args, "-recursive")
}
Expand Down
32 changes: 30 additions & 2 deletions tfexec/fmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,49 @@ import (
"context"
"errors"
"testing"

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

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

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

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

t.Run("chdir", func(t *testing.T) {
fmtCmd, err := tf.formatCmd(context.Background(),
[]string{"testfile"},
Chdir("testpath"),
)

if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"-chdir=testpath",
"fmt",
"-no-color",
"testfile",
}, nil, fmtCmd)
})

t.Run("too old version", func(t *testing.T) {
_, err := tf.formatCmd(context.Background(), []string{})
tf, err := NewTerraform(td, tfVersion(t, "0.7.6"))
if err != nil {
t.Fatal(err)
}

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

_, err = tf.formatCmd(context.Background(), []string{})
if err == nil {
t.Fatal("expected old version to fail")
}
Expand Down
23 changes: 22 additions & 1 deletion tfexec/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tfexec

import (
"context"
"fmt"
"os/exec"
"strconv"
)
Expand All @@ -10,6 +11,7 @@ type importConfig struct {
addr string
id string
backup string
chdir string
config string
allowMissingConfig bool
lock bool
Expand All @@ -36,6 +38,10 @@ func (opt *BackupOption) configureImport(conf *importConfig) {
conf.backup = opt.path
}

func (opt *ChdirOption) configureImport(conf *importConfig) {
conf.chdir = opt.path
}

func (opt *ConfigOption) configureImport(conf *importConfig) {
conf.config = opt.path
}
Expand Down Expand Up @@ -85,10 +91,25 @@ func (tf *Terraform) importCmd(ctx context.Context, address, id string, opts ...
c := defaultImportOptions

for _, o := range opts {
switch o.(type) {
case *ChdirOption:
err := tf.compatible(ctx, tf0_14_0, nil)
if err != nil {
return nil, fmt.Errorf("-chdir was added in Terraform 0.14: %w", err)
}
}

o.configureImport(&c)
}

args := []string{"import", "-no-color", "-input=false"}
var args []string

// global opts
if c.chdir != "" {
args = append(args, "-chdir="+c.chdir)
}

args = append(args, []string{"import", "-no-color", "-input=false"}...)

// string opts: only pass if set
if c.backup != "" {
Expand Down