|
|
|
|
@ -2492,6 +2492,151 @@ resource "test_object" "foo" {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestContext2Apply_mockProviderRequiredSchema(t *testing.T) {
|
|
|
|
|
m := testModuleInline(t, map[string]string{
|
|
|
|
|
"main.tf": `
|
|
|
|
|
provider "test" {}
|
|
|
|
|
|
|
|
|
|
data "test_object" "foo" {}
|
|
|
|
|
|
|
|
|
|
resource "test_object" "foo" {
|
|
|
|
|
value = data.test_object.foo.output
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Manually mark the provider config as being mocked.
|
|
|
|
|
m.Module.ProviderConfigs["test"].Mock = true
|
|
|
|
|
m.Module.ProviderConfigs["test"].MockData = &configs.MockData{
|
|
|
|
|
MockDataSources: map[string]*configs.MockResource{
|
|
|
|
|
"test_object": {
|
|
|
|
|
Mode: addrs.DataResourceMode,
|
|
|
|
|
Type: "test_object",
|
|
|
|
|
Defaults: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"output": cty.StringVal("expected data output"),
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
MockResources: map[string]*configs.MockResource{
|
|
|
|
|
"test_object": {
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Type: "test_object",
|
|
|
|
|
Defaults: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"output": cty.StringVal("expected resource output"),
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This time our test provider has a required attribute that we don't
|
|
|
|
|
// provide in the configuration. The fact we've marked this provider as a
|
|
|
|
|
// mock means the missing required attribute doesn't matter.
|
|
|
|
|
|
|
|
|
|
testProvider := &MockProvider{
|
|
|
|
|
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
|
|
|
|
|
Provider: providers.Schema{
|
|
|
|
|
Block: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"required": {
|
|
|
|
|
Type: cty.String,
|
|
|
|
|
Required: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
ResourceTypes: map[string]providers.Schema{
|
|
|
|
|
"test_object": {
|
|
|
|
|
Block: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"value": {
|
|
|
|
|
Type: cty.String,
|
|
|
|
|
Required: true,
|
|
|
|
|
},
|
|
|
|
|
"output": {
|
|
|
|
|
Type: cty.String,
|
|
|
|
|
Computed: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
DataSources: map[string]providers.Schema{
|
|
|
|
|
"test_object": {
|
|
|
|
|
Block: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"output": {
|
|
|
|
|
Type: cty.String,
|
|
|
|
|
Computed: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reachedReadDataSourceFn := false
|
|
|
|
|
reachedPlanResourceChangeFn := false
|
|
|
|
|
reachedApplyResourceChangeFn := false
|
|
|
|
|
testProvider.ReadDataSourceFn = func(request providers.ReadDataSourceRequest) (resp providers.ReadDataSourceResponse) {
|
|
|
|
|
reachedReadDataSourceFn = true
|
|
|
|
|
cfg := request.Config.AsValueMap()
|
|
|
|
|
cfg["output"] = cty.StringVal("unexpected data output")
|
|
|
|
|
resp.State = cty.ObjectVal(cfg)
|
|
|
|
|
return resp
|
|
|
|
|
}
|
|
|
|
|
testProvider.PlanResourceChangeFn = func(request providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
|
|
|
|
|
reachedPlanResourceChangeFn = true
|
|
|
|
|
cfg := request.Config.AsValueMap()
|
|
|
|
|
cfg["output"] = cty.UnknownVal(cty.String)
|
|
|
|
|
resp.PlannedState = cty.ObjectVal(cfg)
|
|
|
|
|
return resp
|
|
|
|
|
}
|
|
|
|
|
testProvider.ApplyResourceChangeFn = func(request providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) {
|
|
|
|
|
reachedApplyResourceChangeFn = true
|
|
|
|
|
cfg := request.Config.AsValueMap()
|
|
|
|
|
cfg["output"] = cty.StringVal("unexpected resource output")
|
|
|
|
|
resp.NewState = cty.ObjectVal(cfg)
|
|
|
|
|
return resp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
|
Providers: map[addrs.Provider]providers.Factory{
|
|
|
|
|
addrs.NewDefaultProvider("test"): testProviderFuncFixed(testProvider),
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
plan, diags := ctx.Plan(m, states.NewState(), &PlanOpts{
|
|
|
|
|
Mode: plans.NormalMode,
|
|
|
|
|
})
|
|
|
|
|
if diags.HasErrors() {
|
|
|
|
|
t.Fatalf("expected no errors, but got %s", diags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state, diags := ctx.Apply(plan, m, nil)
|
|
|
|
|
if diags.HasErrors() {
|
|
|
|
|
t.Fatalf("expected no errors, but got %s", diags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check we never made it to the actual provider.
|
|
|
|
|
if reachedReadDataSourceFn {
|
|
|
|
|
t.Errorf("read the data source in the provider when it should have been mocked")
|
|
|
|
|
}
|
|
|
|
|
if reachedPlanResourceChangeFn {
|
|
|
|
|
t.Errorf("planned the resource in the provider when it should have been mocked")
|
|
|
|
|
}
|
|
|
|
|
if reachedApplyResourceChangeFn {
|
|
|
|
|
t.Errorf("applied the resource in the provider when it should have been mocked")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check we got the right data back from our mocked provider.
|
|
|
|
|
instance := state.ResourceInstance(mustResourceInstanceAddr("test_object.foo"))
|
|
|
|
|
expected := "{\"output\":\"expected resource output\",\"value\":\"expected data output\"}"
|
|
|
|
|
if diff := cmp.Diff(string(instance.Current.AttrsJSON), expected); len(diff) > 0 {
|
|
|
|
|
t.Errorf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, string(instance.Current.AttrsJSON), diff)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestContext2Apply_forget(t *testing.T) {
|
|
|
|
|
addrA := mustResourceInstanceAddr("test_object.a")
|
|
|
|
|
m := testModuleInline(t, map[string]string{
|
|
|
|
|
|