diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go index a24854aeeaaf..f46675d9a273 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_mmv1_resources.go @@ -3,6 +3,7 @@ package fwprovider import ( "github.com/hashicorp/terraform-plugin-framework/list" + "github.com/hashicorp/terraform-provider-google/google/services/dns" "github.com/hashicorp/terraform-provider-google/google/services/resourcemanager" ) @@ -17,4 +18,5 @@ var generatedListResources = []func() list.ListResource{} var handwrittenListResources = []func() list.ListResource{ listResourceFunc(resourcemanager.NewGoogleServiceAccountListResource()), listResourceFunc(resourcemanager.NewGoogleProjectServiceListResource()), + listResourceFunc(dns.NewGoogleDnsRecordSetListResource()), } diff --git a/mmv1/third_party/terraform/services/dns/list_google_dns_record_set.go b/mmv1/third_party/terraform/services/dns/list_google_dns_record_set.go new file mode 100644 index 000000000000..d3ddb779f307 --- /dev/null +++ b/mmv1/third_party/terraform/services/dns/list_google_dns_record_set.go @@ -0,0 +1,194 @@ +package dns + +import ( + "context" + "errors" + "fmt" + + frameworkdiag "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/list" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + googledns "google.golang.org/api/dns/v1" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +type GoogleDnsRecordSetResource struct { + tpgresource.ListResourceMetadata +} + +type GoogleDnsRecordSetListModel struct { + Project types.String `tfsdk:"project"` + ManagedZone types.String `tfsdk:"managed_zone"` + Name types.String `tfsdk:"name"` + Type types.String `tfsdk:"type"` +} + +func NewGoogleDnsRecordSetListResource() list.ListResource { + listR := &GoogleDnsRecordSetResource{} + listR.TypeName = "google_dns_record_set" + listR.SDKv2Resource = ResourceDnsRecordSet() + listR.ListConfigFields = []tpgresource.ListConfigField{ + {Name: "project", Kind: tpgresource.ListConfigKindString, Optional: true}, + {Name: "managed_zone", Kind: tpgresource.ListConfigKindString, Optional: false}, + {Name: "name", Kind: tpgresource.ListConfigKindString, Optional: true}, + {Name: "type", Kind: tpgresource.ListConfigKindString, Optional: true}, + } + return listR +} + +func (listR *GoogleDnsRecordSetResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) { + var data GoogleDnsRecordSetListModel + diags := req.Config.Get(ctx, &data) + + if diags.HasError() { + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + + if listR.Client == nil { + diags = append(diags, frameworkdiag.NewErrorDiagnostic( + "provider not configured", + "The Google provider client is not available; ensure the prtovider is configured.", + )) + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + + project := listR.GetProject(data.Project) + managedZone := data.ManagedZone.ValueString() + recordName := "" + recordType := "" + + if !data.Name.IsNull() && !data.Name.IsUnknown() { + recordName = data.Name.ValueString() + } + + if !data.Type.IsNull() && !data.Type.IsUnknown() { + recordType = data.Type.ValueString() + } + + stream.Results = func(push func(list.ListResult) bool) { + err := ListDnsRecordSets(listR.Client, project, managedZone, recordName, recordType, func(rd *schema.ResourceData) error { + result := req.NewListResult(ctx) + + if err := listR.SetResult(ctx, req.IncludeResource, &result, rd); err != nil { + return err + } + + if !push(result) { + return errors.New("stream closed") + } + return nil + }) + + if err != nil { + diags.AddError("API Error", err.Error()) + result := req.NewListResult(ctx) + result.Diagnostics = diags + push(result) + } + + stream.Results = list.ListResultsStreamDiagnostics(diags) + } +} + +func flattenGoogleDNSRecordSetListItem( + rrset *googledns.ResourceRecordSet, + d *schema.ResourceData, + project string, + managedZone string, +) error { + if err := d.Set("project", project); err != nil { + return fmt.Errorf("error setting project: %w", err) + } + + if err := d.Set("managed_zone", managedZone); err != nil { + return fmt.Errorf("error setting managed_zone: %w", err) + } + + if err := d.Set("name", rrset.Name); err != nil { + return fmt.Errorf("error setting name: %w", err) + } + + if err := d.Set("type", rrset.Type); err != nil { + return fmt.Errorf("error setting type: %w", err) + } + + if err := d.Set("ttl", rrset.Ttl); err != nil { + return fmt.Errorf("error setting ttl: %w", err) + } + + if err := d.Set("rrdatas", rrset.Rrdatas); err != nil { + return fmt.Errorf("error setting rrdatas: %w", err) + } + + if err := d.Set("routing_policy", flattenDnsRecordSetRoutingPolicy(rrset.RoutingPolicy)); err != nil { + return fmt.Errorf("error setting routing_policy: %w", err) + } + + d.SetId(fmt.Sprintf( + "project/%s/managedZones/%s/rrsets/%s/%s", + project, + managedZone, + rrset.Name, + rrset.Type, + )) + + return nil +} + +func ListDnsRecordSets( + config *transport_tpg.Config, + project string, + managedZone string, + recordName string, + recordType string, + callback func(*schema.ResourceData) error, +) error { + if config == nil { + return fmt.Errorf("provider client is not configured") + } + + tempData := ResourceDnsRecordSet().Data(&terraform.InstanceState{}) + if project != "" { + if err := tempData.Set("project", project); err != nil { + return fmt.Errorf("error setting project on temporary resource data: %w", err) + } + } + if err := tempData.Set("managed_zone", managedZone); err != nil { + return fmt.Errorf("error setting managed_zone on temporary resource data: %w", err) + } + + userAgent, err := tpgresource.GenerateUserAgentString(tempData, config.UserAgent) + if err != nil { + return err + } + + req := config.NewDnsClient(userAgent).ResourceRecordSets.List(project, managedZone) + + if recordName != "" { + req = req.Name(recordName) + if recordType != "" { + req = req.Type(recordType) + } + } + + return req.Pages(context.Background(), func(resp *googledns.ResourceRecordSetsListResponse) error { + for _, rrset := range resp.Rrsets { + rd := ResourceDnsRecordSet().Data(&terraform.InstanceState{}) + + if err := flattenGoogleDNSRecordSetListItem(rrset, rd, project, managedZone); err != nil { + return err + } + + if err := callback(rd); err != nil { + return err + } + } + return nil + }) +} diff --git a/mmv1/third_party/terraform/services/dns/list_google_dns_record_set_test.go b/mmv1/third_party/terraform/services/dns/list_google_dns_record_set_test.go new file mode 100644 index 000000000000..2c47f38384e6 --- /dev/null +++ b/mmv1/third_party/terraform/services/dns/list_google_dns_record_set_test.go @@ -0,0 +1,70 @@ +package dns_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/querycheck" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDNSRecordSetListResource_queryIdentity(t *testing.T) { + t.Parallel() + + zoneName := "list-dnszone-test-" + acctest.RandString(t, 10) + project := envvar.GetTestProjectFromEnv() + t.Logf("Using project %s for testing", project) + recordName := fmt.Sprintf("test-record.%s.hashicorptest.com.", zoneName) + + acctest.VcrTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDnsRecordSet_basic(zoneName, "127.0.0.10", 300), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "project", project), + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "managed_zone", zoneName), + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "name", recordName), + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "type", "A"), + ), + }, + { + Query: true, + Config: testAccDNSRecordSetListQuery(project, zoneName), + QueryResultChecks: []querycheck.QueryResultCheck{ + querycheck.ExpectIdentity("google_dns_record_set.all_in_zone", map[string]knownvalue.Check{ + "project": knownvalue.StringExact(project), + "managed_zone": knownvalue.StringExact(zoneName), + "name": knownvalue.StringExact(recordName), + "type": knownvalue.StringExact("A"), + }), + querycheck.ExpectLengthAtLeast("google_dns_record_set.all_in_zone", 1), + }, + }, + }, + }) +} + +func testAccDNSRecordSetListQuery(project, managedZone string) string { + return fmt.Sprintf(` +provider "google" {} + +list "google_dns_record_set" "all_in_zone" { + provider = google + + config { + project = %q + managed_zone = %q + } +} +`, project, managedZone) +} diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go b/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go index 3a776ab0f0b2..4e0c54dbcfdf 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go +++ b/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go @@ -100,6 +100,30 @@ func ResourceDnsRecordSet() *schema.Resource { tpgresource.DefaultProviderProject, ), + Identity: &schema.ResourceIdentity{ + Version: 1, + SchemaFunc: func() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + OptionalForImport: true, + }, + "managed_zone": { + Type: schema.TypeString, + RequiredForImport: true, + }, + "name": { + Type: schema.TypeString, + RequiredForImport: true, + }, + "type": { + Type: schema.TypeString, + RequiredForImport: true, + }, + } + }, + }, + Schema: map[string]*schema.Schema{ "managed_zone": { Type: schema.TypeString, @@ -477,6 +501,15 @@ func resourceDnsRecordSetRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error setting project: %s", err) } + if err := tpgresource.SetResourceIdentityAttributes(d, map[string]interface{}{ + "project": project, + "managed_zone": zone, + "name": rrset.Name, + "type": rrset.Type, + }); err != nil { + return fmt.Errorf("Error setting resource identity: %s", err) + } + return nil } diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_record_set_test.go.tmpl b/mmv1/third_party/terraform/services/dns/resource_dns_record_set_test.go.tmpl index 325fffcc0e0e..14e8fab8e9bd 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_record_set_test.go.tmpl +++ b/mmv1/third_party/terraform/services/dns/resource_dns_record_set_test.go.tmpl @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfversion" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" @@ -592,6 +593,40 @@ func testAccCheckDnsRecordSetSetRrdataOutOfBand(t *testing.T, zoneName, rrsetNam } } +func TestAccDNSRecordSet_importBlockWithResourceIdentity(t *testing.T) { + t.Parallel() + + zoneName := fmt.Sprintf("dnszone-test-%s", acctest.RandString(t, 10)) + project := envvar.GetTestProjectFromEnv() + recordName := fmt.Sprintf("test-record.%s.hashicorptest.com.", zoneName) + + acctest.VcrTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_12_0), + }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDnsRecordSetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDnsRecordSet_basic(zoneName, "127.0.0.10", 300), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "project", project), + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "managed_zone", zoneName), + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "name", recordName), + resource.TestCheckResourceAttr("google_dns_record_set.foobar", "type", "A"), + ), + }, + { + ResourceName: "google_dns_record_set.foobar", + ImportState: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckDnsRecordSetDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error {