package terraform import ( "encoding/json" "testing" tfjson "github.com/hashicorp/terraform-json" "github.com/stretchr/testify/require" "github.com/coder/coder/v2/provisionersdk/proto" ) type mockLogger struct { logs []*proto.Log } var _ logSink = &mockLogger{} func (m *mockLogger) ProvisionLog(l proto.LogLevel, o string) { m.logs = append(m.logs, &proto.Log{Level: l, Output: o}) } func TestLogWriter_Mainline(t *testing.T) { t.Parallel() logr := &mockLogger{} writer, doneLogging := logWriter(logr, proto.LogLevel_INFO) _, err := writer.Write([]byte(`Sitting in an English garden Waiting for the sun If the sun don't come you get a tan From standing in the English rain`)) require.NoError(t, err) err = writer.Close() require.NoError(t, err) <-doneLogging expected := []*proto.Log{ {Level: proto.LogLevel_INFO, Output: "Sitting in an English garden"}, {Level: proto.LogLevel_INFO, Output: "Waiting for the sun"}, {Level: proto.LogLevel_INFO, Output: "If the sun don't come you get a tan"}, {Level: proto.LogLevel_INFO, Output: "From standing in the English rain"}, } require.Equal(t, expected, logr.logs) } func TestOnlyDataResources(t *testing.T) { t.Parallel() tests := []struct { name string stateMod *tfjson.StateModule expected *tfjson.StateModule }{ { name: "empty state module", stateMod: &tfjson.StateModule{}, expected: &tfjson.StateModule{}, }, { name: "only data resources", stateMod: &tfjson.StateModule{ Resources: []*tfjson.StateResource{ {Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"}, {Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"}, }, ChildModules: []*tfjson.StateModule{ { Resources: []*tfjson.StateResource{ {Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"}, {Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"}, }, Address: "child-module-1", }, }, Address: "fake-module", }, expected: &tfjson.StateModule{ Resources: []*tfjson.StateResource{ {Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"}, {Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"}, }, ChildModules: []*tfjson.StateModule{ { Resources: []*tfjson.StateResource{ {Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"}, {Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"}, }, Address: "child-module-1", }, }, Address: "fake-module", }, }, { name: "only non-data resources", stateMod: &tfjson.StateModule{ Resources: []*tfjson.StateResource{ {Name: "cat", Type: "coder_parameter", Mode: "foobar", Address: "cat-address"}, {Name: "cow", Type: "foobaz", Mode: "foo", Address: "cow-address"}, }, ChildModules: []*tfjson.StateModule{ { Resources: []*tfjson.StateResource{ {Name: "child-cat", Type: "coder_parameter", Mode: "foobar", Address: "child-cat-address"}, {Name: "child-dog", Type: "foobar", Mode: "foobaz", Address: "child-dog-address"}, }, Address: "child-module-1", }, }, Address: "fake-module", }, expected: &tfjson.StateModule{ Address: "fake-module", ChildModules: []*tfjson.StateModule{ {Address: "child-module-1"}, }, }, }, { name: "mixed resources", stateMod: &tfjson.StateModule{ Resources: []*tfjson.StateResource{ {Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"}, {Name: "dog", Type: "foobar", Mode: "magic", Address: "dog-address"}, {Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"}, }, ChildModules: []*tfjson.StateModule{ { Resources: []*tfjson.StateResource{ {Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"}, {Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"}, {Name: "child-cow", Type: "foobaz", Mode: "magic", Address: "child-cow-address"}, }, Address: "child-module-1", }, }, Address: "fake-module", }, expected: &tfjson.StateModule{ Resources: []*tfjson.StateResource{ {Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"}, {Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"}, }, ChildModules: []*tfjson.StateModule{ { Resources: []*tfjson.StateResource{ {Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"}, {Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"}, }, Address: "child-module-1", }, }, Address: "fake-module", }, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() filtered := onlyDataResources(*tt.stateMod) expected, err := json.Marshal(tt.expected) require.NoError(t, err) got, err := json.Marshal(filtered) require.NoError(t, err) require.Equal(t, string(expected), string(got)) }) } }