Introduce tfexec.Get() for downloading modules (#176)

diff --git a/tfexec/get.go b/tfexec/get.go
new file mode 100644
index 0000000..5bac9b1
--- /dev/null
+++ b/tfexec/get.go
@@ -0,0 +1,52 @@
+package tfexec
+
+import (
+	"context"
+	"fmt"
+	"os/exec"
+)
+
+type getCmdConfig struct {
+	dir    string
+	update bool
+}
+
+// GetCmdOption represents options used in the Get method.
+type GetCmdOption interface {
+	configureGet(*getCmdConfig)
+}
+
+func (opt *DirOption) configureGet(conf *getCmdConfig) {
+	conf.dir = opt.path
+}
+
+func (opt *UpdateOption) configureGet(conf *getCmdConfig) {
+	conf.update = opt.update
+}
+
+// Get represents the terraform get subcommand.
+func (tf *Terraform) Get(ctx context.Context, opts ...GetCmdOption) error {
+	cmd, err := tf.getCmd(ctx, opts...)
+	if err != nil {
+		return err
+	}
+	return tf.runTerraformCmd(ctx, cmd)
+}
+
+func (tf *Terraform) getCmd(ctx context.Context, opts ...GetCmdOption) (*exec.Cmd, error) {
+	c := getCmdConfig{}
+
+	for _, o := range opts {
+		o.configureGet(&c)
+	}
+
+	args := []string{"get", "-no-color"}
+
+	args = append(args, "-update="+fmt.Sprint(c.update))
+
+	if c.dir != "" {
+		args = append(args, c.dir)
+	}
+
+	return tf.buildTerraformCmd(ctx, nil, args...), nil
+}
diff --git a/tfexec/get_test.go b/tfexec/get_test.go
new file mode 100644
index 0000000..5254e96
--- /dev/null
+++ b/tfexec/get_test.go
@@ -0,0 +1,33 @@
+package tfexec
+
+import (
+	"context"
+	"testing"
+
+	"github.com/hashicorp/terraform-exec/tfexec/internal/testutil"
+)
+
+func TestGetCmd(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("basic", func(t *testing.T) {
+		getCmd, err := tf.getCmd(context.Background())
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		assertCmd(t, []string{
+			"get",
+			"-no-color",
+			"-update=false",
+		}, nil, getCmd)
+	})
+}
diff --git a/tfexec/options.go b/tfexec/options.go
index 2f1a3db..d789010 100644
--- a/tfexec/options.go
+++ b/tfexec/options.go
@@ -290,6 +290,14 @@
 	return &TargetOption{resource}
 }
 
+type UpdateOption struct {
+	update bool
+}
+
+func Update(update bool) *UpdateOption {
+	return &UpdateOption{update}
+}
+
 type UpgradeOption struct {
 	upgrade bool
 }