| // Copyright IBM Corp. 2014, 2026 | |
| // SPDX-License-Identifier: BUSL-1.1 | |
| package views | |
| import ( | |
| "fmt" | |
| "strings" | |
| "testing" | |
| "github.com/apparentlymart/go-versions/versions" | |
| "github.com/google/go-cmp/cmp" | |
| "github.com/hashicorp/hcl/v2" | |
| "github.com/hashicorp/terraform/internal/addrs" | |
| "github.com/hashicorp/terraform/internal/command/arguments" | |
| viewjson "github.com/hashicorp/terraform/internal/command/views/json" | |
| "github.com/hashicorp/terraform/internal/getproviders" | |
| "github.com/hashicorp/terraform/internal/policy" | |
| "github.com/hashicorp/terraform/internal/terminal" | |
| "github.com/hashicorp/terraform/internal/tfdiags" | |
| tfversion "github.com/hashicorp/terraform/version" | |
| ) | |
| func TestNewInit_jsonViewDiagnostics(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitJSON); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| diags := getTestDiags(t) | |
| newInit.Diagnostics(diags) | |
| version := tfversion.String() | |
| want := []map[string]interface{}{ | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("Terraform %s", version), | |
| "@module": "terraform.ui", | |
| "terraform": version, | |
| "type": "version", | |
| "ui": JSON_UI_VERSION, | |
| }, | |
| { | |
| "@level": "error", | |
| "@message": "Error: Error selecting workspace", | |
| "@module": "terraform.ui", | |
| "diagnostic": map[string]interface{}{ | |
| "severity": "error", | |
| "summary": "Error selecting workspace", | |
| "detail": "Workspace random_pet does not exist", | |
| }, | |
| "type": "diagnostic", | |
| }, | |
| { | |
| "@level": "error", | |
| "@message": "Error: Unsupported backend type", | |
| "@module": "terraform.ui", | |
| "diagnostic": map[string]interface{}{ | |
| "severity": "error", | |
| "summary": "Unsupported backend type", | |
| "detail": "There is no explicit backend type named fake backend.", | |
| }, | |
| "type": "diagnostic", | |
| }, | |
| } | |
| actual := done(t).Stdout() | |
| testJSONViewOutputEqualsFull(t, actual, want) | |
| } | |
| func TestNewInit_humanViewDiagnostics(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitHuman); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| diags := getTestDiags(t) | |
| newInit.Diagnostics(diags) | |
| actual := done(t).All() | |
| expected := "\nError: Error selecting workspace\n\nWorkspace random_pet does not exist\n\nError: Unsupported backend type\n\nThere is no explicit backend type named fake backend.\n" | |
| if !strings.Contains(actual, expected) { | |
| t.Fatalf("expected output to contain: %s, but got %s", expected, actual) | |
| } | |
| } | |
| func TestNewInit_unsupportedViewDiagnostics(t *testing.T) { | |
| defer func() { | |
| r := recover() | |
| if r == nil { | |
| t.Fatalf("should panic with unsupported view type raw") | |
| } else if r != "unknown view type raw" { | |
| t.Fatalf("unexpected panic message: %v", r) | |
| } | |
| }() | |
| streams, done := terminal.StreamsForTesting(t) | |
| defer done(t) | |
| NewInit(arguments.ViewRaw, NewView(streams).SetRunningInAutomation(true)) | |
| } | |
| func getTestDiags(t *testing.T) tfdiags.Diagnostics { | |
| t.Helper() | |
| var diags tfdiags.Diagnostics | |
| diags = diags.Append( | |
| tfdiags.Sourceless( | |
| tfdiags.Error, | |
| "Error selecting workspace", | |
| "Workspace random_pet does not exist", | |
| ), | |
| &hcl.Diagnostic{ | |
| Severity: hcl.DiagError, | |
| Summary: "Unsupported backend type", | |
| Detail: "There is no explicit backend type named fake backend.", | |
| Subject: nil, | |
| }, | |
| ) | |
| return diags | |
| } | |
| func TestNewInit_jsonViewPolicyResults(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitJSON); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| newInit.PolicyResult( | |
| addrs.RootModule.Child("example").String(), | |
| policy.EvaluationResponse{ | |
| Overall: policy.DenyResult, | |
| Diagnostics: policy.Diagnostics{ | |
| policy.NewErrorDiagnostic( | |
| "module policy denied", | |
| "module policy blocked installation", | |
| policy.DenyResult, | |
| ), | |
| }, | |
| Policies: []*policy.Policy{ | |
| { | |
| Address: "module_policy.example", | |
| Filename: "policy_file.tfpolicy.hcl", | |
| EnforcementLevel: "mandatory", | |
| Result: policy.DenyResult, | |
| }, | |
| }, | |
| }, | |
| ) | |
| version := tfversion.String() | |
| want := []map[string]interface{}{ | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("Terraform %s", version), | |
| "@module": "terraform.ui", | |
| "terraform": version, | |
| "type": "version", | |
| "ui": JSON_UI_VERSION, | |
| }, | |
| { | |
| "@level": "error", | |
| "@message": "Error: module policy denied", | |
| "@module": "terraform.ui", | |
| "@policy": "true", | |
| "policy_diagnostic": map[string]interface{}{ | |
| "severity": "error", | |
| "summary": "module policy denied", | |
| "detail": "module policy blocked installation", | |
| }, | |
| "policy_metadata": map[string]interface{}{}, | |
| "result": policy.DenyResult.String(), | |
| "target_address": "module.example", | |
| "type": string(viewjson.MessagePolicyDiagnostic), | |
| }, | |
| { | |
| "@level": "info", | |
| "@message": "Policy Result", | |
| "@module": "terraform.ui", | |
| "@policy": "true", | |
| "target_address": "module.example", | |
| "policy_address": "module_policy.example", | |
| "policy_metadata": map[string]interface{}{ | |
| "policy_name": "module_policy.example", | |
| "file_name": "policy_file.tfpolicy.hcl", | |
| "enforcement_level": "mandatory", | |
| }, | |
| "result": policy.DenyResult.String(), | |
| "type": string(viewjson.MessagePolicyEvaluationResult), | |
| }, | |
| } | |
| actual := done(t).Stdout() | |
| testJSONViewOutputEqualsFull(t, actual, want) | |
| } | |
| func TestNewInit_humanViewPolicyResults(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitHuman); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| newInit.PolicyResult( | |
| addrs.RootModule.Child("example").String(), | |
| policy.EvaluationResponse{ | |
| Overall: policy.DenyResult, | |
| Diagnostics: policy.Diagnostics{ | |
| policy.NewErrorDiagnostic( | |
| "module policy denied", | |
| "module policy blocked installation", | |
| policy.DenyResult, | |
| ), | |
| }, | |
| }, | |
| ) | |
| actual := done(t).All() | |
| expected := "\nError: module policy denied\n\nmodule policy blocked installation\n" | |
| if !strings.Contains(actual, expected) { | |
| t.Fatalf("expected output to contain: %s, but got %s", expected, actual) | |
| } | |
| } | |
| func TestNewInit_humanViewPolicyResults_infoWithoutSnippet(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitHuman); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| newInit.PolicyResult( | |
| addrs.RootModule.Child("example").String(), | |
| policy.EvaluationResponse{ | |
| Overall: policy.AllowResult, | |
| Enforcements: []policy.EnforcementResult{{ | |
| Result: policy.AllowResult, | |
| Message: "module policy allowed installation", | |
| Policy: &policy.Policy{ | |
| Address: "module_policy.example", | |
| }, | |
| }}, | |
| }, | |
| ) | |
| actual := done(t).Stdout() | |
| if !strings.Contains(actual, "Policy Info:") { | |
| t.Fatalf("expected output to contain policy info header, but got %s", actual) | |
| } | |
| if !strings.Contains(actual, "module policy allowed installation") { | |
| t.Fatalf("expected output to contain policy message, but got %s", actual) | |
| } | |
| if !strings.Contains(actual, "module_policy.example") { | |
| t.Fatalf("expected output to contain policy address fallback, but got %s", actual) | |
| } | |
| } | |
| func TestNewInit_jsonViewOutput(t *testing.T) { | |
| t.Run("no param", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitJSON); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| newInit.Output(InitializingProviderPluginMessage) | |
| version := tfversion.String() | |
| want := []map[string]any{ | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("Terraform %s", version), | |
| "@module": "terraform.ui", | |
| "terraform": version, | |
| "type": "version", | |
| "ui": JSON_UI_VERSION, | |
| }, | |
| { | |
| "@level": "info", | |
| "@message": "Initializing provider plugins...", | |
| "message_code": "initializing_provider_plugin_message", | |
| "@module": "terraform.ui", | |
| "type": "init_output", | |
| }, | |
| } | |
| actual := done(t).Stdout() | |
| testJSONViewOutputEqualsFull(t, actual, want) | |
| }) | |
| t.Run("single param", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitJSON); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| packageName := "hashicorp/aws" | |
| newInit.Output(FindingLatestVersionMessage, packageName) | |
| version := tfversion.String() | |
| want := []map[string]interface{}{ | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("Terraform %s", version), | |
| "@module": "terraform.ui", | |
| "terraform": version, | |
| "type": "version", | |
| "ui": JSON_UI_VERSION, | |
| }, | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("%s: Finding latest version...", packageName), | |
| "@module": "terraform.ui", | |
| "message_code": "finding_latest_version_message", | |
| "type": "init_output", | |
| }, | |
| } | |
| actual := done(t).Stdout() | |
| testJSONViewOutputEqualsFull(t, actual, want) | |
| }) | |
| t.Run("variable length params", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitJSON); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| packageName, packageVersion := "hashicorp/aws", "3.0.0" | |
| newInit.Output(ProviderAlreadyInstalledMessage, packageName, packageVersion) | |
| version := tfversion.String() | |
| want := []map[string]interface{}{ | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("Terraform %s", version), | |
| "@module": "terraform.ui", | |
| "terraform": version, | |
| "type": "version", | |
| "ui": JSON_UI_VERSION, | |
| }, | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("%s v%s: Using previously-installed provider version", packageName, packageVersion), | |
| "@module": "terraform.ui", | |
| "message_code": "provider_already_installed_message", | |
| "type": "init_output", | |
| }, | |
| } | |
| actual := done(t).Stdout() | |
| testJSONViewOutputEqualsFull(t, actual, want) | |
| }) | |
| } | |
| func TestNewInit_jsonViewLog(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitJSON); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| newInit.Output(InitializingProviderPluginMessage) | |
| version := tfversion.String() | |
| want := []map[string]interface{}{ | |
| { | |
| "@level": "info", | |
| "@message": fmt.Sprintf("Terraform %s", version), | |
| "@module": "terraform.ui", | |
| "terraform": version, | |
| "type": "version", | |
| "ui": JSON_UI_VERSION, | |
| }, | |
| { | |
| "@level": "info", | |
| "@message": "Initializing provider plugins...", | |
| "@module": "terraform.ui", | |
| "message_code": "initializing_provider_plugin_message", | |
| "type": "init_output", | |
| }, | |
| } | |
| actual := done(t).Stdout() | |
| testJSONViewOutputEqualsFull(t, actual, want) | |
| } | |
| func TestNewInit_jsonViewPrepareMessage(t *testing.T) { | |
| t.Run("existing message code", func(t *testing.T) { | |
| streams, _ := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitJSON); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| want := "Initializing modules..." | |
| actual := newInit.prepareMessage(InitializingModulesMessage) | |
| if !cmp.Equal(want, actual) { | |
| t.Errorf("unexpected output: %s", cmp.Diff(want, actual)) | |
| } | |
| }) | |
| } | |
| func TestNewInit_humanViewOutput(t *testing.T) { | |
| t.Run("no param", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitHuman); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| newInit.Output(InitializingProviderPluginMessage) | |
| actual := done(t).All() | |
| expected := "Initializing provider plugins..." | |
| if !strings.Contains(actual, expected) { | |
| t.Fatalf("expected output to contain: %s, but got %s", expected, actual) | |
| } | |
| }) | |
| t.Run("single param", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitHuman); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| packageName := "hashicorp/aws" | |
| newInit.Output(FindingLatestVersionMessage, packageName) | |
| actual := done(t).All() | |
| expected := "Finding latest version of hashicorp/aws" | |
| if !strings.Contains(actual, expected) { | |
| t.Fatalf("expected output to contain: %s, but got %s", expected, actual) | |
| } | |
| }) | |
| t.Run("variable length params", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true)) | |
| if _, ok := newInit.(*InitHuman); !ok { | |
| t.Fatalf("unexpected return type %t", newInit) | |
| } | |
| packageName, packageVersion := "hashicorp/aws", "3.0.0" | |
| newInit.Output(ProviderAlreadyInstalledMessage, packageName, packageVersion) | |
| actual := done(t).All() | |
| expected := "- Using previously-installed hashicorp/aws v3.0.0" | |
| if !strings.Contains(actual, expected) { | |
| t.Fatalf("expected output to contain: %s, but got %s", expected, actual) | |
| } | |
| }) | |
| } | |
| // Assert message content | |
| func TestNewInit_LogProviderVersionSuccess(t *testing.T) { | |
| const verifiedChecksum = 0 | |
| const officialProvider = 1 | |
| const noKey = "" | |
| t.Run("no auth result - human view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewHuman, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| var authResult *getproviders.PackageAuthenticationResult = nil | |
| initView.LogProviderVersionSuccess(p, ver, authResult) | |
| // Assert output | |
| output := done(t) | |
| expectedOutput := "- Installed hashicorp/test v1.2.3 (unauthenticated)\n" | |
| if output.Stdout() != expectedOutput { | |
| t.Fatalf("expected %q, got %q", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| t.Run("no auth result - json view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| var authResult *getproviders.PackageAuthenticationResult = nil | |
| initView.LogProviderVersionSuccess(p, ver, authResult) | |
| // Assert output - human | |
| output := done(t) | |
| expectedOutput := `"@message":"Installed provider version: hashicorp/test v1.2.3 (unauthenticated)"` | |
| if !strings.Contains(output.Stdout(), expectedOutput) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| t.Run("verified checksum auth result - human view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewHuman, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| authResult := getproviders.NewPackageAuthenticationResult(verifiedChecksum, noKey) | |
| initView.LogProviderVersionSuccess(p, ver, authResult) | |
| // Assert output | |
| output := done(t) | |
| expectedOutput := "- Installed hashicorp/test v1.2.3 (verified checksum)\n" | |
| if output.Stdout() != expectedOutput { | |
| t.Fatalf("expected %q, got %q", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| t.Run("verified checksum auth result - json view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| authResult := getproviders.NewPackageAuthenticationResult(verifiedChecksum, noKey) | |
| initView.LogProviderVersionSuccess(p, ver, authResult) | |
| // Assert output - human | |
| output := done(t) | |
| expectedOutput := `"@message":"Installed provider version: hashicorp/test v1.2.3 (verified checksum)"` | |
| if !strings.Contains(output.Stdout(), expectedOutput) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| t.Run("official provider auth result - human view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewHuman, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| key := "key-id-123" | |
| authResult := getproviders.NewPackageAuthenticationResult(officialProvider, key) | |
| initView.LogProviderVersionSuccess(p, ver, authResult) | |
| // Assert output | |
| output := done(t) | |
| expectedOutput := "- Installed hashicorp/test v1.2.3 (signed by HashiCorp)\n" | |
| if output.Stdout() != expectedOutput { | |
| t.Fatalf("expected %q, got %q", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| t.Run("official provider auth result - json view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| key := "key-id-123" | |
| authResult := getproviders.NewPackageAuthenticationResult(officialProvider, key) | |
| initView.LogProviderVersionSuccess(p, ver, authResult) | |
| // Assert output - human | |
| output := done(t) | |
| expectedOutput := `"@message":"Installed provider version: hashicorp/test v1.2.3 (signed by HashiCorp)"` | |
| if !strings.Contains(output.Stdout(), expectedOutput) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| } | |
| // Assert message content | |
| func TestNewInit_LogProviderVersionSuccessWithKeyID(t *testing.T) { | |
| const partnerProvider = 2 | |
| t.Run("partner provider auth result - human view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewHuman, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| key := "key-id-123" | |
| authResult := getproviders.NewPackageAuthenticationResult(partnerProvider, key) | |
| initView.LogProviderVersionSuccessWithKeyID(p, ver, authResult, key) | |
| // Assert output - human | |
| output := done(t) | |
| expectedOutput := "- Installed hashicorp/test v1.2.3 (signed by a HashiCorp partner, key ID key-id-123)\n" | |
| if output.Stdout() != expectedOutput { | |
| t.Fatalf("expected %q, got %q", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| t.Run("partner provider auth result -json view", func(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| ver := getproviders.MustParseVersion("1.2.3") | |
| key := "key-id-123" | |
| authResult := getproviders.NewPackageAuthenticationResult(partnerProvider, key) | |
| initView.LogProviderVersionSuccessWithKeyID(p, ver, authResult, key) | |
| // Assert output - human | |
| output := done(t) | |
| expectedOutput := `{"@level":"info","@message":"Installed provider version: hashicorp/test v1.2.3 (signed by a HashiCorp partnerkey_id: key-id-123)","@module":"terraform.ui","@timestamp":` // Stop comparison before timestamp | |
| if !strings.Contains(output.Stdout(), expectedOutput) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", expectedOutput, output.Stdout()) | |
| } | |
| }) | |
| } | |
| // Assert JSON log content, including log type and additional fields | |
| func TestNewInit_LogProviderVersionSuccess_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| v := versions.MustParseVersion("1.0.0") | |
| officialProvider := 1 | |
| authResult := getproviders.NewPackageAuthenticationResult(officialProvider, "key-id-123") | |
| initView.LogProviderVersionSuccess(p, v, authResult) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"Installed provider version: hashicorp/test v1.0.0 (signed by HashiCorp)"`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogProviderVersionAlreadyInstalled_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| v := versions.MustParseVersion("1.0.0") | |
| initView.LogProviderVersionAlreadyInstalled(p, v) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"hashicorp/test v1.0.0: Using previously-installed provider version"`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| // Assert JSON log content, including log type and additional fields | |
| // | |
| // Note - in calling code this is only ever used for partner providers | |
| func TestNewInit_LogProviderVersionSuccessWithKeyID_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| v := versions.MustParseVersion("1.0.0") | |
| partnerProvider := 2 | |
| keyID := "key-id-123" | |
| authResult := getproviders.NewPackageAuthenticationResult(partnerProvider, keyID) | |
| initView.LogProviderVersionSuccessWithKeyID(p, v, authResult, keyID) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"Installed provider version: hashicorp/test v1.0.0 (signed by a HashiCorp partnerkey_id: key-id-123)"`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogReusingPreviousProviderVersion_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| initView.LogReusingPreviousProviderVersion(p) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"hashicorp/test: Reusing previous version from the dependency lock file"`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogFindingMatchingVersion_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| constraint, _ := getproviders.ParseVersionConstraints("1.0.0") | |
| initView.LogFindingMatchingVersion(p, constraint) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"Finding matching versions for provider: hashicorp/test, version_constraint: \"1.0.0\""`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogFindingLatestVersion_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| initView.LogFindingLatestVersion(p) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"hashicorp/test: Finding latest version..."`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogInstallingProviderVersion_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| v := versions.MustParseVersion("1.0.0") | |
| initView.LogInstallingProviderVersion(p, v) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"Installing provider version: hashicorp/test v1.0.0..."`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogBuiltInProviderAvailable_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| initView.LogBuiltInProviderAvailable(p) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"hashicorp/test is built in to Terraform"`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogUsingProviderVersionFromCacheDir_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| p := addrs.MustParseProviderSourceString("hashicorp/test") | |
| v := versions.MustParseVersion("1.0.0") | |
| initView.LogUsingProviderVersionFromCacheDir(p, v) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"hashicorp/test v1.0.0: Using from the shared cache directory"`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogPartnerAndCommunityProviders_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| initView.LogPartnerAndCommunityProviders() | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"Partner and community providers are signed by their developers.\nIf you'd like to know more about provider signing, you can read about it here:\nhttps://developer.hashicorp.com/terraform/cli/plugins/signing"`, | |
| `"@module":"terraform.ui"`, | |
| `"type":"log"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_LogInitializingStateStoreProviderPlugin_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| storeType := "test_store" | |
| initView.LogInitializingStateStoreProviderPlugin(storeType) | |
| // Assert output | |
| output := done(t) | |
| expectedOutputFields := []string{ | |
| `"@level":"info"`, | |
| `"@message":"Initializing provider plugin for state store \"test_store\"..."`, | |
| `"@module":"terraform.ui"`, | |
| //@timestamp is dynamic | |
| `"message_code":"initializing_state_store_provider_plugin_message"`, | |
| `"type":"init_output"`, | |
| } | |
| for _, snippet := range expectedOutputFields { | |
| if !strings.Contains(output.Stdout(), snippet) { | |
| t.Fatalf("output didn't include expected snippet:\n expected: %s\n got:\n %s", snippet, output.Stdout()) | |
| } | |
| } | |
| } | |
| func TestNewInit_Spacer_json(t *testing.T) { | |
| streams, done := terminal.StreamsForTesting(t) | |
| view := NewView(streams) | |
| initView := NewInit(arguments.ViewJSON, view) | |
| initView.Spacer() | |
| // Assert output | |
| output := done(t) | |
| // We cannot simply assert no output as the JSON view logs the version message on initialization | |
| // Splitting on \n when there's only the version log will get an array of the log and an empty string. | |
| // If there are more logs there'll be >2 elements. | |
| if x := strings.Split(output.Stdout(), "\n"); len(x) != 2 { | |
| t.Fatalf("expected no additional output after version message, got: %s", output.Stdout()) | |
| } | |
| } |