add -lock-file flag to providers mirror command

The providers mirror command was updated to inspect the lock file,
however that was not part of the original intent for the command, and
it's possible that the command needs to be run without a lock file.

Since we have been honoring the lock file for the past few releases,
let's keep that consistent and allow disabling the file with
`-lock-file=false`.
pull/35322/head
James Bardin 2 years ago
parent e57d8add35
commit 3875ea3656

@ -19,78 +19,97 @@ import (
// interacts directly with Terraform Registry and the full details of that are
// tricky to mock. Such a mock is _possible_, but we're using e2etest as a
// compromise for now to keep these tests relatively simple.
func TestTerraformProvidersMirror(t *testing.T) {
testTerraformProvidersMirror(t, "terraform-providers-mirror", "")
}
func TestTerraformProvidersMirrorWithLockFile(t *testing.T) {
testTerraformProvidersMirror(t, "terraform-providers-mirror-with-lock-file", "")
}
func TestTerraformProvidersMirrorWithBrokenLockFile(t *testing.T) {
testTerraformProvidersMirror(t, "terraform-providers-mirror-with-broken-lock-file", "Inconsistent dependency lock file")
}
func testTerraformProvidersMirror(t *testing.T, fixture string, errMsg string) {
// This test reaches out to releases.hashicorp.com to download the
// template and null providers, so it can only run if network access is
// allowed.
skipIfCannotAccessNetwork(t)
outputDir := t.TempDir()
t.Logf("creating mirror directory in %s", outputDir)
for _, test := range []struct {
name string
args []string
err string
}{
{
name: "terraform-providers-mirror",
args: []string{"-platform=linux_amd64", "-platform=windows_386"},
},
{
name: "terraform-providers-mirror-with-lock-file",
args: []string{"-platform=linux_amd64", "-platform=windows_386"},
},
{
// should ignore lock file
name: "terraform-providers-mirror-with-broken-lock-file",
args: []string{"-platform=linux_amd64", "-platform=windows_386", "-lock-file=false"},
},
{
name: "terraform-providers-mirror-with-broken-lock-file",
args: []string{"-platform=linux_amd64", "-platform=windows_386", "-lock-file=true"},
err: "Inconsistent dependency lock file",
},
} {
t.Run(test.name, func(t *testing.T) {
outputDir := t.TempDir()
t.Logf("creating mirror directory in %s", outputDir)
fixturePath := filepath.Join("testdata", fixture)
tf := e2e.NewBinary(t, terraformBin, fixturePath)
fixturePath := filepath.Join("testdata", test.name)
tf := e2e.NewBinary(t, terraformBin, fixturePath)
stdout, stderr, err := tf.Run("providers", "mirror", "-platform=linux_amd64", "-platform=windows_386", outputDir)
if errMsg != "" {
if !strings.Contains(stderr, errMsg) {
t.Fatalf("expected error %q, got %q\n", errMsg, stderr)
}
return
}
args := []string{"providers", "mirror"}
args = append(args, test.args...)
args = append(args, outputDir)
if err != nil {
t.Fatalf("unexpected error: %s\nstdout:\n%s\nstderr:\n%s", err, stdout, stderr)
}
stdout, stderr, err := tf.Run(args...)
if test.err != "" {
if !strings.Contains(stderr, test.err) {
t.Fatalf("expected error %q, got %q\n", test.err, stderr)
}
return
}
// The test fixture includes exact version constraints for the two
// providers it depends on so that the following should remain stable.
// In the (unlikely) event that these particular versions of these
// providers are removed from the registry, this test will start to fail.
want := []string{
"registry.terraform.io/hashicorp/null/2.1.0.json",
"registry.terraform.io/hashicorp/null/index.json",
"registry.terraform.io/hashicorp/null/terraform-provider-null_2.1.0_linux_amd64.zip",
"registry.terraform.io/hashicorp/null/terraform-provider-null_2.1.0_windows_386.zip",
"registry.terraform.io/hashicorp/template/2.1.1.json",
"registry.terraform.io/hashicorp/template/index.json",
"registry.terraform.io/hashicorp/template/terraform-provider-template_2.1.1_linux_amd64.zip",
"registry.terraform.io/hashicorp/template/terraform-provider-template_2.1.1_windows_386.zip",
}
var got []string
walkErr := filepath.Walk(outputDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil // we only care about leaf files for this test
}
relPath, err := filepath.Rel(outputDir, path)
if err != nil {
return err
}
got = append(got, filepath.ToSlash(relPath))
return nil
})
if walkErr != nil {
t.Fatal(walkErr)
}
sort.Strings(got)
if err != nil {
t.Fatalf("unexpected error: %s\nstdout:\n%s\nstderr:\n%s", err, stdout, stderr)
}
// The test fixture includes exact version constraints for the two
// providers it depends on so that the following should remain stable.
// In the (unlikely) event that these particular versions of these
// providers are removed from the registry, this test will start to fail.
want := []string{
"registry.terraform.io/hashicorp/null/2.1.0.json",
"registry.terraform.io/hashicorp/null/index.json",
"registry.terraform.io/hashicorp/null/terraform-provider-null_2.1.0_linux_amd64.zip",
"registry.terraform.io/hashicorp/null/terraform-provider-null_2.1.0_windows_386.zip",
"registry.terraform.io/hashicorp/template/2.1.1.json",
"registry.terraform.io/hashicorp/template/index.json",
"registry.terraform.io/hashicorp/template/terraform-provider-template_2.1.1_linux_amd64.zip",
"registry.terraform.io/hashicorp/template/terraform-provider-template_2.1.1_windows_386.zip",
}
var got []string
walkErr := filepath.Walk(outputDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil // we only care about leaf files for this test
}
relPath, err := filepath.Rel(outputDir, path)
if err != nil {
return err
}
got = append(got, filepath.ToSlash(relPath))
return nil
})
if walkErr != nil {
t.Fatal(walkErr)
}
sort.Strings(got)
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("unexpected files in result\n%s", diff)
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("unexpected files in result\n%s", diff)
})
}
}

@ -1,7 +1,7 @@
terraform {
required_providers {
template = { source = "hashicorp/template" }
null = { source = "hashicorp/null" }
template = { version = "2.1.1" }
null = { source = "hashicorp/null", version = "2.1.0" }
terraform = { source = "terraform.io/builtin/terraform" }
}
}

@ -34,8 +34,13 @@ func (c *ProvidersMirrorCommand) Synopsis() string {
func (c *ProvidersMirrorCommand) Run(args []string) int {
args = c.Meta.process(args)
cmdFlags := c.Meta.defaultFlagSet("providers mirror")
var optPlatforms arguments.FlagStringSlice
cmdFlags.Var(&optPlatforms, "platform", "target platform")
var optLockFile bool
cmdFlags.BoolVar(&optLockFile, "lock-file", true, "use lock file")
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
if err := cmdFlags.Parse(args); err != nil {
c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
@ -89,7 +94,7 @@ func (c *ProvidersMirrorCommand) Run(args []string) int {
diags = diags.Append(lockedDepsDiags)
// If lock file is present, validate it against configuration
if !lockedDeps.Empty() {
if !lockedDeps.Empty() && optLockFile {
if errs := config.VerifyDependencySelections(lockedDeps); len(errs) > 0 {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
@ -161,7 +166,7 @@ func (c *ProvidersMirrorCommand) Run(args []string) int {
continue
}
selected := candidates.Newest()
if !lockedDeps.Empty() {
if !lockedDeps.Empty() && optLockFile {
selected = lockedDeps.Provider(provider).Version()
c.Ui.Output(fmt.Sprintf(" - Selected v%s to match dependency lock file", selected.String()))
} else if len(constraintsStr) > 0 {

Loading…
Cancel
Save