diff --git a/command/e2etest/init_test.go b/command/e2etest/init_test.go index c1ad00805..7993c4e13 100644 --- a/command/e2etest/init_test.go +++ b/command/e2etest/init_test.go @@ -173,6 +173,56 @@ func TestInitProvidersLocalOnly(t *testing.T) { } } +func TestInitProvidersCustomMethod(t *testing.T) { + t.Parallel() + + // This test should not reach out to the network if it is behaving as + // intended. If it _does_ try to access an upstream registry and encounter + // an error doing so then that's a legitimate test failure that should be + // fixed. (If it incorrectly reaches out anywhere then it's likely to be + // to the host "example.com", which is the placeholder domain we use in + // the test fixture.) + + for _, configFile := range []string{"cliconfig.tfrc", "cliconfig.tfrc.json"} { + t.Run(configFile, func(t *testing.T) { + fixturePath := filepath.Join("testdata", "custom-provider-install-method") + tf := e2e.NewBinary(terraformBin, fixturePath) + defer tf.Close() + + // Our fixture dir has a generic os_arch dir, which we need to customize + // to the actual OS/arch where this test is running in order to get the + // desired result. + fixtMachineDir := tf.Path("fs-mirror/example.com/awesomecorp/happycloud/1.2.0/os_arch") + wantMachineDir := tf.Path("fs-mirror/example.com/awesomecorp/happycloud/1.2.0/", fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)) + err := os.Rename(fixtMachineDir, wantMachineDir) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + // We'll use a local CLI configuration file taken from our fixture + // directory so we can force a custom installation method config. + tf.AddEnv("TF_CLI_CONFIG_FILE=" + tf.Path(configFile)) + + stdout, stderr, err := tf.Run("init") + if err != nil { + t.Errorf("unexpected error: %s", err) + } + + if stderr != "" { + t.Errorf("unexpected stderr output:\n%s", stderr) + } + + if !strings.Contains(stdout, "Terraform has been successfully initialized!") { + t.Errorf("success message is missing from output:\n%s", stdout) + } + + if !strings.Contains(stdout, "- Installing example.com/awesomecorp/happycloud v1.2.0") { + t.Errorf("provider download message is missing from output:\n%s", stdout) + } + }) + } +} + func TestInitProviders_pluginCache(t *testing.T) { t.Parallel() diff --git a/command/e2etest/testdata/custom-provider-install-method/cliconfig.tfrc b/command/e2etest/testdata/custom-provider-install-method/cliconfig.tfrc new file mode 100644 index 000000000..a0c015e23 --- /dev/null +++ b/command/e2etest/testdata/custom-provider-install-method/cliconfig.tfrc @@ -0,0 +1,5 @@ +provider_installation { + filesystem_mirror { + path = "./fs-mirror" + } +} diff --git a/command/e2etest/testdata/custom-provider-install-method/cliconfig.tfrc.json b/command/e2etest/testdata/custom-provider-install-method/cliconfig.tfrc.json new file mode 100644 index 000000000..6e5e946b8 --- /dev/null +++ b/command/e2etest/testdata/custom-provider-install-method/cliconfig.tfrc.json @@ -0,0 +1,9 @@ +{ + "provider_installation": { + "filesystem_mirror": [ + { + "path": "./fs-mirror" + } + ] + } +} diff --git a/command/e2etest/testdata/custom-provider-install-method/fs-mirror/example.com/awesomecorp/happycloud/1.2.0/os_arch/terraform-provider-happycloud_v1.2.0 b/command/e2etest/testdata/custom-provider-install-method/fs-mirror/example.com/awesomecorp/happycloud/1.2.0/os_arch/terraform-provider-happycloud_v1.2.0 new file mode 100644 index 000000000..3299bec8a --- /dev/null +++ b/command/e2etest/testdata/custom-provider-install-method/fs-mirror/example.com/awesomecorp/happycloud/1.2.0/os_arch/terraform-provider-happycloud_v1.2.0 @@ -0,0 +1,2 @@ +This is not a real plugin executable. It's just here to be discovered by the +provider installation process. diff --git a/command/e2etest/testdata/custom-provider-install-method/main.tf b/command/e2etest/testdata/custom-provider-install-method/main.tf new file mode 100644 index 000000000..a521cf07b --- /dev/null +++ b/command/e2etest/testdata/custom-provider-install-method/main.tf @@ -0,0 +1,21 @@ +# The purpose of this test is to refer to a provider whose address contains +# a hostname that is only used for namespacing purposes and doesn't actually +# have a provider registry deployed at it. +# +# A user can install such a provider in one of the implied local filesystem +# directories and Terraform should accept that as the selection for that +# provider without producing any errors about the fact that example.com +# does not have a provider registry. +# +# For this test in particular we're using the "vendor" directory that is +# the documented way to include provider plugins directly inside a +# configuration uploaded to Terraform Cloud, but this functionality applies +# to all of the implicit local filesystem search directories. + +terraform { + required_providers { + happycloud = { + source = "example.com/awesomecorp/happycloud" + } + } +}