|
|
|
|
@ -2,11 +2,11 @@ package views
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/command/arguments"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/terminal"
|
|
|
|
|
@ -14,6 +14,71 @@ import (
|
|
|
|
|
tfversion "github.com/hashicorp/terraform/version"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestNewCloudHuman_RetryLog(t *testing.T) {
|
|
|
|
|
t.Run("first retry, no output", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
cloudHuman, ok := newCloud.(*CloudHuman)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudHuman.RetryLog(0, nil)
|
|
|
|
|
output := done(t).All()
|
|
|
|
|
if output != "" {
|
|
|
|
|
t.Fatalf("expected no output for the first retry attempt, but got: %s", output)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("second retry, server error", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
cloudHuman, ok := newCloud.(*CloudHuman)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudHuman.RetryLog(1, &http.Response{StatusCode: 500})
|
|
|
|
|
output := done(t).All()
|
|
|
|
|
expected := "There was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection..."
|
|
|
|
|
if !strings.Contains(output, expected) {
|
|
|
|
|
t.Fatalf("expected output to contain: %s, but got %s", expected, output)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("subsequent retry with elapsed time", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
cloudHuman, ok := newCloud.(*CloudHuman)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudHuman.lastRetry = time.Now().Add(-2 * time.Second) // Simulate a delay of 2 seconds
|
|
|
|
|
cloudHuman.RetryLog(2, &http.Response{StatusCode: 500})
|
|
|
|
|
output := done(t).All()
|
|
|
|
|
expected := "Still trying to restore the connection... (2s elapsed)"
|
|
|
|
|
if !strings.Contains(output, expected) {
|
|
|
|
|
t.Fatalf("expected output to contain: %s, but got %s", expected, output)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("retry with 429 status, no output", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
cloudHuman, ok := newCloud.(*CloudHuman)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudHuman.RetryLog(2, &http.Response{StatusCode: 429})
|
|
|
|
|
output := done(t).All()
|
|
|
|
|
if output != "" {
|
|
|
|
|
t.Fatalf("expected no output for status code 429, but got: %s", output)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestNewCloud_unsupportedViewDiagnostics(t *testing.T) {
|
|
|
|
|
defer func() {
|
|
|
|
|
r := recover()
|
|
|
|
|
@ -67,24 +132,6 @@ func TestNewCloud_humanViewOutput(t *testing.T) {
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestNewCloud_humanViewPrepareMessage(t *testing.T) {
|
|
|
|
|
t.Run("existing message code", func(t *testing.T) {
|
|
|
|
|
streams, _ := terminal.StreamsForTesting(t)
|
|
|
|
|
|
|
|
|
|
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
if _, ok := newCloud.(*CloudHuman); !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %t", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
want := "\nThere was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection..."
|
|
|
|
|
|
|
|
|
|
actual := newCloud.PrepareMessage(InitialRetryErrorMessage)
|
|
|
|
|
if !cmp.Equal(want, actual) {
|
|
|
|
|
t.Errorf("unexpected output: %s", cmp.Diff(want, actual))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestNewCloud_humanViewDiagnostics(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
|
|
|
|
|
@ -103,16 +150,41 @@ func TestNewCloud_humanViewDiagnostics(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestNewCloud_jsonViewOutput(t *testing.T) {
|
|
|
|
|
t.Run("no param", func(t *testing.T) {
|
|
|
|
|
func TestNewCloudJSON_RetryLog(t *testing.T) {
|
|
|
|
|
t.Run("attempt 0, no output", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
cloudJSON, ok := newCloud.(*CloudJSON)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudJSON.RetryLog(0, nil)
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
actual := done(t).Stdout()
|
|
|
|
|
testJSONViewOutputEqualsFull(t, actual, want)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("attempt 1, server error", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
if _, ok := newCloud.(*CloudJSON); !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %t", newCloud)
|
|
|
|
|
cloudJSON, ok := newCloud.(*CloudJSON)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newCloud.Output(InitialRetryErrorMessage)
|
|
|
|
|
cloudJSON.RetryLog(1, &http.Response{StatusCode: 500})
|
|
|
|
|
|
|
|
|
|
version := tfversion.String()
|
|
|
|
|
want := []map[string]interface{}{
|
|
|
|
|
@ -132,12 +204,74 @@ func TestNewCloud_jsonViewOutput(t *testing.T) {
|
|
|
|
|
"type": "cloud_output",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
actual := done(t).Stdout()
|
|
|
|
|
testJSONViewOutputEqualsFull(t, actual, want)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("subsequent retry with elapsed time", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
cloudJSON, ok := newCloud.(*CloudJSON)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudJSON.lastRetry = time.Now().Add(-2 * time.Second) // Simulate a delay of 2 seconds
|
|
|
|
|
cloudJSON.RetryLog(2, &http.Response{StatusCode: 500})
|
|
|
|
|
|
|
|
|
|
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": "Still trying to restore the connection... (2s elapsed)",
|
|
|
|
|
"message_code": "repeated_retry_error_message",
|
|
|
|
|
"@module": "terraform.ui",
|
|
|
|
|
"type": "cloud_output",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actual := done(t).Stdout()
|
|
|
|
|
testJSONViewOutputEqualsFull(t, actual, want)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("single param", func(t *testing.T) {
|
|
|
|
|
t.Run("retry with 429 status, no output", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
cloudJSON, ok := newCloud.(*CloudJSON)
|
|
|
|
|
if !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %T", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudJSON.RetryLog(0, &http.Response{
|
|
|
|
|
StatusCode: http.StatusTooManyRequests, // HTTP: 429
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
actual := done(t).Stdout()
|
|
|
|
|
testJSONViewOutputEqualsFull(t, actual, want)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestNewCloud_jsonViewOutput(t *testing.T) {
|
|
|
|
|
t.Run("no param", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
|
|
|
|
|
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
@ -145,8 +279,7 @@ func TestNewCloud_jsonViewOutput(t *testing.T) {
|
|
|
|
|
t.Fatalf("unexpected return type %t", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
duration := 5 * time.Second
|
|
|
|
|
newCloud.Output(RepeatedRetryErrorMessage, duration)
|
|
|
|
|
newCloud.Output(InitialRetryErrorMessage)
|
|
|
|
|
|
|
|
|
|
version := tfversion.String()
|
|
|
|
|
want := []map[string]interface{}{
|
|
|
|
|
@ -160,9 +293,9 @@ func TestNewCloud_jsonViewOutput(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"@level": "info",
|
|
|
|
|
"@message": fmt.Sprintf("Still trying to restore the connection... (%s elapsed)", duration),
|
|
|
|
|
"@message": "There was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection...",
|
|
|
|
|
"message_code": "initial_retry_error_message",
|
|
|
|
|
"@module": "terraform.ui",
|
|
|
|
|
"message_code": "repeated_retry_error_message",
|
|
|
|
|
"type": "cloud_output",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
@ -170,23 +303,39 @@ func TestNewCloud_jsonViewOutput(t *testing.T) {
|
|
|
|
|
actual := done(t).Stdout()
|
|
|
|
|
testJSONViewOutputEqualsFull(t, actual, want)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestNewCloud_jsonViewPrepareMessage(t *testing.T) {
|
|
|
|
|
t.Run("existing message code", func(t *testing.T) {
|
|
|
|
|
streams, _ := terminal.StreamsForTesting(t)
|
|
|
|
|
t.Run("single param", func(t *testing.T) {
|
|
|
|
|
streams, done := terminal.StreamsForTesting(t)
|
|
|
|
|
|
|
|
|
|
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
|
|
|
|
|
if _, ok := newCloud.(*CloudJSON); !ok {
|
|
|
|
|
t.Fatalf("unexpected return type %t", newCloud)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
want := "There was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection..."
|
|
|
|
|
duration := 5 * time.Second
|
|
|
|
|
newCloud.Output(RepeatedRetryErrorMessage, duration)
|
|
|
|
|
|
|
|
|
|
actual := newCloud.PrepareMessage(InitialRetryErrorMessage)
|
|
|
|
|
if !cmp.Equal(want, actual) {
|
|
|
|
|
t.Errorf("unexpected output: %s", cmp.Diff(want, actual))
|
|
|
|
|
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("Still trying to restore the connection... (%s elapsed)", duration),
|
|
|
|
|
"@module": "terraform.ui",
|
|
|
|
|
"message_code": "repeated_retry_error_message",
|
|
|
|
|
"type": "cloud_output",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
actual := done(t).Stdout()
|
|
|
|
|
testJSONViewOutputEqualsFull(t, actual, want)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|