2021-12-08 00:35:04 +01:00
|
|
|
package cloud
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-tfe"
|
|
|
|
)
|
|
|
|
|
|
|
|
type testIntegrationOutput struct {
|
|
|
|
ctx *IntegrationContext
|
|
|
|
output *strings.Builder
|
|
|
|
t *testing.T
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ IntegrationOutputWriter = (*testIntegrationOutput)(nil) // Compile time check
|
|
|
|
|
|
|
|
func (s *testIntegrationOutput) End() {
|
|
|
|
s.output.WriteString("END\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *testIntegrationOutput) SubOutput(str string) {
|
|
|
|
s.output.WriteString(s.ctx.B.Colorize().Color("[reset]│ "+str) + "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *testIntegrationOutput) Output(str string) {
|
|
|
|
s.output.WriteString(s.ctx.B.Colorize().Color("[reset]│ ") + str + "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *testIntegrationOutput) OutputElapsed(message string, maxMessage int) {
|
|
|
|
s.output.WriteString("PENDING MESSAGE: " + message)
|
|
|
|
}
|
|
|
|
|
|
|
|
func newMockIntegrationContext(b *Cloud, t *testing.T) (*IntegrationContext, *testIntegrationOutput) {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
// Retrieve the workspace used to run this operation in.
|
|
|
|
w, err := b.client.Workspaces.Read(ctx, b.organization, b.WorkspaceMapping.Name)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error retrieving workspace: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new configuration version.
|
|
|
|
c, err := b.client.ConfigurationVersions.Create(ctx, w.ID, tfe.ConfigurationVersionCreateOptions{})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error creating configuration version: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a pending run to block this run.
|
|
|
|
r, err := b.client.Runs.Create(ctx, tfe.RunCreateOptions{
|
|
|
|
ConfigurationVersion: c,
|
|
|
|
Workspace: w,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error creating pending run: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
op, configCleanup, done := testOperationPlan(t, "./testdata/plan")
|
|
|
|
defer configCleanup()
|
|
|
|
defer done(t)
|
|
|
|
|
|
|
|
integrationContext := &IntegrationContext{
|
|
|
|
B: b,
|
|
|
|
StopContext: ctx,
|
|
|
|
CancelContext: ctx,
|
|
|
|
Op: op,
|
|
|
|
Run: r,
|
|
|
|
}
|
|
|
|
|
|
|
|
return integrationContext, &testIntegrationOutput{
|
|
|
|
ctx: integrationContext,
|
|
|
|
output: &strings.Builder{},
|
|
|
|
t: t,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCloud_runTasksWithTaskResults(t *testing.T) {
|
|
|
|
b, bCleanup := testBackendWithName(t)
|
|
|
|
defer bCleanup()
|
|
|
|
|
|
|
|
integrationContext, writer := newMockIntegrationContext(b, t)
|
|
|
|
|
|
|
|
cases := map[string]struct {
|
|
|
|
taskResults []*tfe.TaskResult
|
|
|
|
context *IntegrationContext
|
|
|
|
writer *testIntegrationOutput
|
|
|
|
expectedOutputs []string
|
|
|
|
isError bool
|
|
|
|
}{
|
|
|
|
"all-succeeded": {
|
|
|
|
taskResults: []*tfe.TaskResult{
|
|
|
|
{ID: "1", TaskName: "Mandatory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "mandatory"},
|
|
|
|
{ID: "2", TaskName: "Advisory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "advisory"},
|
|
|
|
},
|
|
|
|
writer: writer,
|
|
|
|
context: integrationContext,
|
|
|
|
expectedOutputs: []string{"Overall Result: Passed\n"},
|
|
|
|
isError: false,
|
|
|
|
},
|
|
|
|
"mandatory-failed": {
|
|
|
|
taskResults: []*tfe.TaskResult{
|
|
|
|
{ID: "1", TaskName: "Mandatory", Message: "500 Error", Status: "failed", WorkspaceTaskEnforcementLevel: "mandatory"},
|
|
|
|
{ID: "2", TaskName: "Advisory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "advisory"},
|
|
|
|
},
|
|
|
|
writer: writer,
|
|
|
|
context: integrationContext,
|
|
|
|
expectedOutputs: []string{"Passed\n", "A-OK\n", "Overall Result: Failed\n"},
|
|
|
|
isError: true,
|
|
|
|
},
|
|
|
|
"advisory-failed": {
|
|
|
|
taskResults: []*tfe.TaskResult{
|
|
|
|
{ID: "1", TaskName: "Mandatory", Message: "A-OK", Status: "passed", WorkspaceTaskEnforcementLevel: "mandatory"},
|
|
|
|
{ID: "2", TaskName: "Advisory", Message: "500 Error", Status: "failed", WorkspaceTaskEnforcementLevel: "advisory"},
|
|
|
|
},
|
|
|
|
writer: writer,
|
|
|
|
context: integrationContext,
|
|
|
|
expectedOutputs: []string{"Failed (Advisory)", "Overall Result: Passed with advisory failure"},
|
|
|
|
isError: false,
|
|
|
|
},
|
2021-12-15 18:02:48 +01:00
|
|
|
"unreachable": {
|
|
|
|
taskResults: []*tfe.TaskResult{
|
|
|
|
{ID: "1", TaskName: "Mandatory", Message: "", Status: "unreachable", WorkspaceTaskEnforcementLevel: "mandatory"},
|
|
|
|
{ID: "2", TaskName: "Advisory", Message: "", Status: "unreachable", WorkspaceTaskEnforcementLevel: "advisory"},
|
|
|
|
},
|
|
|
|
writer: writer,
|
|
|
|
context: integrationContext,
|
|
|
|
expectedOutputs: []string{"Skipping"},
|
|
|
|
isError: false,
|
|
|
|
},
|
2021-12-08 00:35:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for caseName, c := range cases {
|
|
|
|
c.writer.output.Reset()
|
2021-12-15 22:55:46 +01:00
|
|
|
err := b.runTasksWithTaskResults(c.context, writer, func(b *Cloud, stopCtx context.Context) (*tfe.TaskStage, error) {
|
2021-12-08 00:35:04 +01:00
|
|
|
return &tfe.TaskStage{
|
|
|
|
TaskResults: c.taskResults,
|
|
|
|
}, nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if c.isError && err == nil {
|
|
|
|
t.Fatalf("Expected %s to be error", caseName)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !c.isError && err != nil {
|
|
|
|
t.Errorf("Expected %s to not be error but received %s", caseName, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
output := c.writer.output.String()
|
|
|
|
for _, expected := range c.expectedOutputs {
|
|
|
|
if !strings.Contains(output, expected) {
|
|
|
|
t.Fatalf("Expected output to contain '%s' but it was:\n\n%s", expected, output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|