github.com/cycloidio/terraform@v1.1.10-0.20220513142504-76d5c768dc63/cloud/backend_runTasks_test.go (about) 1 package cloud 2 3 import ( 4 "context" 5 "strings" 6 "testing" 7 8 "github.com/hashicorp/go-tfe" 9 ) 10 11 type testIntegrationOutput struct { 12 ctx *IntegrationContext 13 output *strings.Builder 14 t *testing.T 15 } 16 17 var _ IntegrationOutputWriter = (*testIntegrationOutput)(nil) // Compile time check 18 19 func (s *testIntegrationOutput) End() { 20 s.output.WriteString("END\n") 21 } 22 23 func (s *testIntegrationOutput) SubOutput(str string) { 24 s.output.WriteString(s.ctx.B.Colorize().Color("[reset]│ "+str) + "\n") 25 } 26 27 func (s *testIntegrationOutput) Output(str string) { 28 s.output.WriteString(s.ctx.B.Colorize().Color("[reset]│ ") + str + "\n") 29 } 30 31 func (s *testIntegrationOutput) OutputElapsed(message string, maxMessage int) { 32 s.output.WriteString("PENDING MESSAGE: " + message) 33 } 34 35 func newMockIntegrationContext(b *Cloud, t *testing.T) (*IntegrationContext, *testIntegrationOutput) { 36 ctx := context.Background() 37 38 // Retrieve the workspace used to run this operation in. 39 w, err := b.client.Workspaces.Read(ctx, b.organization, b.WorkspaceMapping.Name) 40 if err != nil { 41 t.Fatalf("error retrieving workspace: %v", err) 42 } 43 44 // Create a new configuration version. 45 c, err := b.client.ConfigurationVersions.Create(ctx, w.ID, tfe.ConfigurationVersionCreateOptions{}) 46 if err != nil { 47 t.Fatalf("error creating configuration version: %v", err) 48 } 49 50 // Create a pending run to block this run. 51 r, err := b.client.Runs.Create(ctx, tfe.RunCreateOptions{ 52 ConfigurationVersion: c, 53 Workspace: w, 54 }) 55 if err != nil { 56 t.Fatalf("error creating pending run: %v", err) 57 } 58 59 op, configCleanup, done := testOperationPlan(t, "./testdata/plan") 60 defer configCleanup() 61 defer done(t) 62 63 integrationContext := &IntegrationContext{ 64 B: b, 65 StopContext: ctx, 66 CancelContext: ctx, 67 Op: op, 68 Run: r, 69 } 70 71 return integrationContext, &testIntegrationOutput{ 72 ctx: integrationContext, 73 output: &strings.Builder{}, 74 t: t, 75 } 76 } 77 78 func TestCloud_runTasksWithTaskResults(t *testing.T) { 79 b, bCleanup := testBackendWithName(t) 80 defer bCleanup() 81 82 integrationContext, writer := newMockIntegrationContext(b, t) 83 84 cases := map[string]struct { 85 taskResults []*tfe.TaskResult 86 context *IntegrationContext 87 writer *testIntegrationOutput 88 expectedOutputs []string 89 isError bool 90 }{ 91 "all-succeeded": { 92 taskResults: []*tfe.TaskResult{ 93 {ID: "1", TaskName: "Mandatory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "mandatory"}, 94 {ID: "2", TaskName: "Advisory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "advisory"}, 95 }, 96 writer: writer, 97 context: integrationContext, 98 expectedOutputs: []string{"Overall Result: Passed\n"}, 99 isError: false, 100 }, 101 "mandatory-failed": { 102 taskResults: []*tfe.TaskResult{ 103 {ID: "1", TaskName: "Mandatory", Message: "500 Error", Status: "failed", WorkspaceTaskEnforcementLevel: "mandatory"}, 104 {ID: "2", TaskName: "Advisory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "advisory"}, 105 }, 106 writer: writer, 107 context: integrationContext, 108 expectedOutputs: []string{"Passed\n", "A-OK\n", "Overall Result: Failed\n"}, 109 isError: true, 110 }, 111 "advisory-failed": { 112 taskResults: []*tfe.TaskResult{ 113 {ID: "1", TaskName: "Mandatory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "mandatory"}, 114 {ID: "2", TaskName: "Advisory", Message: "500 Error", Status: "failed", WorkspaceTaskEnforcementLevel: "advisory"}, 115 }, 116 writer: writer, 117 context: integrationContext, 118 expectedOutputs: []string{"Failed (Advisory)", "Overall Result: Passed with advisory failure"}, 119 isError: false, 120 }, 121 "unreachable": { 122 taskResults: []*tfe.TaskResult{ 123 {ID: "1", TaskName: "Mandatory", Message: "", Status: "unreachable", WorkspaceTaskEnforcementLevel: "mandatory"}, 124 {ID: "2", TaskName: "Advisory", Message: "", Status: "unreachable", WorkspaceTaskEnforcementLevel: "advisory"}, 125 }, 126 writer: writer, 127 context: integrationContext, 128 expectedOutputs: []string{"Skipping"}, 129 isError: false, 130 }, 131 } 132 133 for caseName, c := range cases { 134 c.writer.output.Reset() 135 err := b.runTasksWithTaskResults(c.context, writer, func(b *Cloud, stopCtx context.Context) (*tfe.TaskStage, error) { 136 return &tfe.TaskStage{ 137 TaskResults: c.taskResults, 138 }, nil 139 }) 140 141 if c.isError && err == nil { 142 t.Fatalf("Expected %s to be error", caseName) 143 } 144 145 if !c.isError && err != nil { 146 t.Errorf("Expected %s to not be error but received %s", caseName, err) 147 } 148 149 output := c.writer.output.String() 150 for _, expected := range c.expectedOutputs { 151 if !strings.Contains(output, expected) { 152 t.Fatalf("Expected output to contain '%s' but it was:\n\n%s", expected, output) 153 } 154 } 155 } 156 }