Add support for `metadata functions -json` command (#358)

* Ignore Go workspace files

Relative paths in the go.work file are likely machine specific and
won't work on other systems.

* Add `metadata functions -json` command

* Add metadata functions unit test

* Add e2e test

* Update tfexec/metadata_functions.go

Co-authored-by: Radek Simko <radek.simko@gmail.com>

* Remove newline

---------

Co-authored-by: Radek Simko <radek.simko@gmail.com>
diff --git a/.gitignore b/.gitignore
index 1521c8b..1bfef83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 dist
+go.work*
\ No newline at end of file
diff --git a/tfexec/internal/e2etest/metadata_functions_test.go b/tfexec/internal/e2etest/metadata_functions_test.go
new file mode 100644
index 0000000..f8610a6
--- /dev/null
+++ b/tfexec/internal/e2etest/metadata_functions_test.go
@@ -0,0 +1,23 @@
+package e2etest
+
+import (
+	"context"
+	"testing"
+
+	"github.com/hashicorp/go-version"
+
+	"github.com/hashicorp/terraform-exec/tfexec"
+)
+
+func TestMetadataFunctions(t *testing.T) {
+	runTest(t, "basic", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
+		if tfv.LessThan(metadataFunctionsMinVersion) {
+			t.Skip("metadata functions command is not available in this Terraform version")
+		}
+
+		_, err := tf.MetadataFunctions(context.Background())
+		if err != nil {
+			t.Fatalf("error running MetadataFunctions: %s", err)
+		}
+	})
+}
diff --git a/tfexec/internal/e2etest/util_test.go b/tfexec/internal/e2etest/util_test.go
index 66800d5..01fd25a 100644
--- a/tfexec/internal/e2etest/util_test.go
+++ b/tfexec/internal/e2etest/util_test.go
@@ -24,6 +24,8 @@
 	showMinVersion = version.Must(version.NewVersion("0.12.0"))
 
 	providerAddressMinVersion = version.Must(version.NewVersion("0.13.0"))
+
+	metadataFunctionsMinVersion = version.Must(version.NewVersion("1.4.0"))
 )
 
 func runTest(t *testing.T, fixtureName string, cb func(t *testing.T, tfVersion *version.Version, tf *tfexec.Terraform)) {
diff --git a/tfexec/metadata_functions.go b/tfexec/metadata_functions.go
new file mode 100644
index 0000000..4577e06
--- /dev/null
+++ b/tfexec/metadata_functions.go
@@ -0,0 +1,34 @@
+package tfexec
+
+import (
+	"context"
+	"fmt"
+	"os/exec"
+
+	tfjson "github.com/hashicorp/terraform-json"
+)
+
+// MetadataFunctions represents the terraform metadata functions -json subcommand.
+func (tf *Terraform) MetadataFunctions(ctx context.Context) (*tfjson.MetadataFunctions, error) {
+	err := tf.compatible(ctx, tf1_4_0, nil)
+	if err != nil {
+		return nil, fmt.Errorf("terraform metadata functions was added in 1.4.0: %w", err)
+	}
+
+	functionsCmd := tf.metadataFunctionsCmd(ctx)
+
+	var ret tfjson.MetadataFunctions
+	err = tf.runTerraformCmdJSON(ctx, functionsCmd, &ret)
+	if err != nil {
+		return nil, err
+	}
+
+	return &ret, nil
+}
+
+func (tf *Terraform) metadataFunctionsCmd(ctx context.Context, args ...string) *exec.Cmd {
+	allArgs := []string{"metadata", "functions", "-json"}
+	allArgs = append(allArgs, args...)
+
+	return tf.buildTerraformCmd(ctx, nil, allArgs...)
+}
diff --git a/tfexec/metadata_functions_test.go b/tfexec/metadata_functions_test.go
new file mode 100644
index 0000000..c259d7e
--- /dev/null
+++ b/tfexec/metadata_functions_test.go
@@ -0,0 +1,29 @@
+package tfexec
+
+import (
+	"context"
+	"testing"
+
+	"github.com/hashicorp/terraform-exec/tfexec/internal/testutil"
+)
+
+func TestMetadataFunctionsCmd(t *testing.T) {
+	td := t.TempDir()
+
+	tf, err := NewTerraform(td, tfVersion(t, testutil.Latest_v1_1))
+	// tf, err := NewTerraform(td, tfVersion(t, testutil.Latest_v1_4)) // TODO! enable after 1.4 release
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// empty env, to avoid environ mismatch in testing
+	tf.SetEnv(map[string]string{})
+
+	functionsCmd := tf.metadataFunctionsCmd(context.Background())
+
+	assertCmd(t, []string{
+		"metadata",
+		"functions",
+		"-json",
+	}, nil, functionsCmd)
+}
diff --git a/tfexec/version.go b/tfexec/version.go
index 37825b5..a2e9736 100644
--- a/tfexec/version.go
+++ b/tfexec/version.go
@@ -27,6 +27,7 @@
 	tf0_15_2 = version.Must(version.NewVersion("0.15.2"))
 	tf0_15_3 = version.Must(version.NewVersion("0.15.3"))
 	tf1_1_0  = version.Must(version.NewVersion("1.1.0"))
+	tf1_4_0  = version.Must(version.NewVersion("1.4.0"))
 )
 
 // Version returns structured output from the terraform version command including both the Terraform CLI version