diff --git a/helper/resource/teststep_providers_test.go b/helper/resource/teststep_providers_test.go index bce1c19d1a8..2be5aa30178 100644 --- a/helper/resource/teststep_providers_test.go +++ b/helper/resource/teststep_providers_test.go @@ -1075,6 +1075,7 @@ func TestTest_TestStep_Taint(t *testing.T) { } } +//nolint:unparam func extractResourceAttr(resourceName string, attributeName string, attributeValue *string) TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -1252,6 +1253,8 @@ func TestTest_TestStep_ProviderFactories_To_ExternalProviders(t *testing.T) { } func TestTest_TestStep_ProviderFactories_Import_Inline(t *testing.T) { + id := "none" + t.Parallel() Test(t, TestCase{ @@ -1315,9 +1318,8 @@ func TestTest_TestStep_ProviderFactories_Import_Inline(t *testing.T) { ImportStateId: "Z=:cbrJE?Ltg", ImportStatePersist: true, ImportStateCheck: composeImportStateCheck( - testCheckResourceAttrInstanceState("id", "none"), - testCheckResourceAttrInstanceState("result", "Z=:cbrJE?Ltg"), - testCheckResourceAttrInstanceState("length", "12"), + testCheckResourceAttrInstanceState(&id, "result", "Z=:cbrJE?Ltg"), + testCheckResourceAttrInstanceState(&id, "length", "12"), ), }, }, @@ -1390,7 +1392,7 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_WithPersistMatch(t *testi ImportStateId: "Z=:cbrJE?Ltg", ImportStatePersist: true, ImportStateCheck: composeImportStateCheck( - testExtractResourceAttrInstanceState("result", &result1), + testExtractResourceAttrInstanceState("none", "result", &result1), ), }, { @@ -1483,6 +1485,8 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_WithoutPersist(t *testing } func TestTest_TestStep_ProviderFactories_Import_External(t *testing.T) { + id := "none" + t.Parallel() Test(t, TestCase{ @@ -1499,9 +1503,8 @@ func TestTest_TestStep_ProviderFactories_Import_External(t *testing.T) { ImportStateId: "Z=:cbrJE?Ltg", ImportStatePersist: true, ImportStateCheck: composeImportStateCheck( - testCheckResourceAttrInstanceState("id", "none"), - testCheckResourceAttrInstanceState("result", "Z=:cbrJE?Ltg"), - testCheckResourceAttrInstanceState("length", "12"), + testCheckResourceAttrInstanceState(&id, "result", "Z=:cbrJE?Ltg"), + testCheckResourceAttrInstanceState(&id, "length", "12"), ), }, }, @@ -1527,7 +1530,7 @@ func TestTest_TestStep_ProviderFactories_Import_External_WithPersistMatch(t *tes ImportStateId: "Z=:cbrJE?Ltg", ImportStatePersist: true, ImportStateCheck: composeImportStateCheck( - testExtractResourceAttrInstanceState("result", &result1), + testExtractResourceAttrInstanceState("none", "result", &result1), ), }, { @@ -1560,7 +1563,7 @@ func TestTest_TestStep_ProviderFactories_Import_External_WithoutPersistNonMatch( ImportStateId: "Z=:cbrJE?Ltg", ImportStatePersist: false, ImportStateCheck: composeImportStateCheck( - testExtractResourceAttrInstanceState("result", &result1), + testExtractResourceAttrInstanceState("none", "result", &result1), ), }, { @@ -1574,6 +1577,188 @@ func TestTest_TestStep_ProviderFactories_Import_External_WithoutPersistNonMatch( }) } +func TestTest_TestStep_ProviderFactories_Import_Inline_With_Data_Source(t *testing.T) { + var id string + + t.Parallel() + + Test(t, TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "http": func() (*schema.Provider, error) { //nolint:unparam // required signature + return &schema.Provider{ + DataSourcesMap: map[string]*schema.Resource{ + "http": { + ReadContext: func(ctx context.Context, d *schema.ResourceData, i interface{}) (diags diag.Diagnostics) { + url := d.Get("url").(string) + + responseHeaders := map[string]string{ + "headerOne": "one", + "headerTwo": "two", + "headerThree": "three", + "headerFour": "four", + } + if err := d.Set("response_headers", responseHeaders); err != nil { + return append(diags, diag.Errorf("Error setting HTTP response headers: %s", err)...) + } + + d.SetId(url) + + return diags + }, + Schema: map[string]*schema.Schema{ + "url": { + Type: schema.TypeString, + Required: true, + }, + "response_headers": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, nil + }, + "random": func() (*schema.Provider, error) { //nolint:unparam // required signature + return &schema.Provider{ + ResourcesMap: map[string]*schema.Resource{ + "random_string": { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + d.SetId("none") + err := d.Set("length", 4) + if err != nil { + panic(err) + } + err = d.Set("result", "none") + if err != nil { + panic(err) + } + return nil + }, + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + Schema: map[string]*schema.Schema{ + "length": { + Required: true, + ForceNew: true, + Type: schema.TypeInt, + }, + "result": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "id": { + Computed: true, + Type: schema.TypeString, + }, + }, + Importer: &schema.ResourceImporter{ + StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + val := d.Id() + + d.SetId(val) + + err := d.Set("result", val) + if err != nil { + panic(err) + } + + err = d.Set("length", len(val)) + if err != nil { + panic(err) + } + + return []*schema.ResourceData{d}, nil + }, + }, + }, + }, + }, nil + }, + }, + Steps: []TestStep{ + { + Config: `data "http" "example" { + url = "https://checkpoint-api.hashicorp.com/v1/check/terraform" + } + + resource "random_string" "example" { + length = length(data.http.example.response_headers) + }`, + Check: extractResourceAttr("random_string.example", "id", &id), + }, + { + Config: `data "http" "example" { + url = "https://checkpoint-api.hashicorp.com/v1/check/terraform" + } + + resource "random_string" "example" { + length = length(data.http.example.response_headers) + }`, + ResourceName: "random_string.example", + ImportState: true, + ImportStateCheck: composeImportStateCheck( + testCheckResourceAttrInstanceState(&id, "length", "4"), + ), + ImportStateVerify: true, + }, + }, + }) +} + +func TestTest_TestStep_ProviderFactories_Import_External_With_Data_Source(t *testing.T) { + var id string + + t.Parallel() + + Test(t, TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "http": { + Source: "registry.terraform.io/hashicorp/http", + }, + "random": { + Source: "registry.terraform.io/hashicorp/random", + }, + }, + Steps: []TestStep{ + { + Config: `data "http" "example" { + url = "https://checkpoint-api.hashicorp.com/v1/check/terraform" + } + + resource "random_string" "example" { + length = length(data.http.example.response_headers) + }`, + Check: extractResourceAttr("random_string.example", "id", &id), + }, + { + Config: `data "http" "example" { + url = "https://checkpoint-api.hashicorp.com/v1/check/terraform" + } + + resource "random_string" "example" { + length = length(data.http.example.response_headers) + }`, + ResourceName: "random_string.example", + ImportState: true, + ImportStateCheck: composeImportStateCheck( + testCheckResourceAttrInstanceState(&id, "length", "12"), + ), + ImportStateVerify: true, + }, + }, + }) +} + func composeImportStateCheck(fs ...ImportStateCheckFunc) ImportStateCheckFunc { return func(s []*terraform.InstanceState) error { for i, f := range fs { @@ -1586,43 +1771,41 @@ func composeImportStateCheck(fs ...ImportStateCheckFunc) ImportStateCheckFunc { } } -func testExtractResourceAttrInstanceState(attributeName string, attributeValue *string) ImportStateCheckFunc { +func testExtractResourceAttrInstanceState(id, attributeName string, attributeValue *string) ImportStateCheckFunc { return func(is []*terraform.InstanceState) error { - if len(is) != 1 { - return fmt.Errorf("unexpected number of instance states: %d", len(is)) - } + for _, v := range is { + if v.ID != id { + continue + } - s := is[0] + if attrVal, ok := v.Attributes[attributeName]; ok { + *attributeValue = attrVal - attrValue, ok := s.Attributes[attributeName] - if !ok { - return fmt.Errorf("attribute %s not found in instance state", attributeName) + return nil + } } - *attributeValue = attrValue - - return nil + return fmt.Errorf("attribute %s not found in instance state", attributeName) } } -func testCheckResourceAttrInstanceState(attributeName, attributeValue string) ImportStateCheckFunc { +func testCheckResourceAttrInstanceState(id *string, attributeName, attributeValue string) ImportStateCheckFunc { return func(is []*terraform.InstanceState) error { - if len(is) != 1 { - return fmt.Errorf("unexpected number of instance states: %d", len(is)) - } + for _, v := range is { + if v.ID != *id { + continue + } - s := is[0] + if attrVal, ok := v.Attributes[attributeName]; ok { + if attrVal != attributeValue { + return fmt.Errorf("expected: %s got: %s", attributeValue, attrVal) + } - attrVal, ok := s.Attributes[attributeName] - if !ok { - return fmt.Errorf("attribute %s found in instance state", attributeName) - } - - if attrVal != attributeValue { - return fmt.Errorf("expected: %s got: %s", attributeValue, attrVal) + return nil + } } - return nil + return fmt.Errorf("attribute %s not found in instance state", attributeName) } }