From 72c5102df5484c806223302416d66b4eebe7cd3c Mon Sep 17 00:00:00 2001 From: megan07 Date: Mon, 6 Feb 2023 10:59:11 -0600 Subject: [PATCH] dns managed zone with plugin-framework (#7182) * initial commit for muxer and framework provider * minor changes to new provider and muxer * add provider model, provider schema, defaults in config * initial commit to upgrading the provider * match schema to sdk provider * remove duplicates * add dns record set, test and provider schema update * add dcl custom endpoints, custom endpoint validator and credentials validator * mv sdk provider defaults to config, fix up other small issues * add changes from merging with main * working with provider meta * move MultiEnvDefault function so it will hopefully be picked up by the validator * don't need to downgrade the provider * fix beta build issue * remove redundant dcl generated custom endpoint * strange org policy issue - only needed in ga * fix failures in beta * fix vcr tests * fix vcr tests for real hopefully * fix provider meta error * Update record set data source test to compare muxed provider to v4.50.0 This includes copying useful test util functions from terraform-provider-random (https://github.com/hashicorp/terraform-provider-random/blob/main/internal/provider/resource_integer_test.go#L1006) * Fix error in `providerVersion450` * add framework_test_utils * add functionality to configure the test framework provider and get check destroys working * add managed zone check destroy * add tflog to framework files * review comment changes * use version.ProviderVersion * add comment for test provider configure function * remove redundant Cloudbuildv2CustomEndpoint endpoint on framework provider * add dns_managed_zone data source * fix metadata error * fix bad merge spots * one more fix from manual merge * add acc test for comparing with version450 * add markdown description and descrption * fix formatting --------- Co-authored-by: Sarah French --- .../data_source_dns_managed_zone.go | 191 ++++++++++++------ .../data_source_dns_managed_zone_test.go.erb | 46 ++++- .../terraform/utils/framework_provider.go.erb | 1 + .../terraform/utils/provider.go.erb | 1 - 4 files changed, 167 insertions(+), 72 deletions(-) diff --git a/mmv1/third_party/terraform/data_sources/data_source_dns_managed_zone.go b/mmv1/third_party/terraform/data_sources/data_source_dns_managed_zone.go index 734fe2ac8f52..6d45298b4b8a 100644 --- a/mmv1/third_party/terraform/data_sources/data_source_dns_managed_zone.go +++ b/mmv1/third_party/terraform/data_sources/data_source_dns_managed_zone.go @@ -1,101 +1,170 @@ package google import ( + "context" "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "google.golang.org/api/dns/v1" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" ) -func dataSourceDnsManagedZone() *schema.Resource { - return &schema.Resource{ - Read: dataSourceDnsManagedZoneRead, +var _ datasource.DataSource = &GoogleDnsManagedZoneDataSource{} - Schema: map[string]*schema.Schema{ - "dns_name": { - Type: schema.TypeString, - Computed: true, +func NewGoogleDnsManagedZoneDataSource() datasource.DataSource { + return &GoogleDnsManagedZoneDataSource{} +} + +// GoogleDnsManagedZoneDataSource defines the data source implementation +type GoogleDnsManagedZoneDataSource struct { + client *dns.Service + project types.String +} + +type GoogleDnsManagedZoneModel struct { + Id types.String `tfsdk:"id"` + DnsName types.String `tfsdk:"dns_name"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + ManagedZoneId types.Int64 `tfsdk:"managed_zone_id"` + NameServers types.List `tfsdk:"name_servers"` + Visibility types.String `tfsdk:"visibility"` + Project types.String `tfsdk:"project"` +} + +func (d *GoogleDnsManagedZoneDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_dns_managed_zone" +} + +func (d *GoogleDnsManagedZoneDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "Provides access to a zone's attributes within Google Cloud DNS", + + Attributes: map[string]schema.Attribute{ + "dns_name": schema.StringAttribute{ + Description: "The fully qualified DNS name of this zone.", + MarkdownDescription: "The fully qualified DNS name of this zone.", + Computed: true, }, - "name": { - Type: schema.TypeString, - Required: true, + "name": schema.StringAttribute{ + Description: "A unique name for the resource.", + MarkdownDescription: "A unique name for the resource.", + Required: true, }, - "description": { - Type: schema.TypeString, - Computed: true, + "description": schema.StringAttribute{ + Description: "A textual description field.", + MarkdownDescription: "A textual description field.", + Computed: true, }, - "managed_zone_id": { - Type: schema.TypeInt, - Computed: true, - Description: `Unique identifier for the resource; defined by the server.`, + "managed_zone_id": schema.Int64Attribute{ + Description: "Unique identifier for the resource; defined by the server.", + MarkdownDescription: "Unique identifier for the resource; defined by the server.", + Computed: true, }, - "name_servers": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + "name_servers": schema.ListAttribute{ + Description: "The list of nameservers that will be authoritative for this " + + "domain. Use NS records to redirect from your DNS provider to these names, " + + "thus making Google Cloud DNS authoritative for this zone.", + MarkdownDescription: "The list of nameservers that will be authoritative for this " + + "domain. Use NS records to redirect from your DNS provider to these names, " + + "thus making Google Cloud DNS authoritative for this zone.", + Computed: true, + ElementType: types.StringType, }, - "visibility": { - Type: schema.TypeString, + "visibility": schema.StringAttribute{ + Description: "The zone's visibility: public zones are exposed to the Internet, " + + "while private zones are visible only to Virtual Private Cloud resources.", + MarkdownDescription: "The zone's visibility: public zones are exposed to the Internet, " + + "while private zones are visible only to Virtual Private Cloud resources.", Computed: true, }, // Google Cloud DNS ManagedZone resources do not have a SelfLink attribute. - "project": { - Type: schema.TypeString, - Optional: true, + "project": schema.StringAttribute{ + Description: "The ID of the project for the Google Cloud.", + MarkdownDescription: "The ID of the project for the Google Cloud.", + Optional: true, + }, + "id": schema.StringAttribute{ + Description: "DNS managed zone identifier", + MarkdownDescription: "DNS managed zone identifier", + Computed: true, }, }, } } -func dataSourceDnsManagedZoneRead(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) - if err != nil { - return err +func (d *GoogleDnsManagedZoneDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return } - project, err := getProject(d, config) - if err != nil { - return err + p, ok := req.ProviderData.(*frameworkProvider) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *frameworkProvider, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return } - name := d.Get("name").(string) - d.SetId(fmt.Sprintf("projects/%s/managedZones/%s", project, name)) + d.client = p.NewDnsClient(p.userAgent, &resp.Diagnostics) + d.project = p.project +} - zone, err := config.NewDnsClient(userAgent).ManagedZones.Get( - project, name).Do() - if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("dataSourceDnsManagedZone %q", name)) - } +func (d *GoogleDnsManagedZoneDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data GoogleDnsManagedZoneModel + var metaData *ProviderMetaModel + var diags diag.Diagnostics - if err := d.Set("dns_name", zone.DnsName); err != nil { - return fmt.Errorf("Error setting dns_name: %s", err) - } - if err := d.Set("name", zone.Name); err != nil { - return fmt.Errorf("Error setting name: %s", err) - } - if err := d.Set("description", zone.Description); err != nil { - return fmt.Errorf("Error setting description: %s", err) + // Read Provider meta into the meta model + resp.Diagnostics.Append(req.ProviderMeta.Get(ctx, &metaData)...) + if resp.Diagnostics.HasError() { + return } - if err := d.Set("managed_zone_id", zone.Id); err != nil { - return fmt.Errorf("Error setting managed_zone_id: %s", err) + + d.client.UserAgent = generateFrameworkUserAgentString(metaData, d.client.UserAgent) + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return } - if err := d.Set("name_servers", zone.NameServers); err != nil { - return fmt.Errorf("Error setting name_servers: %s", err) + + data.Project = getProjectFramework(data.Project, d.project, &resp.Diagnostics) + if resp.Diagnostics.HasError() { + return } - if err := d.Set("visibility", zone.Visibility); err != nil { - return fmt.Errorf("Error setting visibility: %s", err) + + data.Id = types.StringValue(fmt.Sprintf("projects/%s/managedZones/%s", data.Project.ValueString(), data.Name.ValueString())) + clientResp, err := d.client.ManagedZones.Get(data.Project.ValueString(), data.Name.ValueString()).Do() + if err != nil { + handleDatasourceNotFoundError(ctx, err, &resp.State, fmt.Sprintf("dataSourceDnsManagedZone %q", data.Name.ValueString()), &resp.Diagnostics) } - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error setting project: %s", err) + + tflog.Trace(ctx, "read dns record set data source") + + data.DnsName = types.StringValue(clientResp.DnsName) + data.Description = types.StringValue(clientResp.Description) + data.ManagedZoneId = types.Int64Value(int64(clientResp.Id)) + data.Visibility = types.StringValue(clientResp.Visibility) + data.NameServers, diags = types.ListValueFrom(ctx, types.StringType, clientResp.NameServers) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return } - return nil + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } diff --git a/mmv1/third_party/terraform/tests/data_source_dns_managed_zone_test.go.erb b/mmv1/third_party/terraform/tests/data_source_dns_managed_zone_test.go.erb index 319d7be24aef..c7d496652579 100644 --- a/mmv1/third_party/terraform/tests/data_source_dns_managed_zone_test.go.erb +++ b/mmv1/third_party/terraform/tests/data_source_dns_managed_zone_test.go.erb @@ -15,24 +15,50 @@ func TestAccDataSourceDnsManagedZone_basic(t *testing.T) { vcrTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckDNSManagedZoneDestroyProducer(t), + CheckDestroy: testAccCheckDNSManagedZoneDestroyProducerFramework(t), Steps: []resource.TestStep{ { + ExternalProviders: providerVersion450(), + Config: testAccDataSourceDnsManagedZone_basic(randString(t, 10)), + Check: checkDataSourceStateMatchesResourceStateWithIgnores( + "data.google_dns_managed_zone.qa", + "google_dns_managed_zone.foo", + map[string]struct{}{ + "dnssec_config.#": {}, + "private_visibility_config.#": {}, + "peering_config.#": {}, + "forwarding_config.#": {}, + "force_destroy": {}, + "labels.#": {}, + "creation_time": {}, + "cloud_logging_config.#": {}, + "cloud_logging_config.0.%": {}, + "cloud_logging_config.0.enable_logging": {}, +<% unless version == "ga" -%> + "reverse_lookup": {}, +<% end -%> + }, + ), + }, + { + ProtoV5ProviderFactories: protoV5ProviderFactories(t), Config: testAccDataSourceDnsManagedZone_basic(randString(t, 10)), Check: checkDataSourceStateMatchesResourceStateWithIgnores( "data.google_dns_managed_zone.qa", "google_dns_managed_zone.foo", map[string]struct{}{ - "dnssec_config.#": {}, - "private_visibility_config.#": {}, - "peering_config.#": {}, - "forwarding_config.#": {}, - "force_destroy": {}, - "labels.#": {}, - "creation_time": {}, + "dnssec_config.#": {}, + "private_visibility_config.#": {}, + "peering_config.#": {}, + "forwarding_config.#": {}, + "force_destroy": {}, + "labels.#": {}, + "creation_time": {}, + "cloud_logging_config.#": {}, + "cloud_logging_config.0.%": {}, + "cloud_logging_config.0.enable_logging": {}, <% unless version == "ga" -%> - "reverse_lookup": {}, + "reverse_lookup": {}, <% end -%> }, ), diff --git a/mmv1/third_party/terraform/utils/framework_provider.go.erb b/mmv1/third_party/terraform/utils/framework_provider.go.erb index 522b67104b6a..95b55539e85b 100644 --- a/mmv1/third_party/terraform/utils/framework_provider.go.erb +++ b/mmv1/third_party/terraform/utils/framework_provider.go.erb @@ -264,6 +264,7 @@ func (p *frameworkProvider) Configure(ctx context.Context, req provider.Configur // DataSources defines the data sources implemented in the provider. func (p *frameworkProvider) DataSources(_ context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ + NewGoogleDnsManagedZoneDataSource, NewGoogleDnsRecordSetDataSource, } } diff --git a/mmv1/third_party/terraform/utils/provider.go.erb b/mmv1/third_party/terraform/utils/provider.go.erb index 9612df7910b1..44566cb4742a 100644 --- a/mmv1/third_party/terraform/utils/provider.go.erb +++ b/mmv1/third_party/terraform/utils/provider.go.erb @@ -227,7 +227,6 @@ func Provider() *schema.Provider { "google_container_registry_repository": dataSourceGoogleContainerRepo(), "google_dataproc_metastore_service": dataSourceDataprocMetastoreService(), "google_dns_keys": dataSourceDNSKeys(), - "google_dns_managed_zone": dataSourceDnsManagedZone(), "google_game_services_game_server_deployment_rollout": dataSourceGameServicesGameServerDeploymentRollout(), "google_iam_policy": dataSourceGoogleIamPolicy(), "google_iam_role": dataSourceGoogleIamRole(),