github.com/opentofu/opentofu@v1.7.1/internal/command/e2etest/provider_dev_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package e2etest 7 8 import ( 9 "fmt" 10 "os" 11 "path/filepath" 12 "strings" 13 "testing" 14 15 "github.com/opentofu/opentofu/internal/e2e" 16 ) 17 18 // TestProviderDevOverrides is a test for the special dev_overrides setting 19 // in the provider_installation section of the CLI configuration file, which 20 // is our current answer to smoothing provider development by allowing 21 // developers to opt out of the version number and checksum verification 22 // we normally do, so they can just overwrite the same local executable 23 // in-place to iterate faster. 24 func TestProviderDevOverrides(t *testing.T) { 25 if !canRunGoBuild { 26 // We're running in a separate-build-then-run context, so we can't 27 // currently execute this test which depends on being able to build 28 // new executable at runtime. 29 // 30 // (See the comment on canRunGoBuild's declaration for more information.) 31 t.Skip("can't run without building a new provider executable") 32 } 33 t.Parallel() 34 35 tf := e2e.NewBinary(t, tofuBin, "testdata/provider-dev-override") 36 37 // In order to do a decent end-to-end test for this case we will need a 38 // real enough provider plugin to try to run and make sure we are able 39 // to actually run it. For now we'll use the "test" provider for that, 40 // because it happens to be in this repository and therefore allows 41 // us to avoid drawing in anything external, but we might revisit this 42 // strategy in future if other needs cause us to evolve the test 43 // provider in a way that makes it less suitable for this particular test, 44 // such as if it stops being buildable into an independent executable. 45 providerExeDir := filepath.Join(tf.WorkDir(), "pkgdir") 46 providerExePrefix := filepath.Join(providerExeDir, "terraform-provider-test_") 47 providerExe := e2e.GoBuild("github.com/opentofu/opentofu/internal/provider-simple/main", providerExePrefix) 48 t.Logf("temporary provider executable is %s", providerExe) 49 50 err := os.WriteFile(filepath.Join(tf.WorkDir(), "dev.tfrc"), []byte(fmt.Sprintf(` 51 provider_installation { 52 dev_overrides { 53 "example.com/test/test" = %q 54 } 55 } 56 `, providerExeDir)), os.ModePerm) 57 if err != nil { 58 t.Fatal(err) 59 } 60 61 tf.AddEnv("TF_CLI_CONFIG_FILE=dev.tfrc") 62 63 stdout, stderr, err := tf.Run("providers") 64 if err != nil { 65 t.Fatalf("unexpected error: %s\n%s", err, stderr) 66 } 67 if got, want := stdout, `provider[example.com/test/test]`; !strings.Contains(got, want) { 68 t.Errorf("configuration should depend on %s, but doesn't\n%s", want, got) 69 } 70 71 // NOTE: We're intentionally not running "tofu init" here, because 72 // dev overrides are always ready to use and don't need any special action 73 // to "install" them. This test is mimicking the a happy path of going 74 // directly from "go build" to validate/plan/apply without interacting 75 // with any registries, mirrors, lock files, etc. To verify "tofu 76 // init" does actually show a warning, that behavior is tested at the end. 77 stdout, stderr, err = tf.Run("validate") 78 if err != nil { 79 t.Fatalf("unexpected error: %s\n%s", err, stderr) 80 } 81 82 if got, want := stdout, `The configuration is valid, but`; !strings.Contains(got, want) { 83 t.Errorf("stdout doesn't include the success message\nwant: %s\n%s", want, got) 84 } 85 if got, want := stdout, `Provider development overrides are in effect`; !strings.Contains(got, want) { 86 t.Errorf("stdout doesn't include the warning about development overrides\nwant: %s\n%s", want, got) 87 } 88 89 stdout, stderr, err = tf.Run("init") 90 if err == nil { 91 t.Fatal("expected error: Failed to query available provider packages") 92 } 93 if got, want := stdout, `Provider development overrides are in effect`; !strings.Contains(got, want) { 94 t.Errorf("stdout doesn't include the warning about development overrides\nwant: %s\n%s", want, got) 95 } 96 if got, want := stderr, `Failed to resolve provider packages`; !strings.Contains(got, want) { 97 t.Errorf("stderr doesn't include the error about listing unavailable development provider\nwant: %s\n%s", want, got) 98 } 99 }