From 5634ae3e1822c6dfc344cd95e513e11ae5318dbf Mon Sep 17 00:00:00 2001 From: Sebastian Rivera Date: Tue, 11 Apr 2023 16:48:36 -0400 Subject: [PATCH] Unit tests to ensure renderer is appropriately called --- internal/cloud/backend_plan.go | 3 - internal/cloud/backend_plan_test.go | 118 ++++++++++++++++++++++++++++ internal/cloud/backend_test.go | 2 +- internal/cloud/testing.go | 35 +++++++-- 4 files changed, 149 insertions(+), 9 deletions(-) diff --git a/internal/cloud/backend_plan.go b/internal/cloud/backend_plan.go index 880233637d..b2d4651388 100644 --- a/internal/cloud/backend_plan.go +++ b/internal/cloud/backend_plan.go @@ -460,7 +460,6 @@ func (b *Cloud) shouldRenderStructuredRunOutput(run *tfe.Run) (bool, error) { // If the cloud backend is configured against TFC, we only require that // the workspace has structured run output enabled. if b.client.IsCloud() && run.Workspace.StructuredRunOutputEnabled { - fmt.Println("we should see this") return true, nil } @@ -475,8 +474,6 @@ func (b *Cloud) shouldRenderStructuredRunOutput(run *tfe.Run) (bool, error) { return false, err } - fmt.Println(releaseDate) - // Any release older than 202302-1 will not support enabling SRO for // CLI-driven runs if releaseDate < 202302 { diff --git a/internal/cloud/backend_plan_test.go b/internal/cloud/backend_plan_test.go index 4e60510a12..a4c1e4998a 100644 --- a/internal/cloud/backend_plan_test.go +++ b/internal/cloud/backend_plan_test.go @@ -2,6 +2,7 @@ package cloud import ( "context" + "net/http" "os" "os/signal" "strings" @@ -1250,3 +1251,120 @@ func TestCloud_planOtherError(t *testing.T) { t.Fatalf("expected error message, got: %s", err.Error()) } } + +func TestCloud_planShouldRenderSRO(t *testing.T) { + t.Run("when instance is TFC", func(t *testing.T) { + handlers := map[string]func(http.ResponseWriter, *http.Request){ + "/api/v2/ping": func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("TFP-API-Version", "2.5") + w.Header().Set("TFP-AppName", "Terraform Cloud") + }, + } + b, bCleanup := testBackendWithHandlers(t, handlers) + t.Cleanup(bCleanup) + b.renderer = &jsonformat.Renderer{} + + t.Run("and SRO is enabled", func(t *testing.T) { + r := &tfe.Run{ + Workspace: &tfe.Workspace{ + StructuredRunOutputEnabled: true, + }, + } + assertSRORendered(t, b, r, true) + }) + + t.Run("and SRO is not enabled", func(t *testing.T) { + r := &tfe.Run{ + Workspace: &tfe.Workspace{ + StructuredRunOutputEnabled: false, + }, + } + assertSRORendered(t, b, r, false) + }) + + }) + + t.Run("when instance is TFE and version supports CLI SRO", func(t *testing.T) { + handlers := map[string]func(http.ResponseWriter, *http.Request){ + "/api/v2/ping": func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("TFP-API-Version", "2.5") + w.Header().Set("TFP-AppName", "Terraform Enterprise") + w.Header().Set("X-TFE-Version", "v202303-1") + }, + } + b, bCleanup := testBackendWithHandlers(t, handlers) + t.Cleanup(bCleanup) + b.renderer = &jsonformat.Renderer{} + + t.Run("and SRO is enabled", func(t *testing.T) { + r := &tfe.Run{ + Workspace: &tfe.Workspace{ + StructuredRunOutputEnabled: true, + }, + } + assertSRORendered(t, b, r, true) + }) + + t.Run("and SRO is not enabled", func(t *testing.T) { + r := &tfe.Run{ + Workspace: &tfe.Workspace{ + StructuredRunOutputEnabled: false, + }, + } + assertSRORendered(t, b, r, false) + }) + }) + + t.Run("when instance is a known unsupported TFE release", func(t *testing.T) { + handlers := map[string]func(http.ResponseWriter, *http.Request){ + "/api/v2/ping": func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("TFP-API-Version", "2.5") + w.Header().Set("TFP-AppName", "Terraform Enterprise") + w.Header().Set("X-TFE-Version", "v202208-1") + }, + } + b, bCleanup := testBackendWithHandlers(t, handlers) + t.Cleanup(bCleanup) + b.renderer = &jsonformat.Renderer{} + + r := &tfe.Run{ + Workspace: &tfe.Workspace{ + StructuredRunOutputEnabled: true, + }, + } + assertSRORendered(t, b, r, false) + }) + + t.Run("when instance is an unknown TFE release", func(t *testing.T) { + handlers := map[string]func(http.ResponseWriter, *http.Request){ + "/api/v2/ping": func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("TFP-API-Version", "2.5") + }, + } + b, bCleanup := testBackendWithHandlers(t, handlers) + t.Cleanup(bCleanup) + b.renderer = &jsonformat.Renderer{} + + r := &tfe.Run{ + Workspace: &tfe.Workspace{ + StructuredRunOutputEnabled: true, + }, + } + assertSRORendered(t, b, r, false) + }) + +} + +func assertSRORendered(t *testing.T, b *Cloud, r *tfe.Run, shouldRender bool) { + got, err := b.shouldRenderStructuredRunOutput(r) + if err != nil { + t.Fatalf("expected no error: %v", err) + } + if shouldRender != got { + t.Fatalf("expected SRO to be rendered: %t, got %t", shouldRender, got) + } +} diff --git a/internal/cloud/backend_test.go b/internal/cloud/backend_test.go index c73109bf48..081fce6505 100644 --- a/internal/cloud/backend_test.go +++ b/internal/cloud/backend_test.go @@ -647,7 +647,7 @@ func TestCloud_setUnavailableTerraformVersion(t *testing.T) { }), }) - b, bCleanup := testBackend(t, config) + b, bCleanup := testBackend(t, config, nil) defer bCleanup() // Make sure the workspace doesn't exist yet -- otherwise, we can't test what diff --git a/internal/cloud/testing.go b/internal/cloud/testing.go index ef0d9ed8b2..4c5302ce4a 100644 --- a/internal/cloud/testing.go +++ b/internal/cloud/testing.go @@ -43,6 +43,13 @@ var ( tfeHost: {"token": testCred}, }) testBackendSingleWorkspaceName = "app-prod" + defaultTFCPing = map[string]func(http.ResponseWriter, *http.Request){ + "/api/v2/ping": func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("TFP-API-Version", "2.5") + w.Header().Set("TFP-AppName", "Terraform Cloud") + }, + } ) // mockInput is a mock implementation of terraform.UIInput. @@ -79,7 +86,7 @@ func testBackendWithName(t *testing.T) (*Cloud, func()) { "tags": cty.NullVal(cty.Set(cty.String)), }), }) - return testBackend(t, obj) + return testBackend(t, obj, defaultTFCPing) } func testBackendWithTags(t *testing.T) (*Cloud, func()) { @@ -96,7 +103,7 @@ func testBackendWithTags(t *testing.T) (*Cloud, func()) { ), }), }) - return testBackend(t, obj) + return testBackend(t, obj, nil) } func testBackendNoOperations(t *testing.T) (*Cloud, func()) { @@ -109,7 +116,20 @@ func testBackendNoOperations(t *testing.T) (*Cloud, func()) { "tags": cty.NullVal(cty.Set(cty.String)), }), }) - return testBackend(t, obj) + return testBackend(t, obj, nil) +} + +func testBackendWithHandlers(t *testing.T, handlers map[string]func(http.ResponseWriter, *http.Request)) (*Cloud, func()) { + obj := cty.ObjectVal(map[string]cty.Value{ + "hostname": cty.NullVal(cty.String), + "organization": cty.StringVal("hashicorp"), + "token": cty.NullVal(cty.String), + "workspaces": cty.ObjectVal(map[string]cty.Value{ + "name": cty.StringVal(testBackendSingleWorkspaceName), + "tags": cty.NullVal(cty.Set(cty.String)), + }), + }) + return testBackend(t, obj, handlers) } func testCloudState(t *testing.T) *State { @@ -186,8 +206,13 @@ func testBackendWithOutputs(t *testing.T) (*Cloud, func()) { return b, cleanup } -func testBackend(t *testing.T, obj cty.Value) (*Cloud, func()) { - s := testServer(t) +func testBackend(t *testing.T, obj cty.Value, handlers map[string]func(http.ResponseWriter, *http.Request)) (*Cloud, func()) { + var s *httptest.Server + if handlers != nil { + s = testServerWithHandlers(handlers) + } else { + s = testServer(t) + } b := New(testDisco(s)) // Configure the backend so the client is created.