Skip to content

Commit

Permalink
dns managed zone with plugin-framework (#7182)
Browse files Browse the repository at this point in the history
* 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 <sarah.french@hashicorp.com>
  • Loading branch information
megan07 and SarahFrench authored Feb 6, 2023
1 parent 4cab4a1 commit 72c5102
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 72 deletions.
191 changes: 130 additions & 61 deletions mmv1/third_party/terraform/data_sources/data_source_dns_managed_zone.go
Original file line number Diff line number Diff line change
@@ -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)...)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 -%>
},
),
Expand Down
1 change: 1 addition & 0 deletions mmv1/third_party/terraform/utils/framework_provider.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down
1 change: 0 additions & 1 deletion mmv1/third_party/terraform/utils/provider.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down

0 comments on commit 72c5102

Please sign in to comment.