diff --git a/.changelog/3524.txt b/.changelog/3524.txt new file mode 100644 index 00000000000..39557c09bc1 --- /dev/null +++ b/.changelog/3524.txt @@ -0,0 +1,6 @@ +```release-note:note +dns: Promoted `google_dns_policy` to GA. +``` +```release-note:note +dns: Promoted the following `google_dns_managed_zone ` fields to GA: `forwarding_config`, `peering_config` +``` diff --git a/google/data_source_dns_managed_zone_test.go b/google/data_source_dns_managed_zone_test.go index 42a3e4f2902..fc18c18010f 100644 --- a/google/data_source_dns_managed_zone_test.go +++ b/google/data_source_dns_managed_zone_test.go @@ -23,6 +23,8 @@ func TestAccDataSourceDnsManagedZone_basic(t *testing.T) { map[string]struct{}{ "dnssec_config.#": {}, "private_visibility_config.#": {}, + "peering_config.#": {}, + "forwarding_config.#": {}, }, ), }, diff --git a/google/provider.go b/google/provider.go index 9f5e04ac74b..586b183c183 100644 --- a/google/provider.go +++ b/google/provider.go @@ -556,9 +556,9 @@ func Provider() terraform.ResourceProvider { return provider } -// Generated resources: 129 +// Generated resources: 130 // Generated IAM resources: 57 -// Total generated resources: 186 +// Total generated resources: 187 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -669,6 +669,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_dialogflow_intent": resourceDialogflowIntent(), "google_dialogflow_entity_type": resourceDialogflowEntityType(), "google_dns_managed_zone": resourceDNSManagedZone(), + "google_dns_policy": resourceDNSPolicy(), "google_filestore_instance": resourceFilestoreInstance(), "google_firestore_index": resourceFirestoreIndex(), "google_healthcare_dataset": resourceHealthcareDataset(), diff --git a/google/resource_dns_managed_zone.go b/google/resource_dns_managed_zone.go index e39f499220a..069e796cf87 100644 --- a/google/resource_dns_managed_zone.go +++ b/google/resource_dns_managed_zone.go @@ -139,12 +139,69 @@ non_existence can only be updated when the state is 'off'. Possible values: ["ns }, }, }, + "forwarding_config": { + Type: schema.TypeList, + Optional: true, + Description: `The presence for this field indicates that outbound forwarding is enabled +for this zone. The value of this field contains the set of destinations +to forward to.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target_name_servers": { + Type: schema.TypeSet, + Required: true, + Description: `List of target name servers to forward to. Cloud DNS will +select the best available name server if more than +one target is given.`, + Elem: dnsManagedZoneForwardingConfigTargetNameServersSchema(), + Set: func(v interface{}) int { + raw := v.(map[string]interface{}) + if address, ok := raw["ipv4_address"]; ok { + hashcode.String(address.(string)) + } + var buf bytes.Buffer + schema.SerializeResourceForHash(&buf, raw, dnsManagedZoneForwardingConfigTargetNameServersSchema()) + return hashcode.String(buf.String()) + }, + }, + }, + }, + }, "labels": { Type: schema.TypeMap, Optional: true, Description: `A set of key/value label pairs to assign to this ManagedZone.`, Elem: &schema.Schema{Type: schema.TypeString}, }, + "peering_config": { + Type: schema.TypeList, + Optional: true, + Description: `The presence of this field indicates that DNS Peering is enabled for this +zone. The value of this field contains the network to peer with.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target_network": { + Type: schema.TypeList, + Required: true, + Description: `The network with which to peer.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_url": { + Type: schema.TypeString, + Required: true, + Description: `The fully qualified URL of the VPC network to forward queries to. +This should be formatted like +'https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{network}'`, + }, + }, + }, + }, + }, + }, + }, "private_visibility_config": { Type: schema.TypeList, Optional: true, @@ -222,6 +279,26 @@ This should be formatted like } } +func dnsManagedZoneForwardingConfigTargetNameServersSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ipv4_address": { + Type: schema.TypeString, + Required: true, + Description: `IPv4 address of a target name server.`, + }, + "forwarding_path": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"default", "private", ""}, false), + Description: `Forwarding path for this TargetNameServer. If unset or 'default' Cloud DNS will make forwarding +decision based on address ranges, i.e. RFC1918 addresses go to the VPC, Non-RFC1918 addresses go +to the Internet. When set to 'private', Cloud DNS will always send queries through VPC for this target Possible values: ["default", "private"]`, + }, + }, + } +} + func resourceDNSManagedZoneCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -268,6 +345,18 @@ func resourceDNSManagedZoneCreate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("private_visibility_config"); !isEmptyValue(reflect.ValueOf(privateVisibilityConfigProp)) && (ok || !reflect.DeepEqual(v, privateVisibilityConfigProp)) { obj["privateVisibilityConfig"] = privateVisibilityConfigProp } + forwardingConfigProp, err := expandDNSManagedZoneForwardingConfig(d.Get("forwarding_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("forwarding_config"); !isEmptyValue(reflect.ValueOf(forwardingConfigProp)) && (ok || !reflect.DeepEqual(v, forwardingConfigProp)) { + obj["forwardingConfig"] = forwardingConfigProp + } + peeringConfigProp, err := expandDNSManagedZonePeeringConfig(d.Get("peering_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peering_config"); !isEmptyValue(reflect.ValueOf(peeringConfigProp)) && (ok || !reflect.DeepEqual(v, peeringConfigProp)) { + obj["peeringConfig"] = peeringConfigProp + } url, err := replaceVars(d, config, "{{DNSBasePath}}projects/{{project}}/managedZones") if err != nil { @@ -341,6 +430,12 @@ func resourceDNSManagedZoneRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("private_visibility_config", flattenDNSManagedZonePrivateVisibilityConfig(res["privateVisibilityConfig"], d, config)); err != nil { return fmt.Errorf("Error reading ManagedZone: %s", err) } + if err := d.Set("forwarding_config", flattenDNSManagedZoneForwardingConfig(res["forwardingConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading ManagedZone: %s", err) + } + if err := d.Set("peering_config", flattenDNSManagedZonePeeringConfig(res["peeringConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading ManagedZone: %s", err) + } return nil } @@ -378,6 +473,18 @@ func resourceDNSManagedZoneUpdate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("private_visibility_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, privateVisibilityConfigProp)) { obj["privateVisibilityConfig"] = privateVisibilityConfigProp } + forwardingConfigProp, err := expandDNSManagedZoneForwardingConfig(d.Get("forwarding_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("forwarding_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, forwardingConfigProp)) { + obj["forwardingConfig"] = forwardingConfigProp + } + peeringConfigProp, err := expandDNSManagedZonePeeringConfig(d.Get("peering_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peering_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, peeringConfigProp)) { + obj["peeringConfig"] = peeringConfigProp + } url, err := replaceVars(d, config, "{{DNSBasePath}}projects/{{project}}/managedZones/{{name}}") if err != nil { @@ -594,6 +701,84 @@ func flattenDNSManagedZonePrivateVisibilityConfigNetworksNetworkUrl(v interface{ return v } +func flattenDNSManagedZoneForwardingConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["target_name_servers"] = + flattenDNSManagedZoneForwardingConfigTargetNameServers(original["targetNameServers"], d, config) + return []interface{}{transformed} +} +func flattenDNSManagedZoneForwardingConfigTargetNameServers(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := schema.NewSet(func(v interface{}) int { + raw := v.(map[string]interface{}) + if address, ok := raw["ipv4_address"]; ok { + hashcode.String(address.(string)) + } + var buf bytes.Buffer + schema.SerializeResourceForHash(&buf, raw, dnsManagedZoneForwardingConfigTargetNameServersSchema()) + return hashcode.String(buf.String()) + }, []interface{}{}) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed.Add(map[string]interface{}{ + "ipv4_address": flattenDNSManagedZoneForwardingConfigTargetNameServersIpv4Address(original["ipv4Address"], d, config), + "forwarding_path": flattenDNSManagedZoneForwardingConfigTargetNameServersForwardingPath(original["forwardingPath"], d, config), + }) + } + return transformed +} +func flattenDNSManagedZoneForwardingConfigTargetNameServersIpv4Address(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDNSManagedZoneForwardingConfigTargetNameServersForwardingPath(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDNSManagedZonePeeringConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["target_network"] = + flattenDNSManagedZonePeeringConfigTargetNetwork(original["targetNetwork"], d, config) + return []interface{}{transformed} +} +func flattenDNSManagedZonePeeringConfigTargetNetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["network_url"] = + flattenDNSManagedZonePeeringConfigTargetNetworkNetworkUrl(original["networkUrl"], d, config) + return []interface{}{transformed} +} +func flattenDNSManagedZonePeeringConfigTargetNetworkNetworkUrl(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + func expandDNSManagedZoneDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -777,3 +962,102 @@ func expandDNSManagedZonePrivateVisibilityConfigNetworks(v interface{}, d Terraf func expandDNSManagedZonePrivateVisibilityConfigNetworksNetworkUrl(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } + +func expandDNSManagedZoneForwardingConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTargetNameServers, err := expandDNSManagedZoneForwardingConfigTargetNameServers(original["target_name_servers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTargetNameServers); val.IsValid() && !isEmptyValue(val) { + transformed["targetNameServers"] = transformedTargetNameServers + } + + return transformed, nil +} + +func expandDNSManagedZoneForwardingConfigTargetNameServers(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedIpv4Address, err := expandDNSManagedZoneForwardingConfigTargetNameServersIpv4Address(original["ipv4_address"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIpv4Address); val.IsValid() && !isEmptyValue(val) { + transformed["ipv4Address"] = transformedIpv4Address + } + + transformedForwardingPath, err := expandDNSManagedZoneForwardingConfigTargetNameServersForwardingPath(original["forwarding_path"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedForwardingPath); val.IsValid() && !isEmptyValue(val) { + transformed["forwardingPath"] = transformedForwardingPath + } + + req = append(req, transformed) + } + return req, nil +} + +func expandDNSManagedZoneForwardingConfigTargetNameServersIpv4Address(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDNSManagedZoneForwardingConfigTargetNameServersForwardingPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDNSManagedZonePeeringConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTargetNetwork, err := expandDNSManagedZonePeeringConfigTargetNetwork(original["target_network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTargetNetwork); val.IsValid() && !isEmptyValue(val) { + transformed["targetNetwork"] = transformedTargetNetwork + } + + return transformed, nil +} + +func expandDNSManagedZonePeeringConfigTargetNetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNetworkUrl, err := expandDNSManagedZonePeeringConfigTargetNetworkNetworkUrl(original["network_url"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkUrl); val.IsValid() && !isEmptyValue(val) { + transformed["networkUrl"] = transformedNetworkUrl + } + + return transformed, nil +} + +func expandDNSManagedZonePeeringConfigTargetNetworkNetworkUrl(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} diff --git a/google/resource_dns_managed_zone_generated_test.go b/google/resource_dns_managed_zone_generated_test.go index 7706d50ae4b..5f57243e29b 100644 --- a/google/resource_dns_managed_zone_generated_test.go +++ b/google/resource_dns_managed_zone_generated_test.go @@ -123,6 +123,64 @@ resource "google_compute_network" "network-2" { `, context) } +func TestAccDNSManagedZone_dnsManagedZonePrivatePeeringExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDNSManagedZoneDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDNSManagedZone_dnsManagedZonePrivatePeeringExample(context), + }, + { + ResourceName: "google_dns_managed_zone.peering-zone", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccDNSManagedZone_dnsManagedZonePrivatePeeringExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_dns_managed_zone" "peering-zone" { + name = "tf-test-peering-zone%{random_suffix}" + dns_name = "peering.example.com." + description = "Example private DNS peering zone" + + visibility = "private" + + private_visibility_config { + networks { + network_url = google_compute_network.network-source.self_link + } + } + + peering_config { + target_network { + network_url = google_compute_network.network-target.self_link + } + } +} + +resource "google_compute_network" "network-source" { + name = "tf-test-network-source%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_network" "network-target" { + name = "tf-test-network-target%{random_suffix}" + auto_create_subnetworks = false +} +`, context) +} + func testAccCheckDNSManagedZoneDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/google/resource_dns_managed_zone_test.go b/google/resource_dns_managed_zone_test.go index e10974c7ba0..0ef0584a4b0 100644 --- a/google/resource_dns_managed_zone_test.go +++ b/google/resource_dns_managed_zone_test.go @@ -119,6 +119,36 @@ func TestAccDNSManagedZone_dnssec_empty(t *testing.T) { }) } +func TestAccDNSManagedZone_privateForwardingUpdate(t *testing.T) { + t.Parallel() + + zoneSuffix := randString(t, 10) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDNSManagedZoneDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDnsManagedZone_privateForwardingUpdate(zoneSuffix, "172.16.1.10", "172.16.1.20", "default", "private"), + }, + { + ResourceName: "google_dns_managed_zone.private", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDnsManagedZone_privateForwardingUpdate(zoneSuffix, "172.16.1.10", "192.168.1.1", "private", "default"), + }, + { + ResourceName: "google_dns_managed_zone.private", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccDnsManagedZone_basic(suffix, description string) string { return fmt.Sprintf(` resource "google_dns_managed_zone" "foobar" { @@ -231,6 +261,38 @@ resource "google_compute_network" "network-3" { `, suffix, first_network, second_network, suffix, suffix, suffix) } +func testAccDnsManagedZone_privateForwardingUpdate(suffix, first_nameserver, second_nameserver, first_forwarding_path, second_forwarding_path string) string { + return fmt.Sprintf(` +resource "google_dns_managed_zone" "private" { + name = "private-zone-%s" + dns_name = "private.example.com." + description = "Example private DNS zone" + visibility = "private" + private_visibility_config { + networks { + network_url = google_compute_network.network-1.self_link + } + } + + forwarding_config { + target_name_servers { + ipv4_address = "%s" + forwarding_path = "%s" + } + target_name_servers { + ipv4_address = "%s" + forwarding_path = "%s" + } + } +} + +resource "google_compute_network" "network-1" { + name = "network-1-%s" + auto_create_subnetworks = false +} +`, suffix, first_nameserver, first_forwarding_path, second_nameserver, second_forwarding_path, suffix) +} + func TestDnsManagedZoneImport_parseImportId(t *testing.T) { zoneRegexes := []string{ "projects/(?P[^/]+)/managedZones/(?P[^/]+)", diff --git a/google/resource_dns_policy.go b/google/resource_dns_policy.go new file mode 100644 index 00000000000..5b9503e4db3 --- /dev/null +++ b/google/resource_dns_policy.go @@ -0,0 +1,564 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "bytes" + "fmt" + "log" + "reflect" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func resourceDNSPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceDNSPolicyCreate, + Read: resourceDNSPolicyRead, + Update: resourceDNSPolicyUpdate, + Delete: resourceDNSPolicyDelete, + + Importer: &schema.ResourceImporter{ + State: resourceDNSPolicyImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(4 * time.Minute), + Update: schema.DefaultTimeout(4 * time.Minute), + Delete: schema.DefaultTimeout(4 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `User assigned name for this policy.`, + }, + "alternative_name_server_config": { + Type: schema.TypeList, + Optional: true, + Description: `Sets an alternative name server for the associated networks. +When specified, all DNS queries are forwarded to a name server that you choose. +Names such as .internal are not available when an alternative name server is specified.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target_name_servers": { + Type: schema.TypeSet, + Required: true, + Description: `Sets an alternative name server for the associated networks. When specified, +all DNS queries are forwarded to a name server that you choose. Names such as .internal +are not available when an alternative name server is specified.`, + Elem: dnsPolicyAlternativeNameServerConfigTargetNameServersSchema(), + Set: func(v interface{}) int { + raw := v.(map[string]interface{}) + if address, ok := raw["ipv4_address"]; ok { + hashcode.String(address.(string)) + } + var buf bytes.Buffer + schema.SerializeResourceForHash(&buf, raw, dnsPolicyAlternativeNameServerConfigTargetNameServersSchema()) + return hashcode.String(buf.String()) + }, + }, + }, + }, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `A textual description field. Defaults to 'Managed by Terraform'.`, + Default: "Managed by Terraform", + }, + "enable_inbound_forwarding": { + Type: schema.TypeBool, + Optional: true, + Description: `Allows networks bound to this policy to receive DNS queries sent +by VMs or applications over VPN connections. When enabled, a +virtual IP address will be allocated from each of the sub-networks +that are bound to this policy.`, + }, + "enable_logging": { + Type: schema.TypeBool, + Optional: true, + Description: `Controls whether logging is enabled for the networks bound to this policy. +Defaults to no logging if not set.`, + }, + "networks": { + Type: schema.TypeSet, + Optional: true, + Description: `List of network names specifying networks to which this policy is applied.`, + Elem: dnsPolicyNetworksSchema(), + Set: func(v interface{}) int { + raw := v.(map[string]interface{}) + if url, ok := raw["network_url"]; ok { + return selfLinkNameHash(url) + } + var buf bytes.Buffer + schema.SerializeResourceForHash(&buf, raw, dnsPolicyNetworksSchema()) + return hashcode.String(buf.String()) + }, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + } +} + +func dnsPolicyAlternativeNameServerConfigTargetNameServersSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ipv4_address": { + Type: schema.TypeString, + Required: true, + Description: `IPv4 address to forward to.`, + }, + }, + } +} + +func dnsPolicyNetworksSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_url": { + Type: schema.TypeString, + Required: true, + Description: `The fully qualified URL of the VPC network to bind to. +This should be formatted like +'https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{network}'`, + }, + }, + } +} + +func resourceDNSPolicyCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + obj := make(map[string]interface{}) + alternativeNameServerConfigProp, err := expandDNSPolicyAlternativeNameServerConfig(d.Get("alternative_name_server_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("alternative_name_server_config"); !isEmptyValue(reflect.ValueOf(alternativeNameServerConfigProp)) && (ok || !reflect.DeepEqual(v, alternativeNameServerConfigProp)) { + obj["alternativeNameServerConfig"] = alternativeNameServerConfigProp + } + descriptionProp, err := expandDNSPolicyDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + enableInboundForwardingProp, err := expandDNSPolicyEnableInboundForwarding(d.Get("enable_inbound_forwarding"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_inbound_forwarding"); ok || !reflect.DeepEqual(v, enableInboundForwardingProp) { + obj["enableInboundForwarding"] = enableInboundForwardingProp + } + enableLoggingProp, err := expandDNSPolicyEnableLogging(d.Get("enable_logging"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_logging"); ok || !reflect.DeepEqual(v, enableLoggingProp) { + obj["enableLogging"] = enableLoggingProp + } + nameProp, err := expandDNSPolicyName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + networksProp, err := expandDNSPolicyNetworks(d.Get("networks"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("networks"); !isEmptyValue(reflect.ValueOf(networksProp)) && (ok || !reflect.DeepEqual(v, networksProp)) { + obj["networks"] = networksProp + } + + url, err := replaceVars(d, config, "{{DNSBasePath}}projects/{{project}}/policies") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new Policy: %#v", obj) + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating Policy: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "projects/{{project}}/policies/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating Policy %q: %#v", d.Id(), res) + + return resourceDNSPolicyRead(d, meta) +} + +func resourceDNSPolicyRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + url, err := replaceVars(d, config, "{{DNSBasePath}}projects/{{project}}/policies/{{name}}") + if err != nil { + return err + } + + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequest(config, "GET", project, url, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("DNSPolicy %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading Policy: %s", err) + } + + if err := d.Set("alternative_name_server_config", flattenDNSPolicyAlternativeNameServerConfig(res["alternativeNameServerConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading Policy: %s", err) + } + if err := d.Set("description", flattenDNSPolicyDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading Policy: %s", err) + } + if err := d.Set("enable_inbound_forwarding", flattenDNSPolicyEnableInboundForwarding(res["enableInboundForwarding"], d, config)); err != nil { + return fmt.Errorf("Error reading Policy: %s", err) + } + if err := d.Set("enable_logging", flattenDNSPolicyEnableLogging(res["enableLogging"], d, config)); err != nil { + return fmt.Errorf("Error reading Policy: %s", err) + } + if err := d.Set("name", flattenDNSPolicyName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading Policy: %s", err) + } + if err := d.Set("networks", flattenDNSPolicyNetworks(res["networks"], d, config)); err != nil { + return fmt.Errorf("Error reading Policy: %s", err) + } + + return nil +} + +func resourceDNSPolicyUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + d.Partial(true) + + if d.HasChange("alternative_name_server_config") || d.HasChange("description") || d.HasChange("enable_inbound_forwarding") || d.HasChange("enable_logging") || d.HasChange("networks") { + obj := make(map[string]interface{}) + + alternativeNameServerConfigProp, err := expandDNSPolicyAlternativeNameServerConfig(d.Get("alternative_name_server_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("alternative_name_server_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, alternativeNameServerConfigProp)) { + obj["alternativeNameServerConfig"] = alternativeNameServerConfigProp + } + descriptionProp, err := expandDNSPolicyDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + enableInboundForwardingProp, err := expandDNSPolicyEnableInboundForwarding(d.Get("enable_inbound_forwarding"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_inbound_forwarding"); ok || !reflect.DeepEqual(v, enableInboundForwardingProp) { + obj["enableInboundForwarding"] = enableInboundForwardingProp + } + enableLoggingProp, err := expandDNSPolicyEnableLogging(d.Get("enable_logging"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_logging"); ok || !reflect.DeepEqual(v, enableLoggingProp) { + obj["enableLogging"] = enableLoggingProp + } + networksProp, err := expandDNSPolicyNetworks(d.Get("networks"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("networks"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, networksProp)) { + obj["networks"] = networksProp + } + + url, err := replaceVars(d, config, "{{DNSBasePath}}projects/{{project}}/policies/{{name}}") + if err != nil { + return err + } + _, err = sendRequestWithTimeout(config, "PATCH", project, url, obj, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error updating Policy %q: %s", d.Id(), err) + } + + d.SetPartial("alternative_name_server_config") + d.SetPartial("description") + d.SetPartial("enable_inbound_forwarding") + d.SetPartial("enable_logging") + d.SetPartial("networks") + } + + d.Partial(false) + + return resourceDNSPolicyRead(d, meta) +} + +func resourceDNSPolicyDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{DNSBasePath}}projects/{{project}}/policies/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + // if networks are attached, they need to be detached before the policy can be deleted + if d.Get("networks.#").(int) > 0 { + patched := make(map[string]interface{}) + patched["networks"] = nil + + url, err := replaceVars(d, config, "{{DNSBasePath}}projects/{{project}}/policies/{{name}}") + if err != nil { + return err + } + + _, err = sendRequestWithTimeout(config, "PATCH", project, url, patched, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error updating Policy %q: %s", d.Id(), err) + } + } + log.Printf("[DEBUG] Deleting Policy %q", d.Id()) + + res, err := sendRequestWithTimeout(config, "DELETE", project, url, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "Policy") + } + + log.Printf("[DEBUG] Finished deleting Policy %q: %#v", d.Id(), res) + return nil +} + +func resourceDNSPolicyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/policies/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "projects/{{project}}/policies/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenDNSPolicyAlternativeNameServerConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["target_name_servers"] = + flattenDNSPolicyAlternativeNameServerConfigTargetNameServers(original["targetNameServers"], d, config) + return []interface{}{transformed} +} +func flattenDNSPolicyAlternativeNameServerConfigTargetNameServers(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := schema.NewSet(func(v interface{}) int { + raw := v.(map[string]interface{}) + if address, ok := raw["ipv4_address"]; ok { + hashcode.String(address.(string)) + } + var buf bytes.Buffer + schema.SerializeResourceForHash(&buf, raw, dnsPolicyAlternativeNameServerConfigTargetNameServersSchema()) + return hashcode.String(buf.String()) + }, []interface{}{}) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed.Add(map[string]interface{}{ + "ipv4_address": flattenDNSPolicyAlternativeNameServerConfigTargetNameServersIpv4Address(original["ipv4Address"], d, config), + }) + } + return transformed +} +func flattenDNSPolicyAlternativeNameServerConfigTargetNameServersIpv4Address(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDNSPolicyDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDNSPolicyEnableInboundForwarding(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDNSPolicyEnableLogging(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDNSPolicyName(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenDNSPolicyNetworks(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := schema.NewSet(func(v interface{}) int { + raw := v.(map[string]interface{}) + if url, ok := raw["network_url"]; ok { + return selfLinkNameHash(url) + } + var buf bytes.Buffer + schema.SerializeResourceForHash(&buf, raw, dnsPolicyNetworksSchema()) + return hashcode.String(buf.String()) + }, []interface{}{}) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed.Add(map[string]interface{}{ + "network_url": flattenDNSPolicyNetworksNetworkUrl(original["networkUrl"], d, config), + }) + } + return transformed +} +func flattenDNSPolicyNetworksNetworkUrl(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func expandDNSPolicyAlternativeNameServerConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedTargetNameServers, err := expandDNSPolicyAlternativeNameServerConfigTargetNameServers(original["target_name_servers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTargetNameServers); val.IsValid() && !isEmptyValue(val) { + transformed["targetNameServers"] = transformedTargetNameServers + } + + return transformed, nil +} + +func expandDNSPolicyAlternativeNameServerConfigTargetNameServers(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedIpv4Address, err := expandDNSPolicyAlternativeNameServerConfigTargetNameServersIpv4Address(original["ipv4_address"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIpv4Address); val.IsValid() && !isEmptyValue(val) { + transformed["ipv4Address"] = transformedIpv4Address + } + + req = append(req, transformed) + } + return req, nil +} + +func expandDNSPolicyAlternativeNameServerConfigTargetNameServersIpv4Address(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDNSPolicyDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDNSPolicyEnableInboundForwarding(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDNSPolicyEnableLogging(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDNSPolicyName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandDNSPolicyNetworks(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNetworkUrl, err := expandDNSPolicyNetworksNetworkUrl(original["network_url"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkUrl); val.IsValid() && !isEmptyValue(val) { + transformed["networkUrl"] = transformedNetworkUrl + } + + req = append(req, transformed) + } + return req, nil +} + +func expandDNSPolicyNetworksNetworkUrl(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} diff --git a/google/resource_dns_policy_generated_test.go b/google/resource_dns_policy_generated_test.go new file mode 100644 index 00000000000..8073047e504 --- /dev/null +++ b/google/resource_dns_policy_generated_test.go @@ -0,0 +1,112 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccDNSPolicy_dnsPolicyBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDNSPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDNSPolicy_dnsPolicyBasicExample(context), + }, + { + ResourceName: "google_dns_policy.example-policy", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccDNSPolicy_dnsPolicyBasicExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_dns_policy" "example-policy" { + name = "tf-test-example-policy%{random_suffix}" + enable_inbound_forwarding = true + + enable_logging = true + + alternative_name_server_config { + target_name_servers { + ipv4_address = "172.16.1.10" + } + target_name_servers { + ipv4_address = "172.16.1.20" + } + } + + networks { + network_url = google_compute_network.network-1.self_link + } + networks { + network_url = google_compute_network.network-2.self_link + } +} + +resource "google_compute_network" "network-1" { + name = "tf-test-network-1%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_network" "network-2" { + name = "tf-test-network-2%{random_suffix}" + auto_create_subnetworks = false +} +`, context) +} + +func testAccCheckDNSPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_dns_policy" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + url, err := replaceVarsForTest(config, rs, "{{DNSBasePath}}projects/{{project}}/policies/{{name}}") + if err != nil { + return err + } + + _, err = sendRequest(config, "GET", "", url, nil) + if err == nil { + return fmt.Errorf("DNSPolicy still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/resource_dns_policy_test.go b/google/resource_dns_policy_test.go index 71664db3c87..ac50a1f67aa 100644 --- a/google/resource_dns_policy_test.go +++ b/google/resource_dns_policy_test.go @@ -1 +1,67 @@ package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccDNSPolicy_update(t *testing.T) { + t.Parallel() + + policySuffix := randString(t, 10) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDNSPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDnsPolicy_privateUpdate(policySuffix, "true", "172.16.1.10", "network-1"), + }, + { + ResourceName: "google_dns_policy.example-policy", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccDnsPolicy_privateUpdate(policySuffix, "false", "172.16.1.20", "network-2"), + }, + { + ResourceName: "google_dns_policy.example-policy", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccDnsPolicy_privateUpdate(suffix, forwarding, nameserver, network string) string { + return fmt.Sprintf(` +resource "google_dns_policy" "example-policy" { + name = "example-policy-%s" + enable_inbound_forwarding = %s + + alternative_name_server_config { + target_name_servers { + ipv4_address = "%s" + } + } + + networks { + network_url = google_compute_network.%s.self_link + } +} + +resource "google_compute_network" "network-1" { + name = "network-1-%s" + auto_create_subnetworks = false +} + +resource "google_compute_network" "network-2" { + name = "network-2-%s" + auto_create_subnetworks = false +} +`, suffix, forwarding, nameserver, network, suffix, suffix) +} diff --git a/website/docs/r/dns_managed_zone.html.markdown b/website/docs/r/dns_managed_zone.html.markdown index 0cf3f91d110..8433a7e530b 100644 --- a/website/docs/r/dns_managed_zone.html.markdown +++ b/website/docs/r/dns_managed_zone.html.markdown @@ -100,7 +100,6 @@ resource "google_compute_network" "network-2" { ```hcl resource "google_dns_managed_zone" "private-zone" { - provider = google-beta name = "private-zone" dns_name = "private.example.com." description = "Example private DNS zone" @@ -149,8 +148,6 @@ resource "google_compute_network" "network-2" { ```hcl resource "google_dns_managed_zone" "peering-zone" { - provider = google-beta - name = "peering-zone" dns_name = "peering.example.com." description = "Example private DNS peering zone" @@ -171,23 +168,14 @@ resource "google_dns_managed_zone" "peering-zone" { } resource "google_compute_network" "network-source" { - provider = google-beta - name = "network-source" auto_create_subnetworks = false } resource "google_compute_network" "network-target" { - provider = google-beta - name = "network-target" auto_create_subnetworks = false } - -provider "google-beta" { - region = "us-central1" - zone = "us-central1-a" -} ```
@@ -274,6 +262,17 @@ The following arguments are supported: For privately visible zones, the set of Virtual Private Cloud resources that the zone is visible from. Structure is documented below. +* `forwarding_config` - + (Optional) + The presence for this field indicates that outbound forwarding is enabled + for this zone. The value of this field contains the set of destinations + to forward to. Structure is documented below. + +* `peering_config` - + (Optional) + The presence of this field indicates that DNS Peering is enabled for this + zone. The value of this field contains the network to peer with. Structure is documented below. + * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. @@ -363,6 +362,46 @@ The `networks` block supports: This should be formatted like `https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{network}` +The `forwarding_config` block supports: + +* `target_name_servers` - + (Required) + List of target name servers to forward to. Cloud DNS will + select the best available name server if more than + one target is given. Structure is documented below. + + +The `target_name_servers` block supports: + +* `ipv4_address` - + (Required) + IPv4 address of a target name server. + +* `forwarding_path` - + (Optional) + Forwarding path for this TargetNameServer. If unset or `default` Cloud DNS will make forwarding + decision based on address ranges, i.e. RFC1918 addresses go to the VPC, Non-RFC1918 addresses go + to the Internet. When set to `private`, Cloud DNS will always send queries through VPC for this target + + Possible values are: + * `default` + * `private` + +The `peering_config` block supports: + +* `target_network` - + (Required) + The network with which to peer. Structure is documented below. + + +The `target_network` block supports: + +* `network_url` - + (Required) + The fully qualified URL of the VPC network to forward queries to. + This should be formatted like + `https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{network}` + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: diff --git a/website/docs/r/dns_policy.html.markdown b/website/docs/r/dns_policy.html.markdown new file mode 100644 index 00000000000..02c97f62437 --- /dev/null +++ b/website/docs/r/dns_policy.html.markdown @@ -0,0 +1,176 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +subcategory: "Cloud DNS" +layout: "google" +page_title: "Google: google_dns_policy" +sidebar_current: "docs-google-dns-policy" +description: |- + A policy is a collection of DNS rules applied to one or more Virtual + Private Cloud resources. +--- + +# google\_dns\_policy + +A policy is a collection of DNS rules applied to one or more Virtual +Private Cloud resources. + + +To get more information about Policy, see: + +* [API documentation](https://cloud.google.com/dns/docs/reference/v1beta2/policies) +* How-to Guides + * [Using DNS server policies](https://cloud.google.com/dns/zones/#using-dns-server-policies) + + +## Example Usage - Dns Policy Basic + + +```hcl +resource "google_dns_policy" "example-policy" { + name = "example-policy" + enable_inbound_forwarding = true + + enable_logging = true + + alternative_name_server_config { + target_name_servers { + ipv4_address = "172.16.1.10" + } + target_name_servers { + ipv4_address = "172.16.1.20" + } + } + + networks { + network_url = google_compute_network.network-1.self_link + } + networks { + network_url = google_compute_network.network-2.self_link + } +} + +resource "google_compute_network" "network-1" { + name = "network-1" + auto_create_subnetworks = false +} + +resource "google_compute_network" "network-2" { + name = "network-2" + auto_create_subnetworks = false +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `name` - + (Required) + User assigned name for this policy. + + +- - - + + +* `alternative_name_server_config` - + (Optional) + Sets an alternative name server for the associated networks. + When specified, all DNS queries are forwarded to a name server that you choose. + Names such as .internal are not available when an alternative name server is specified. Structure is documented below. + +* `description` - + (Optional) + A textual description field. Defaults to 'Managed by Terraform'. + +* `enable_inbound_forwarding` - + (Optional) + Allows networks bound to this policy to receive DNS queries sent + by VMs or applications over VPN connections. When enabled, a + virtual IP address will be allocated from each of the sub-networks + that are bound to this policy. + +* `enable_logging` - + (Optional) + Controls whether logging is enabled for the networks bound to this policy. + Defaults to no logging if not set. + +* `networks` - + (Optional) + List of network names specifying networks to which this policy is applied. Structure is documented below. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `alternative_name_server_config` block supports: + +* `target_name_servers` - + (Required) + Sets an alternative name server for the associated networks. When specified, + all DNS queries are forwarded to a name server that you choose. Names such as .internal + are not available when an alternative name server is specified. Structure is documented below. + + +The `target_name_servers` block supports: + +* `ipv4_address` - + (Required) + IPv4 address to forward to. + +The `networks` block supports: + +* `network_url` - + (Required) + The fully qualified URL of the VPC network to bind to. + This should be formatted like + `https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{network}` + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/policies/{{name}}` + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. + +## Import + +Policy can be imported using any of these accepted formats: + +``` +$ terraform import google_dns_policy.default projects/{{project}}/policies/{{name}} +$ terraform import google_dns_policy.default {{project}}/{{name}} +$ terraform import google_dns_policy.default {{name}} +``` + +-> If you're importing a resource with beta features, make sure to include `-provider=google-beta` +as an argument so that Terraform uses the correct provider to import your resource. + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#user_project_override). diff --git a/website/google.erb b/website/google.erb index 9be5c7d9272..fd7c6fff8a7 100644 --- a/website/google.erb +++ b/website/google.erb @@ -407,6 +407,10 @@ google_dns_managed_zone +
  • + google_dns_policy +
  • +
  • google_dns_record_set