diff --git a/command/e2etest/automation_test.go b/command/e2etest/automation_test.go index 8c51f381b..80495fa1e 100644 --- a/command/e2etest/automation_test.go +++ b/command/e2etest/automation_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/davecgh/go-spew/spew" "github.com/hashicorp/terraform/e2e" ) @@ -41,11 +40,11 @@ func TestPlanApplyInAutomation(t *testing.T) { // Make sure we actually downloaded the plugins, rather than picking up // copies that might be already installed globally on the system. - if !strings.Contains(stdout, "- Downloading plugin for provider \"template\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"template") { t.Errorf("template provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } - if !strings.Contains(stdout, "- Downloading plugin for provider \"null\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"null") { t.Errorf("null provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } @@ -71,14 +70,11 @@ func TestPlanApplyInAutomation(t *testing.T) { t.Fatalf("failed to read plan file: %s", err) } - stateResources := plan.State.RootModule().Resources - diffResources := plan.Diff.RootModule().Resources + // stateResources := plan.Changes.Resources + diffResources := plan.Changes.Resources - if len(stateResources) != 1 || stateResources["data.template_file.test"] == nil { - t.Errorf("incorrect state in plan; want just data.template_file.test to have been rendered, but have:\n%s", spew.Sdump(stateResources)) - } - if len(diffResources) != 1 || diffResources["null_resource.test"] == nil { - t.Errorf("incorrect diff in plan; want just null_resource.test to have been rendered, but have:\n%s", spew.Sdump(diffResources)) + if len(diffResources) != 1 || diffResources[0].Addr.String() != "null_resource.test" { + t.Errorf("incorrect number of resources in plan") } //// APPLY @@ -96,9 +92,9 @@ func TestPlanApplyInAutomation(t *testing.T) { t.Fatalf("failed to read state file: %s", err) } - stateResources = state.RootModule().Resources + stateResources := state.RootModule().Resources var gotResources []string - for n := range stateResources { + for n, _ := range stateResources { gotResources = append(gotResources, n) } sort.Strings(gotResources) @@ -139,11 +135,11 @@ func TestAutoApplyInAutomation(t *testing.T) { // Make sure we actually downloaded the plugins, rather than picking up // copies that might be already installed globally on the system. - if !strings.Contains(stdout, "- Downloading plugin for provider \"template\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"template") { t.Errorf("template provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } - if !strings.Contains(stdout, "- Downloading plugin for provider \"null\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"null") { t.Errorf("null provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } @@ -206,11 +202,11 @@ func TestPlanOnlyInAutomation(t *testing.T) { // Make sure we actually downloaded the plugins, rather than picking up // copies that might be already installed globally on the system. - if !strings.Contains(stdout, "- Downloading plugin for provider \"template\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"template") { t.Errorf("template provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } - if !strings.Contains(stdout, "- Downloading plugin for provider \"null\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"null") { t.Errorf("null provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } diff --git a/command/e2etest/init_test.go b/command/e2etest/init_test.go index a80ba7db3..50e1fe3e9 100644 --- a/command/e2etest/init_test.go +++ b/command/e2etest/init_test.go @@ -39,7 +39,7 @@ func TestInitProviders(t *testing.T) { t.Errorf("success message is missing from output:\n%s", stdout) } - if !strings.Contains(stdout, "- Downloading plugin for provider \"template\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"template\" (terraform-providers/template)") { t.Errorf("provider download message is missing from output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } @@ -112,10 +112,10 @@ func TestInitProviders_pluginCache(t *testing.T) { stderr := cmd.Stderr.(*bytes.Buffer).String() if stderr != "" { - t.Errorf("unexpected stderr output:\n%s", stderr) + t.Errorf("unexpected stderr output:\n%s\n", stderr) } - path := fmt.Sprintf(".terraform/plugins/%s_%s/terraform-provider-template_v0.1.0_x4", runtime.GOOS, runtime.GOARCH) + path := fmt.Sprintf(".terraform/plugins/%s_%s/terraform-provider-template_v2.1.0_x4", runtime.GOOS, runtime.GOARCH) content, err := tf.ReadFile(path) if err != nil { t.Fatalf("failed to read installed plugin from %s: %s", path, err) @@ -124,11 +124,11 @@ func TestInitProviders_pluginCache(t *testing.T) { t.Errorf("template plugin was not installed from local cache") } - if !tf.FileExists(fmt.Sprintf(".terraform/plugins/%s_%s/terraform-provider-null_v0.1.0_x4", runtime.GOOS, runtime.GOARCH)) { + if !tf.FileExists(fmt.Sprintf(".terraform/plugins/%s_%s/terraform-provider-null_v2.1.0_x4", runtime.GOOS, runtime.GOARCH)) { t.Errorf("null plugin was not installed") } - if !tf.FileExists(fmt.Sprintf("cache/%s_%s/terraform-provider-null_v0.1.0_x4", runtime.GOOS, runtime.GOARCH)) { + if !tf.FileExists(fmt.Sprintf("cache/%s_%s/terraform-provider-null_v2.1.0_x4", runtime.GOOS, runtime.GOARCH)) { t.Errorf("null plugin is not in cache after install") } } diff --git a/command/e2etest/main_test.go b/command/e2etest/main_test.go index a053e501e..64dc8f148 100644 --- a/command/e2etest/main_test.go +++ b/command/e2etest/main_test.go @@ -56,10 +56,4 @@ func skipIfCannotAccessNetwork(t *testing.T) { if !canAccessNetwork() { t.Skip("network access not allowed; use TF_ACC=1 to enable") } - - // During the early part of the Terraform v0.12 release process, certain - // upstream resources are not yet ready to support it and so these - // tests cannot be run. These will be re-enabled prior to Terraform v0.12.0 - // final. - t.Skip("all tests with external network access are temporarily disabled until upstream services are updated") } diff --git a/command/e2etest/primary_test.go b/command/e2etest/primary_test.go index fb825e477..dd5b1160a 100644 --- a/command/e2etest/primary_test.go +++ b/command/e2etest/primary_test.go @@ -38,11 +38,11 @@ func TestPrimarySeparatePlan(t *testing.T) { // Make sure we actually downloaded the plugins, rather than picking up // copies that might be already installed globally on the system. - if !strings.Contains(stdout, "- Downloading plugin for provider \"template\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"template") { t.Errorf("template provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } - if !strings.Contains(stdout, "- Downloading plugin for provider \"null\"") { + if !strings.Contains(stdout, "- Downloading plugin for provider \"null") { t.Errorf("null provider download message is missing from init output:\n%s", stdout) t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") } @@ -69,13 +69,8 @@ func TestPrimarySeparatePlan(t *testing.T) { t.Fatalf("failed to read plan file: %s", err) } - stateResources := plan.State.RootModule().Resources - diffResources := plan.Diff.RootModule().Resources - - if len(stateResources) != 1 || stateResources["data.template_file.test"] == nil { - t.Errorf("incorrect state in plan; want just data.template_file.test to have been rendered, but have:\n%s", spew.Sdump(stateResources)) - } - if len(diffResources) != 1 || diffResources["null_resource.test"] == nil { + diffResources := plan.Changes.Resources + if len(diffResources) != 1 || diffResources[0].Addr.String() != "null_resource.test" { t.Errorf("incorrect diff in plan; want just null_resource.test to have been rendered, but have:\n%s", spew.Sdump(diffResources)) } @@ -94,9 +89,9 @@ func TestPrimarySeparatePlan(t *testing.T) { t.Fatalf("failed to read state file: %s", err) } - stateResources = state.RootModule().Resources + stateResources := state.RootModule().Resources var gotResources []string - for n := range stateResources { + for n, _ := range stateResources { gotResources = append(gotResources, n) } sort.Strings(gotResources) diff --git a/command/e2etest/test-fixtures/plugin-cache/cache/os_arch/terraform-provider-template_v0.1.0_x4 b/command/e2etest/test-fixtures/plugin-cache/cache/os_arch/terraform-provider-template_v2.1.0_x4 similarity index 100% rename from command/e2etest/test-fixtures/plugin-cache/cache/os_arch/terraform-provider-template_v0.1.0_x4 rename to command/e2etest/test-fixtures/plugin-cache/cache/os_arch/terraform-provider-template_v2.1.0_x4 diff --git a/command/e2etest/test-fixtures/plugin-cache/main.tf b/command/e2etest/test-fixtures/plugin-cache/main.tf index 94bae0fa2..f52d48294 100644 --- a/command/e2etest/test-fixtures/plugin-cache/main.tf +++ b/command/e2etest/test-fixtures/plugin-cache/main.tf @@ -1,7 +1,7 @@ provider "template" { - version = "0.1.0" + version = "2.1.0" } provider "null" { - version = "0.1.0" + version = "2.1.0" } diff --git a/e2e/e2e.go b/e2e/e2e.go index 23ebc121c..2262f5a1e 100644 --- a/e2e/e2e.go +++ b/e2e/e2e.go @@ -9,7 +9,10 @@ import ( "os/exec" "path/filepath" - tfcore "github.com/hashicorp/terraform/terraform" + "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/plans/planfile" + "github.com/hashicorp/terraform/states" + "github.com/hashicorp/terraform/states/statefile" ) // Type binary represents the combination of a compiled binary @@ -48,6 +51,12 @@ func NewBinary(binaryPath, workingDir string) *binary { return nil } + if filepath.Base(path) == ".exists" { + // We use this file just to let git know the "empty" fixture + // exists. It is not used by any test. + return nil + } + srcFn := path path, err = filepath.Rel(workingDir, path) @@ -170,43 +179,52 @@ func (b *binary) FileExists(path ...string) bool { // LocalState is a helper for easily reading the local backend's state file // terraform.tfstate from the working directory. -func (b *binary) LocalState() (*tfcore.State, error) { +func (b *binary) LocalState() (*states.State, error) { f, err := b.OpenFile("terraform.tfstate") if err != nil { return nil, err } defer f.Close() - return tfcore.ReadState(f) + + stateFile, err := statefile.Read(f) + if err != nil { + return nil, fmt.Errorf("Error reading statefile: %s", err) + } + return stateFile.State, nil } // Plan is a helper for easily reading a plan file from the working directory. -func (b *binary) Plan(path ...string) (*tfcore.Plan, error) { - f, err := b.OpenFile(path...) +func (b *binary) Plan(path string) (*plans.Plan, error) { + path = b.Path(path) + pr, err := planfile.Open(path) if err != nil { return nil, err } - defer f.Close() - return tfcore.ReadPlan(f) + plan, err := pr.ReadPlan() + if err != nil { + return nil, err + } + return plan, nil } // SetLocalState is a helper for easily writing to the file the local backend // uses for state in the working directory. This does not go through the // actual local backend code, so processing such as management of serials // does not apply and the given state will simply be written verbatim. -func (b *binary) SetLocalState(state *tfcore.State) error { +func (b *binary) SetLocalState(state *states.State) error { path := b.Path("terraform.tfstate") f, err := os.OpenFile(path, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, os.ModePerm) if err != nil { - return err + return fmt.Errorf("failed to create temporary state file %s: %s", path, err) } - defer func() { - err := f.Close() - if err != nil { - panic(fmt.Sprintf("failed to close state file after writing: %s", err)) - } - }() + defer f.Close() - return tfcore.WriteState(state, f) + sf := &statefile.File{ + Serial: 0, + Lineage: "fake-for-testing", + State: state, + } + return statefile.Write(sf, f) } // Close cleans up the temporary resources associated with the object, diff --git a/plugin/discovery/get.go b/plugin/discovery/get.go index 1b70c5178..b1d01fb9a 100644 --- a/plugin/discovery/get.go +++ b/plugin/discovery/get.go @@ -298,7 +298,7 @@ func (i *ProviderInstaller) install(provider string, version Version, url string // check if the target dir exists, and create it if not var err error if _, StatErr := os.Stat(i.Dir); os.IsNotExist(StatErr) { - err = os.Mkdir(i.Dir, 0700) + err = os.MkdirAll(i.Dir, 0700) } if err != nil { return err