Skip to content

Commit

Permalink
Add providers lock Command
Browse files Browse the repository at this point in the history
Adds feature requested in hashicorp#201. This allows programatic generation of
`.terraform.lock.hcl` files via this library
  • Loading branch information
philnielsen committed Jul 28, 2021
1 parent 43e54be commit 5789a53
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 0 deletions.
26 changes: 26 additions & 0 deletions tfexec/internal/e2etest/providers_lock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package e2etest

import (
"context"
"testing"

"github.com/hashicorp/go-version"

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

func TestProvidersLock(t *testing.T) {
runTestVersions(t, []string{testutil.Latest014, testutil.Latest015, testutil.Latest_v1}, "basic", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
err := tf.Init(context.Background())
if err != nil {
t.Fatalf("error running Init in test directory: %s", err)
}

err = tf.ProvidersLock(context.Background())
if err != nil {
t.Fatalf("error running provider lock: %s", err)
}
})

}
36 changes: 36 additions & 0 deletions tfexec/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ func DryRun(dryRun bool) *DryRunOption {
return &DryRunOption{dryRun}
}

type FSMirrorOption struct {
fsMirror string
}

// FSMirror Represents the -fs-mirror option
func FSMirror(fsMirror string) *FSMirrorOption {
return &FSMirrorOption{fsMirror}
}

type ForceOption struct {
force bool
}
Expand Down Expand Up @@ -178,6 +187,15 @@ func LockTimeout(lockTimeout string) *LockTimeoutOption {
return &LockTimeoutOption{lockTimeout}
}

type NetMirrorOption struct {
netMirror string
}

// NetMirror Represents the -fs-mirror option
func NetMirror(netMirror string) *NetMirrorOption {
return &NetMirrorOption{netMirror}
}

type OutOption struct {
path string
}
Expand All @@ -194,6 +212,15 @@ func Parallelism(n int) *ParallelismOption {
return &ParallelismOption{n}
}

type PlatformOption struct {
platform string
}

// Platform represents the -platform flag which is an os_arch string
func Platform(platform string) *PlatformOption {
return &PlatformOption{platform}
}

type PluginDirOption struct {
pluginDir string
}
Expand All @@ -202,6 +229,15 @@ func PluginDir(pluginDir string) *PluginDirOption {
return &PluginDirOption{pluginDir}
}

type ProviderOption struct {
provider string
}

// Provider Represents the provider positional argument
func Provider(providers string) *ProviderOption {
return &ProviderOption{providers}
}

type ReattachInfo map[string]ReattachConfig

// ReattachConfig holds the information Terraform needs to be able to attach
Expand Down
76 changes: 76 additions & 0 deletions tfexec/providers_lock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package tfexec

import (
"context"
"os/exec"
)

type providersLockConfig struct {
fsMirror string
netMirror string
platforms []string
providers []string
}

var defaultProvidersLockOptions = providersLockConfig{}

type ProvidersLockOption interface {
configureProvidersLock(*providersLockConfig)
}

func (opt *FSMirrorOption) configureProvidersLock(conf *providersLockConfig) {
conf.fsMirror = opt.fsMirror
}

func (opt *NetMirrorOption) configureProvidersLock(conf *providersLockConfig) {
conf.netMirror = opt.netMirror
}

func (opt *PlatformOption) configureProvidersLock(conf *providersLockConfig) {
conf.platforms = append(conf.platforms, opt.platform)
}

func (opt *ProviderOption) configureProvidersLock(conf *providersLockConfig) {
conf.providers = append(conf.providers, opt.provider)
}

// ProvidersLock represents the terraform providers lock
func (tf *Terraform) ProvidersLock(ctx context.Context, opts ...ProvidersLockOption) error {
lockCmd := tf.providersLockCmd(ctx, opts...)

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

return err
}

func (tf *Terraform) providersLockCmd(ctx context.Context, opts ...ProvidersLockOption) *exec.Cmd {
c := defaultProvidersLockOptions

for _, o := range opts {
o.configureProvidersLock(&c)
}
args := []string{"providers", "lock"}

// string options, only pass if set
if c.fsMirror != "" {
args = append(args, "-fs-mirror="+c.fsMirror)
}

if c.netMirror != "" {
args = append(args, "-net-mirror="+c.netMirror)
}

for _, p := range c.platforms {
args = append(args, "-platform="+p)
}

// positional providers argument
for _, p := range c.providers {
args = append(args, p)
}

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

import (
"context"
"testing"

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

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

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

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

t.Run("defaults", func(t *testing.T) {
lockCmd := tf.providersLockCmd(context.Background())

assertCmd(t, []string{
"providers",
"lock",
}, nil, lockCmd)
})

t.Run("override all defaults", func(t *testing.T) {
lockCmd := tf.providersLockCmd(context.Background(), FSMirror("test"), NetMirror("test"), Platform("linux_amd64"), Provider("workingdir"))

assertCmd(t, []string{
"providers",
"lock",
"-fs-mirror=test",
"-net-mirror=test",
"-platform=linux_amd64",
"workingdir",
}, nil, lockCmd)
})
}

0 comments on commit 5789a53

Please sign in to comment.