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  }