github.com/pulumi/terraform@v1.4.0/pkg/command/providers_lock_test.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strings" 9 "testing" 10 11 "github.com/pulumi/terraform/pkg/addrs" 12 "github.com/pulumi/terraform/pkg/depsfile" 13 "github.com/pulumi/terraform/pkg/getproviders" 14 "github.com/mitchellh/cli" 15 ) 16 17 func TestProvidersLock(t *testing.T) { 18 t.Run("noop", func(t *testing.T) { 19 // in the most basic case, running providers lock in a directory with no configuration at all should succeed. 20 // create an empty working directory 21 td := t.TempDir() 22 os.MkdirAll(td, 0755) 23 defer testChdir(t, td)() 24 25 ui := new(cli.MockUi) 26 c := &ProvidersLockCommand{ 27 Meta: Meta{ 28 Ui: ui, 29 }, 30 } 31 code := c.Run([]string{}) 32 if code != 0 { 33 t.Fatalf("wrong exit code; expected 0, got %d", code) 34 } 35 }) 36 37 // This test depends on the -fs-mirror argument, so we always know what results to expect 38 t.Run("basic", func(t *testing.T) { 39 testDirectory := "providers-lock/basic" 40 expected := `# This file is maintained automatically by "terraform init". 41 # Manual edits may be lost in future updates. 42 43 provider "registry.terraform.io/hashicorp/test" { 44 version = "1.0.0" 45 hashes = [ 46 "h1:7MjN4eFisdTv4tlhXH5hL4QQd39Jy4baPhFxwAd/EFE=", 47 ] 48 } 49 ` 50 runProviderLockGenericTest(t, testDirectory, expected) 51 }) 52 53 // This test depends on the -fs-mirror argument, so we always know what results to expect 54 t.Run("append", func(t *testing.T) { 55 testDirectory := "providers-lock/append" 56 expected := `# This file is maintained automatically by "terraform init". 57 # Manual edits may be lost in future updates. 58 59 provider "registry.terraform.io/hashicorp/test" { 60 version = "1.0.0" 61 hashes = [ 62 "h1:7MjN4eFisdTv4tlhXH5hL4QQd39Jy4baPhFxwAd/EFE=", 63 "h1:invalid", 64 ] 65 } 66 ` 67 runProviderLockGenericTest(t, testDirectory, expected) 68 }) 69 } 70 71 func runProviderLockGenericTest(t *testing.T, testDirectory, expected string) { 72 td := t.TempDir() 73 testCopyDir(t, testFixturePath(testDirectory), td) 74 defer testChdir(t, td)() 75 76 // Our fixture dir has a generic os_arch dir, which we need to customize 77 // to the actual OS/arch where this test is running in order to get the 78 // desired result. 79 fixtMachineDir := filepath.Join(td, "fs-mirror/registry.terraform.io/hashicorp/test/1.0.0/os_arch") 80 wantMachineDir := filepath.Join(td, "fs-mirror/registry.terraform.io/hashicorp/test/1.0.0/", fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)) 81 err := os.Rename(fixtMachineDir, wantMachineDir) 82 if err != nil { 83 t.Fatalf("unexpected error: %s", err) 84 } 85 86 p := testProvider() 87 ui := new(cli.MockUi) 88 c := &ProvidersLockCommand{ 89 Meta: Meta{ 90 Ui: ui, 91 testingOverrides: metaOverridesForProvider(p), 92 }, 93 } 94 95 args := []string{"-fs-mirror=fs-mirror"} 96 code := c.Run(args) 97 if code != 0 { 98 t.Fatalf("wrong exit code; expected 0, got %d", code) 99 } 100 101 lockfile, err := os.ReadFile(".terraform.lock.hcl") 102 if err != nil { 103 t.Fatal("error reading lockfile") 104 } 105 106 if string(lockfile) != expected { 107 t.Fatalf("wrong lockfile content") 108 } 109 } 110 111 func TestProvidersLock_args(t *testing.T) { 112 113 t.Run("mirror collision", func(t *testing.T) { 114 ui := new(cli.MockUi) 115 c := &ProvidersLockCommand{ 116 Meta: Meta{ 117 Ui: ui, 118 }, 119 } 120 121 // only one of these arguments can be used at a time 122 args := []string{ 123 "-fs-mirror=/foo/", 124 "-net-mirror=www.foo.com", 125 } 126 code := c.Run(args) 127 128 if code != 1 { 129 t.Fatalf("wrong exit code; expected 1, got %d", code) 130 } 131 output := ui.ErrorWriter.String() 132 if !strings.Contains(output, "The -fs-mirror and -net-mirror command line options are mutually-exclusive.") { 133 t.Fatalf("missing expected error message: %s", output) 134 } 135 }) 136 137 t.Run("invalid platform", func(t *testing.T) { 138 ui := new(cli.MockUi) 139 c := &ProvidersLockCommand{ 140 Meta: Meta{ 141 Ui: ui, 142 }, 143 } 144 145 // not a valid platform 146 args := []string{"-platform=arbitrary_nonsense_that_isnt_valid"} 147 code := c.Run(args) 148 149 if code != 1 { 150 t.Fatalf("wrong exit code; expected 1, got %d", code) 151 } 152 output := ui.ErrorWriter.String() 153 if !strings.Contains(output, "must be two words separated by an underscore.") { 154 t.Fatalf("missing expected error message: %s", output) 155 } 156 }) 157 158 t.Run("invalid provider argument", func(t *testing.T) { 159 ui := new(cli.MockUi) 160 c := &ProvidersLockCommand{ 161 Meta: Meta{ 162 Ui: ui, 163 }, 164 } 165 166 // There is no configuration, so it's not valid to use any provider argument 167 args := []string{"hashicorp/random"} 168 code := c.Run(args) 169 170 if code != 1 { 171 t.Fatalf("wrong exit code; expected 1, got %d", code) 172 } 173 output := ui.ErrorWriter.String() 174 if !strings.Contains(output, "The provider registry.terraform.io/hashicorp/random is not required by the\ncurrent configuration.") { 175 t.Fatalf("missing expected error message: %s", output) 176 } 177 }) 178 } 179 180 func TestProvidersLockCalculateChangeType(t *testing.T) { 181 provider := addrs.NewDefaultProvider("provider") 182 v2 := getproviders.MustParseVersion("2.0.0") 183 v2EqConstraints := getproviders.MustParseVersionConstraints("2.0.0") 184 185 t.Run("oldLock == nil", func(t *testing.T) { 186 platformLock := depsfile.NewProviderLock(provider, v2, v2EqConstraints, []getproviders.Hash{ 187 "9r3i9a9QmASqMnQM", 188 "K43RHM2klOoywtyW", 189 "swJPXfuCNhJsTM5c", 190 }) 191 192 if ct := providersLockCalculateChangeType(nil, platformLock); ct != providersLockChangeTypeNewProvider { 193 t.Fatalf("output was %s but should be %s", ct, providersLockChangeTypeNewProvider) 194 } 195 }) 196 197 t.Run("oldLock == platformLock", func(t *testing.T) { 198 platformLock := depsfile.NewProviderLock(provider, v2, v2EqConstraints, []getproviders.Hash{ 199 "9r3i9a9QmASqMnQM", 200 "K43RHM2klOoywtyW", 201 "swJPXfuCNhJsTM5c", 202 }) 203 204 oldLock := depsfile.NewProviderLock(provider, v2, v2EqConstraints, []getproviders.Hash{ 205 "9r3i9a9QmASqMnQM", 206 "K43RHM2klOoywtyW", 207 "swJPXfuCNhJsTM5c", 208 }) 209 210 if ct := providersLockCalculateChangeType(oldLock, platformLock); ct != providersLockChangeTypeNoChange { 211 t.Fatalf("output was %s but should be %s", ct, providersLockChangeTypeNoChange) 212 } 213 }) 214 215 t.Run("oldLock > platformLock", func(t *testing.T) { 216 platformLock := depsfile.NewProviderLock(provider, v2, v2EqConstraints, []getproviders.Hash{ 217 "9r3i9a9QmASqMnQM", 218 "K43RHM2klOoywtyW", 219 "swJPXfuCNhJsTM5c", 220 }) 221 222 oldLock := depsfile.NewProviderLock(provider, v2, v2EqConstraints, []getproviders.Hash{ 223 "9r3i9a9QmASqMnQM", 224 "1ZAChGWUMWn4zmIk", 225 "K43RHM2klOoywtyW", 226 "HWjRvIuWZ1LVatnc", 227 "swJPXfuCNhJsTM5c", 228 "KwhJK4p/U2dqbKhI", 229 }) 230 231 if ct := providersLockCalculateChangeType(oldLock, platformLock); ct != providersLockChangeTypeNoChange { 232 t.Fatalf("output was %s but should be %s", ct, providersLockChangeTypeNoChange) 233 } 234 }) 235 236 t.Run("oldLock < platformLock", func(t *testing.T) { 237 platformLock := depsfile.NewProviderLock(provider, v2, v2EqConstraints, []getproviders.Hash{ 238 "9r3i9a9QmASqMnQM", 239 "1ZAChGWUMWn4zmIk", 240 "K43RHM2klOoywtyW", 241 "HWjRvIuWZ1LVatnc", 242 "swJPXfuCNhJsTM5c", 243 "KwhJK4p/U2dqbKhI", 244 }) 245 246 oldLock := depsfile.NewProviderLock(provider, v2, v2EqConstraints, []getproviders.Hash{ 247 "9r3i9a9QmASqMnQM", 248 "K43RHM2klOoywtyW", 249 "swJPXfuCNhJsTM5c", 250 }) 251 252 if ct := providersLockCalculateChangeType(oldLock, platformLock); ct != providersLockChangeTypeNewHashes { 253 t.Fatalf("output was %s but should be %s", ct, providersLockChangeTypeNoChange) 254 } 255 }) 256 }