Skip to content

Commit

Permalink
Add support for state push/pull
Browse files Browse the repository at this point in the history
  • Loading branch information
pasternak authored and kmoe committed Apr 26, 2022
1 parent 6861367 commit 705ec00
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 0 deletions.
49 changes: 49 additions & 0 deletions tfexec/state_pull.go
@@ -0,0 +1,49 @@
package tfexec

import (
"context"
"os/exec"

tfjson "github.com/hashicorp/terraform-json"
)

type statePullConfig struct {
reattachInfo ReattachInfo
}

var defaultStatePullConfig = statePullConfig{}

func (tf *Terraform) StatePull(ctx context.Context) (*tfjson.State, error) {
c := defaultStatePullConfig

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

cmd := tf.statePullCmd(ctx)

var ret tfjson.State
ret.UseJSONNumber(true)
err := tf.runTerraformCmdJSON(ctx, cmd, &ret)
if err != nil {
return nil, err
}

err = ret.Validate()
if err != nil {
return nil, err
}

return &ret, nil
}

func (tf *Terraform) statePullCmd(ctx context.Context) *exec.Cmd {
args := []string{"state", "pull"}

return tf.buildTerraformCmd(ctx, nil, args...)
}
28 changes: 28 additions & 0 deletions tfexec/state_pull_test.go
@@ -0,0 +1,28 @@
package tfexec

import (
"context"
"testing"

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

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

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

tf.SetEnv(map[string]string{})

t.Run("tfstate", func(t *testing.T) {
statePullCmd := tf.statePullCmd(context.Background())

assertCmd(t, []string{
"state",
"pull",
}, nil, statePullCmd)
})
}
65 changes: 65 additions & 0 deletions tfexec/state_push.go
@@ -0,0 +1,65 @@
package tfexec

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

type statePushConfig struct {
force bool
lock bool
lockTimeout string
}

var defaultStatePushOptions = statePushConfig{
lock: false,
lockTimeout: "0s",
}

// StatePushCmdOption represents options used in the Refresh method.
type StatePushCmdOption interface {
configureStatePush(*statePushConfig)
}

func (opt *ForceOption) configureStatePush(conf *statePushConfig) {
conf.force = opt.force
}

func (opt *LockOption) configureStatePush(conf *statePushConfig) {
conf.lock = opt.lock
}

func (opt *LockTimeoutOption) configureStatePush(conf *statePushConfig) {
conf.lockTimeout = opt.timeout
}

func (tf *Terraform) StatePush(ctx context.Context, path string, opts ...StatePushCmdOption) error {
cmd, err := tf.statePushCmd(ctx, path, opts...)
if err != nil {
return err
}
return tf.runTerraformCmd(ctx, cmd)
}

func (tf *Terraform) statePushCmd(ctx context.Context, path string, opts ...StatePushCmdOption) (*exec.Cmd, error) {
c := defaultStatePushOptions

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

args := []string{"state", "push"}

if c.force {
args = append(args, "-force")
}

args = append(args, "-lock="+strconv.FormatBool(c.lock))

if c.lockTimeout != "" {
args = append(args, "-lock-timeout="+c.lockTimeout)
}

return tf.buildTerraformCmd(ctx, nil, args...), nil
}
48 changes: 48 additions & 0 deletions tfexec/state_push_test.go
@@ -0,0 +1,48 @@
package tfexec

import (
"context"
"testing"

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

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

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

tf.SetEnv(map[string]string{})

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

assertCmd(t, []string{
"state",
"push",
"-lock=false",
"-lock-timeout=0s",
}, nil, statePushCmd)
})

t.Run("override all defaults", func(t *testing.T) {
statePushCmd, err := tf.statePushCmd(context.Background(), "testpath", Force(true), Lock(true), LockTimeout("10s"))
if err != nil {
t.Fatal(err)
}

assertCmd(t, []string{
"state",
"push",
"-force",
"-lock=true",
"-lock-timeout=10s",
}, nil, statePushCmd)
})
}

0 comments on commit 705ec00

Please sign in to comment.