mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Modify tfe client mocks to meet some new requirements
- Add plausible unredacted plan json for `plan-json-{basic,full}` testdata -- Created by just running the relevant terraform commands locally. - Add plan-json-no-changes testdata -- The unredacted json was organically grown, but I edited the log and redacted json by hand to match what I observed from a real but unrelated planned-and-finished run in TFC. - Add plan-json-basic-no-unredacted testdata -- This mimics a lack of admin permissions, resulting in a 404. - Hook up `MockPlans.ReadJSONOutput` to test fixtures, when present. This method has been implemented for ages, and has had a backing store for unredacted plan json, but has been effectively a no-op since nothing ever fills that backing store. So, when creating a mock plan, make an attempt to read unredacted json and stow it in the mocks on success. - Make it possible to get the entire MockClient for a test backend In order to test some things, I'm going to need to mess with the internal state of runs and plans beyond what the go-tfe client API allows. I could add magic special-casing to the mock API methods, or I could locate the shenanigans next to the test that actually exploits it. The latter seems more comprehensible, but I need access to the full mock client struct in order to mess with its interior. - Fill in some missing expectations around HasChanges when retrieving a run + plan.
This commit is contained in:
parent
ed27fa096e
commit
7f6b827987
@ -650,7 +650,7 @@ func TestCloud_setUnavailableTerraformVersion(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
b, bCleanup := testBackend(t, config, nil)
|
b, _, bCleanup := testBackend(t, config, nil)
|
||||||
defer bCleanup()
|
defer bCleanup()
|
||||||
|
|
||||||
// Make sure the workspace doesn't exist yet -- otherwise, we can't test what
|
// Make sure the workspace doesn't exist yet -- otherwise, we can't test what
|
||||||
|
1
internal/cloud/testdata/plan-json-basic-no-unredacted/main.tf
vendored
Normal file
1
internal/cloud/testdata/plan-json-basic-no-unredacted/main.tf
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
resource "null_resource" "foo" {}
|
116
internal/cloud/testdata/plan-json-basic-no-unredacted/plan-redacted.json
vendored
Normal file
116
internal/cloud/testdata/plan-json-basic-no-unredacted/plan-redacted.json
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
{
|
||||||
|
"plan_format_version": "1.1",
|
||||||
|
"resource_drift": [],
|
||||||
|
"resource_changes": [
|
||||||
|
{
|
||||||
|
"address": "null_resource.foo",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "null_resource",
|
||||||
|
"name": "foo",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
|
"change": {
|
||||||
|
"actions": [
|
||||||
|
"create"
|
||||||
|
],
|
||||||
|
"before": null,
|
||||||
|
"after": {
|
||||||
|
"triggers": null
|
||||||
|
},
|
||||||
|
"after_unknown": {
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"before_sensitive": false,
|
||||||
|
"after_sensitive": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"relevant_attributes": [],
|
||||||
|
"output_changes": {},
|
||||||
|
"provider_schemas": {
|
||||||
|
"registry.terraform.io/hashicorp/null": {
|
||||||
|
"provider": {
|
||||||
|
"version": 0,
|
||||||
|
"block": {
|
||||||
|
"description_kind": "plain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resource_schemas": {
|
||||||
|
"null_resource": {
|
||||||
|
"version": 0,
|
||||||
|
"block": {
|
||||||
|
"attributes": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "This is set to a random value at create time.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"triggers": {
|
||||||
|
"type": [
|
||||||
|
"map",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"description": "A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "The `null_resource` resource implements the standard resource lifecycle but takes no further action.\n\nThe `triggers` argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced.",
|
||||||
|
"description_kind": "plain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data_source_schemas": {
|
||||||
|
"null_data_source": {
|
||||||
|
"version": 0,
|
||||||
|
"block": {
|
||||||
|
"attributes": {
|
||||||
|
"has_computed_default": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "If set, its literal value will be stored and returned. If not, its value defaults to `\"default\"`. This argument exists primarily for testing and has little practical use.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"optional": true,
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"deprecated": true,
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"type": [
|
||||||
|
"map",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"description": "A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"outputs": {
|
||||||
|
"type": [
|
||||||
|
"map",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"description": "After the data source is \"read\", a copy of the `inputs` map.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"random": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"computed": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "The `null_data_source` data source implements the standard data source lifecycle but does not\ninteract with any external APIs.\n\nHistorically, the `null_data_source` was typically used to construct intermediate values to re-use elsewhere in configuration. The\nsame can now be achieved using [locals](https://www.terraform.io/docs/language/values/locals.html).\n",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"deprecated": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"provider_format_version": "1.0"
|
||||||
|
}
|
3
internal/cloud/testdata/plan-json-basic-no-unredacted/plan.log
vendored
Normal file
3
internal/cloud/testdata/plan-json-basic-no-unredacted/plan.log
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{"@level":"info","@message":"Terraform 1.3.7","@module":"terraform.ui","@timestamp":"2023-01-19T10:47:27.409143-05:00","terraform":"1.3.7","type":"version","ui":"1.0"}
|
||||||
|
{"@level":"info","@message":"null_resource.foo: Plan to create","@module":"terraform.ui","@timestamp":"2023-01-19T10:47:27.605841-05:00","change":{"resource":{"addr":"null_resource.foo","module":"","resource":"null_resource.foo","implied_provider":"null","resource_type":"null_resource","resource_name":"foo","resource_key":null},"action":"create"},"type":"planned_change"}
|
||||||
|
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","@timestamp":"2023-01-19T10:47:27.605906-05:00","changes":{"add":1,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}
|
1
internal/cloud/testdata/plan-json-basic/plan-unredacted.json
vendored
Normal file
1
internal/cloud/testdata/plan-json-basic/plan-unredacted.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"format_version":"1.1","terraform_version":"1.4.4","planned_values":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","schema_version":0,"values":{"triggers":null},"sensitive_values":{}}]}},"resource_changes":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","change":{"actions":["create"],"before":null,"after":{"triggers":null},"after_unknown":{"id":true},"before_sensitive":false,"after_sensitive":{}}}],"configuration":{"provider_config":{"null":{"name":"null","full_name":"registry.terraform.io/hashicorp/null"}},"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_config_key":"null","schema_version":0}]}}}
|
1
internal/cloud/testdata/plan-json-full/plan-unredacted.json
vendored
Normal file
1
internal/cloud/testdata/plan-json-full/plan-unredacted.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
internal/cloud/testdata/plan-json-no-changes/main.tf
vendored
Normal file
1
internal/cloud/testdata/plan-json-no-changes/main.tf
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
resource "null_resource" "foo" {}
|
118
internal/cloud/testdata/plan-json-no-changes/plan-redacted.json
vendored
Normal file
118
internal/cloud/testdata/plan-json-no-changes/plan-redacted.json
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
{
|
||||||
|
"plan_format_version": "1.1",
|
||||||
|
"resource_drift": [],
|
||||||
|
"resource_changes": [
|
||||||
|
{
|
||||||
|
"address": "null_resource.foo",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "null_resource",
|
||||||
|
"name": "foo",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
|
"change": {
|
||||||
|
"actions": [
|
||||||
|
"no-op"
|
||||||
|
],
|
||||||
|
"before": {
|
||||||
|
"id": "3549869958859575216",
|
||||||
|
"triggers": null
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"id": "3549869958859575216",
|
||||||
|
"triggers": null
|
||||||
|
},
|
||||||
|
"after_unknown": {},
|
||||||
|
"before_sensitive": {},
|
||||||
|
"after_sensitive": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"relevant_attributes": [],
|
||||||
|
"output_changes": {},
|
||||||
|
"provider_schemas": {
|
||||||
|
"registry.terraform.io/hashicorp/null": {
|
||||||
|
"provider": {
|
||||||
|
"version": 0,
|
||||||
|
"block": {
|
||||||
|
"description_kind": "plain"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resource_schemas": {
|
||||||
|
"null_resource": {
|
||||||
|
"version": 0,
|
||||||
|
"block": {
|
||||||
|
"attributes": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "This is set to a random value at create time.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"triggers": {
|
||||||
|
"type": [
|
||||||
|
"map",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"description": "A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "The `null_resource` resource implements the standard resource lifecycle but takes no further action.\n\nThe `triggers` argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced.",
|
||||||
|
"description_kind": "plain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data_source_schemas": {
|
||||||
|
"null_data_source": {
|
||||||
|
"version": 0,
|
||||||
|
"block": {
|
||||||
|
"attributes": {
|
||||||
|
"has_computed_default": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "If set, its literal value will be stored and returned. If not, its value defaults to `\"default\"`. This argument exists primarily for testing and has little practical use.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"optional": true,
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"deprecated": true,
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"inputs": {
|
||||||
|
"type": [
|
||||||
|
"map",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"description": "A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"outputs": {
|
||||||
|
"type": [
|
||||||
|
"map",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"description": "After the data source is \"read\", a copy of the `inputs` map.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"computed": true
|
||||||
|
},
|
||||||
|
"random": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases.",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"computed": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "The `null_data_source` data source implements the standard data source lifecycle but does not\ninteract with any external APIs.\n\nHistorically, the `null_data_source` was typically used to construct intermediate values to re-use elsewhere in configuration. The\nsame can now be achieved using [locals](https://www.terraform.io/docs/language/values/locals.html).\n",
|
||||||
|
"description_kind": "plain",
|
||||||
|
"deprecated": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"provider_format_version": "1.0"
|
||||||
|
}
|
1
internal/cloud/testdata/plan-json-no-changes/plan-unredacted.json
vendored
Normal file
1
internal/cloud/testdata/plan-json-no-changes/plan-unredacted.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"format_version":"1.1","terraform_version":"1.4.4","planned_values":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","schema_version":0,"values":{"id":"3549869958859575216","triggers":null},"sensitive_values":{}}]}},"resource_changes":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","change":{"actions":["no-op"],"before":{"id":"3549869958859575216","triggers":null},"after":{"id":"3549869958859575216","triggers":null},"after_unknown":{},"before_sensitive":{},"after_sensitive":{}}}],"prior_state":{"format_version":"1.0","terraform_version":"1.4.4","values":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","schema_version":0,"values":{"id":"3549869958859575216","triggers":null},"sensitive_values":{}}]}}},"configuration":{"provider_config":{"null":{"name":"null","full_name":"registry.terraform.io/hashicorp/null"}},"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_config_key":"null","schema_version":0}]}}}
|
2
internal/cloud/testdata/plan-json-no-changes/plan.log
vendored
Normal file
2
internal/cloud/testdata/plan-json-no-changes/plan.log
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
{"@level":"info","@message":"Terraform 1.3.7","@module":"terraform.ui","@timestamp":"2023-01-19T10:47:27.409143-05:00","terraform":"1.3.7","type":"version","ui":"1.0"}
|
||||||
|
{"@level":"info","@message":"Plan: 0 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","@timestamp":"2023-01-19T10:47:27.605906-05:00","changes":{"add":0,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}
|
@ -83,6 +83,11 @@ func testInput(t *testing.T, answers map[string]string) *mockInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testBackendWithName(t *testing.T) (*Cloud, func()) {
|
func testBackendWithName(t *testing.T) (*Cloud, func()) {
|
||||||
|
b, _, c := testBackendAndMocksWithName(t)
|
||||||
|
return b, c
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBackendAndMocksWithName(t *testing.T) (*Cloud, *MockClient, func()) {
|
||||||
obj := cty.ObjectVal(map[string]cty.Value{
|
obj := cty.ObjectVal(map[string]cty.Value{
|
||||||
"hostname": cty.NullVal(cty.String),
|
"hostname": cty.NullVal(cty.String),
|
||||||
"organization": cty.StringVal("hashicorp"),
|
"organization": cty.StringVal("hashicorp"),
|
||||||
@ -109,7 +114,8 @@ func testBackendWithTags(t *testing.T) (*Cloud, func()) {
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
return testBackend(t, obj, nil)
|
b, _, c := testBackend(t, obj, nil)
|
||||||
|
return b, c
|
||||||
}
|
}
|
||||||
|
|
||||||
func testBackendNoOperations(t *testing.T) (*Cloud, func()) {
|
func testBackendNoOperations(t *testing.T) (*Cloud, func()) {
|
||||||
@ -122,7 +128,8 @@ func testBackendNoOperations(t *testing.T) (*Cloud, func()) {
|
|||||||
"tags": cty.NullVal(cty.Set(cty.String)),
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
return testBackend(t, obj, nil)
|
b, _, c := testBackend(t, obj, nil)
|
||||||
|
return b, c
|
||||||
}
|
}
|
||||||
|
|
||||||
func testBackendWithHandlers(t *testing.T, handlers map[string]func(http.ResponseWriter, *http.Request)) (*Cloud, func()) {
|
func testBackendWithHandlers(t *testing.T, handlers map[string]func(http.ResponseWriter, *http.Request)) (*Cloud, func()) {
|
||||||
@ -135,7 +142,8 @@ func testBackendWithHandlers(t *testing.T, handlers map[string]func(http.Respons
|
|||||||
"tags": cty.NullVal(cty.Set(cty.String)),
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
return testBackend(t, obj, handlers)
|
b, _, c := testBackend(t, obj, handlers)
|
||||||
|
return b, c
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCloudState(t *testing.T) *State {
|
func testCloudState(t *testing.T) *State {
|
||||||
@ -212,7 +220,7 @@ func testBackendWithOutputs(t *testing.T) (*Cloud, func()) {
|
|||||||
return b, cleanup
|
return b, cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
func testBackend(t *testing.T, obj cty.Value, handlers map[string]func(http.ResponseWriter, *http.Request)) (*Cloud, func()) {
|
func testBackend(t *testing.T, obj cty.Value, handlers map[string]func(http.ResponseWriter, *http.Request)) (*Cloud, *MockClient, func()) {
|
||||||
var s *httptest.Server
|
var s *httptest.Server
|
||||||
if handlers != nil {
|
if handlers != nil {
|
||||||
s = testServerWithHandlers(handlers)
|
s = testServerWithHandlers(handlers)
|
||||||
@ -287,7 +295,7 @@ func testBackend(t *testing.T, obj cty.Value, handlers map[string]func(http.Resp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return b, s.Close
|
return b, mc, s.Close
|
||||||
}
|
}
|
||||||
|
|
||||||
// testUnconfiguredBackend is used for testing the configuration of the backend
|
// testUnconfiguredBackend is used for testing the configuration of the backend
|
||||||
|
@ -513,7 +513,7 @@ func (m *MockRedactedPlans) Read(ctx context.Context, hostname, token, planID st
|
|||||||
type MockPlans struct {
|
type MockPlans struct {
|
||||||
client *MockClient
|
client *MockClient
|
||||||
logs map[string]string
|
logs map[string]string
|
||||||
planOutputs map[string]string
|
planOutputs map[string][]byte
|
||||||
plans map[string]*tfe.Plan
|
plans map[string]*tfe.Plan
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +521,7 @@ func newMockPlans(client *MockClient) *MockPlans {
|
|||||||
return &MockPlans{
|
return &MockPlans{
|
||||||
client: client,
|
client: client,
|
||||||
logs: make(map[string]string),
|
logs: make(map[string]string),
|
||||||
planOutputs: make(map[string]string),
|
planOutputs: make(map[string][]byte),
|
||||||
plans: make(map[string]*tfe.Plan),
|
plans: make(map[string]*tfe.Plan),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -548,6 +548,17 @@ func (m *MockPlans) create(cvID, workspaceID string) (*tfe.Plan, error) {
|
|||||||
w.WorkingDirectory,
|
w.WorkingDirectory,
|
||||||
"plan.log",
|
"plan.log",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Try to load unredacted json output, if it exists
|
||||||
|
outputPath := filepath.Join(
|
||||||
|
m.client.ConfigurationVersions.uploadPaths[cvID],
|
||||||
|
w.WorkingDirectory,
|
||||||
|
"plan-unredacted.json",
|
||||||
|
)
|
||||||
|
if outBytes, err := os.ReadFile(outputPath); err == nil {
|
||||||
|
m.planOutputs[p.ID] = outBytes
|
||||||
|
}
|
||||||
|
|
||||||
m.plans[p.ID] = p
|
m.plans[p.ID] = p
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
@ -608,7 +619,7 @@ func (m *MockPlans) ReadJSONOutput(ctx context.Context, planID string) ([]byte,
|
|||||||
return nil, tfe.ErrResourceNotFound
|
return nil, tfe.ErrResourceNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(planOutput), nil
|
return planOutput, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type MockTaskStages struct {
|
type MockTaskStages struct {
|
||||||
@ -1101,7 +1112,7 @@ func (m *MockRuns) ReadWithOptions(ctx context.Context, runID string, options *t
|
|||||||
}
|
}
|
||||||
|
|
||||||
logs, _ := ioutil.ReadFile(m.client.Plans.logs[r.Plan.LogReadURL])
|
logs, _ := ioutil.ReadFile(m.client.Plans.logs[r.Plan.LogReadURL])
|
||||||
if r.Status == tfe.RunPlanning && r.Plan.Status == tfe.PlanFinished {
|
if (r.Status == tfe.RunPlanning || r.Status == tfe.RunPlannedAndSaved) && r.Plan.Status == tfe.PlanFinished {
|
||||||
hasChanges := r.IsDestroy ||
|
hasChanges := r.IsDestroy ||
|
||||||
bytes.Contains(logs, []byte("1 to add")) ||
|
bytes.Contains(logs, []byte("1 to add")) ||
|
||||||
bytes.Contains(logs, []byte("1 to change")) ||
|
bytes.Contains(logs, []byte("1 to change")) ||
|
||||||
@ -1110,6 +1121,7 @@ func (m *MockRuns) ReadWithOptions(ctx context.Context, runID string, options *t
|
|||||||
r.Actions.IsCancelable = false
|
r.Actions.IsCancelable = false
|
||||||
r.Actions.IsConfirmable = true
|
r.Actions.IsConfirmable = true
|
||||||
r.HasChanges = true
|
r.HasChanges = true
|
||||||
|
r.Plan.HasChanges = true
|
||||||
r.Permissions.CanApply = true
|
r.Permissions.CanApply = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user