Skip to content

Commit

Permalink
Merge pull request #1169 in CLOUD/terraform-provider-yandex-mirror fr…
Browse files Browse the repository at this point in the history
…om CLOUD-63662/dns_records_in_vpc_address to master

Squashed commit of the following:

commit ceb47157c4ec17c05e1b9a4fe767fe268bf723e8
Author: Vladimir Danilov <vdaniloff@yandex-team.ru>
Date:   Mon Mar 25 14:22:16 2024 +0300

    [CLOUD-63662] dns record specs in vpc address

commit 25f28d027e4842dcb2e59fec654ff4122b35e7a3
Author: Vladimir Danilov <vdaniloff@yandex-team.ru>
Date:   Mon Mar 18 14:16:53 2024 +0300

    [CLOUD-63662] dns record specs in vpc address
  • Loading branch information
Vladimir Danilov committed Mar 25, 2024
1 parent 16e7abe commit a441b4e
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ENHANCEMENTS:
* compute: change `secondary_disk` attribute type from List to Set in `instance` resource.
* greenplum: fixed `pxf_config` fetching in yandex_mdb_greenplum_cluster datasource.
* vpc: allow to change cidrs in subnet (v4_cidr_blocks)
* vpc: add `dns_record` attribute in `yandex_vpc_address` resource and data source

## 0.112.0 (March 12, 2024)
BUG FIXES:
Expand Down
12 changes: 12 additions & 0 deletions website/docs/r/vpc_address.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ The `external_ipv4_address` block supports:
~> **NOTE:** Either one `ddos_protection_provider` or `outgoing_smtp_capability` arguments can be specified.
~> **NOTE:** Change any argument in `external_ipv4_address` will cause an address recreate

---

* `dns_record` - (Optional) DNS record specification of address
---

The `dns_record` block supports:

* `fqdn` - (Required) FQDN for record to address
* `dns_zone_id` - (Optional) DNS zone id to create record at. When not set, private zone used.
* `ttl` - (Optional) TTL of DNS record
* `ptr` - (Optional) If PTR record is needed

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are exported:
Expand Down
24 changes: 24 additions & 0 deletions yandex/data_source_yandex_vpc_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,30 @@ func dataSourceYandexVPCAddress() *schema.Resource {
Type: schema.TypeBool,
Computed: true,
},
"dns_record": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"dns_zone_id": {
Type: schema.TypeString,
Computed: true,
},
"fqdn": {
Type: schema.TypeString,
Computed: true,
},
"ttl": {
Type: schema.TypeInt,
Computed: true,
},
"ptr": {
Type: schema.TypeBool,
Computed: true,
},
},
},
},
},
}
}
Expand Down
82 changes: 72 additions & 10 deletions yandex/resource_yandex_vpc_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package yandex
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand All @@ -22,10 +23,10 @@ func handleAddressNotFoundError(err error, d *schema.ResourceData, id string) er

func resourceYandexVPCAddress() *schema.Resource {
return &schema.Resource{
Read: resourceYandexVPCAddressRead,
Create: resourceYandexVPCAddressCreate,
Update: resourceYandexVPCAddressUpdate,
Delete: resourceYandexVPCAddressDelete,
Read: resourceYandexVPCAddressRead,
Create: resourceYandexVPCAddressCreate,
UpdateContext: resourceYandexVPCAddressUpdateContext,
Delete: resourceYandexVPCAddressDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
Expand Down Expand Up @@ -111,6 +112,30 @@ func resourceYandexVPCAddress() *schema.Resource {
Optional: true,
Computed: true,
},
"dns_record": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"dns_zone_id": {
Type: schema.TypeString,
Computed: true,
},
"fqdn": {
Type: schema.TypeString,
Computed: true,
},
"ttl": {
Type: schema.TypeInt,
Computed: true,
},
"ptr": {
Type: schema.TypeBool,
Computed: true,
},
},
},
},
},
}
}
Expand Down Expand Up @@ -155,6 +180,12 @@ func yandexVPCAddressRead(d *schema.ResourceData, meta interface{}, id string) e
if err := d.Set("reserved", address.GetReserved()); err != nil {
return err
}

dnsRecords := flattenVpcAddressDnsRecords(address.DnsRecords)
if err := d.Set("dns_record", dnsRecords); err != nil {
return err
}

return d.Set("used", address.GetUsed())
}

Expand All @@ -180,6 +211,11 @@ func resourceYandexVPCAddressCreate(d *schema.ResourceData, meta interface{}) er
return addressError("expanding external ipv4 address while creating address: %s", err)
}

dnsSpecs, err := expandVpcAddressDnsRecords(d)
if err != nil {
return addressError("expanding dns record specs while creating address %s", err)
}

req := vpc.CreateAddressRequest{
FolderId: folderID,
Name: d.Get("name").(string),
Expand All @@ -190,6 +226,7 @@ func resourceYandexVPCAddressCreate(d *schema.ResourceData, meta interface{}) er
ExternalIpv4AddressSpec: spec,
},
DeletionProtection: d.Get("deletion_protection").(bool),
DnsRecordSpecs: dnsSpecs,
}

ctx, cancel := context.WithTimeout(config.Context(), d.Timeout(schema.TimeoutCreate))
Expand Down Expand Up @@ -224,7 +261,7 @@ func resourceYandexVPCAddressCreate(d *schema.ResourceData, meta interface{}) er
return resourceYandexVPCAddressRead(d, meta)
}

func resourceYandexVPCAddressUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceYandexVPCAddressUpdateContext(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
config := meta.(*Config)

d.Partial(true)
Expand All @@ -238,7 +275,7 @@ func resourceYandexVPCAddressUpdate(d *schema.ResourceData, meta interface{}) er
if d.HasChange(addrLabelsPropName) {
labelsProp, err := expandLabels(d.Get(addrLabelsPropName))
if err != nil {
return err
return diag.FromErr(err)
}

req.Labels = labelsProp
Expand All @@ -263,22 +300,47 @@ func resourceYandexVPCAddressUpdate(d *schema.ResourceData, meta interface{}) er
req.UpdateMask.Paths = append(req.UpdateMask.Paths, addrDeletionProtectionPropName)
}

ctx, cancel := context.WithTimeout(config.Context(), d.Timeout(schema.TimeoutUpdate))
const addrDnsRecords = "dns_record"
if d.HasChange(addrDnsRecords) {
specs, err := expandVpcAddressDnsRecords(d)
if err != nil {
return diag.FromErr(err)
}
req.DnsRecordSpecs = specs
// differs in ycp and tf
req.UpdateMask.Paths = append(req.UpdateMask.Paths, "dns_record_specs")
}

var diags diag.Diagnostics
if d.HasChange("reserved") && !req.Reserved && len(req.DnsRecordSpecs) > 0 {
diags = append(diags, diag.Diagnostic{
Severity: diag.Warning,
Summary: "DNS records were copied to the network interface",
Detail: "You changed the type of address to ephemeral. This copies DNS records to the network interface. " +
"Don't forget to update it in Terraform specification!",
})
}

ctx, cancel := context.WithTimeout(ctx, d.Timeout(schema.TimeoutUpdate))
defer cancel()

op, err := config.sdk.WrapOperation(config.sdk.VPC().Address().Update(ctx, req))
if err != nil {
return addressError("while requesting API to update Address %q: %s", d.Id(), err)
return diag.FromErr(addressError("while requesting API to update Address %q: %s", d.Id(), err))
}

err = op.Wait(ctx)
if err != nil {
return addressError("updating Address %q: %s", d.Id(), err)
return diag.FromErr(addressError("updating Address %q: %s", d.Id(), err))
}

d.Partial(false)

return resourceYandexVPCAddressRead(d, meta)
err = resourceYandexVPCAddressRead(d, meta)
if err != nil {
return diag.FromErr(err)
}
return diags
}

func resourceYandexVPCAddressDelete(d *schema.ResourceData, meta interface{}) error {
Expand Down
15 changes: 15 additions & 0 deletions yandex/resource_yandex_vpc_address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ resource "yandex_vpc_address" "addr1" {
ddos_protection_provider = "qrator"
}
deletion_protection = true
dns_record {
fqdn = "some.fqdn."
}
}
`, name)
}
Expand All @@ -44,6 +48,11 @@ resource "yandex_vpc_address" "addr1" {
external_ipv4_address {
zone_id = "ru-central1-c"
}
dns_record {
fqdn = "other.fqdn."
ptr = true
}
}
`, name)
}
Expand Down Expand Up @@ -99,6 +108,9 @@ func TestAccVPCAddress_basic(t *testing.T) {
testAccCheckVPCAddressContainsLabel(&address, "tf-label", "tf-label-value"),
testAccCheckVPCAddressContainsLabel(&address, "empty-label", ""),
testAccCheckCreatedAtAttr("yandex_vpc_address.addr1"),
resource.TestCheckResourceAttr("yandex_vpc_address.addr1", "dns_record.#", "1"),
resource.TestCheckResourceAttr("yandex_vpc_address.addr1", "dns_record.0.fqdn", "some.fqdn"),
resource.TestCheckResourceAttr("yandex_vpc_address.addr1", "dns_record.0.ptr", "true"),
),
},
{
Expand All @@ -119,6 +131,8 @@ func TestAccVPCAddress_basic(t *testing.T) {
testAccCheckVPCAddressContainsLabelNotFound(&address, "empty-label"),
testAccCheckVPCAddressContainsLabel(&address, "new-label", "new"),
testAccCheckCreatedAtAttr("yandex_vpc_address.addr1"),
resource.TestCheckResourceAttr("yandex_vpc_address.addr1", "dns_record.#", "1"),
resource.TestCheckResourceAttr("yandex_vpc_address.addr1", "dns_record.0.fqdn", "other.fqdn"),
),
},
{
Expand All @@ -132,6 +146,7 @@ func TestAccVPCAddress_basic(t *testing.T) {
"yandex_vpc_address.addr1", "external_ipv4_address.0.ddos_protection_provider", "qrator",
),
resource.TestCheckResourceAttr("yandex_vpc_address.addr1", "deletion_protection", "false"),
resource.TestCheckResourceAttr("yandex_vpc_address.addr1", "dns_record.#", "0"),
),
},
{
Expand Down
45 changes: 45 additions & 0 deletions yandex/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,21 @@ func flattenSecurityGroupRulesSpec(sg []*vpc.SecurityGroupRule) (*schema.Set, *s
return ingress, egress
}

func flattenVpcAddressDnsRecords(specs []*vpc.DnsRecord) []map[string]interface{} {
res := make([]map[string]interface{}, len(specs))

for i, spec := range specs {
res[i] = map[string]interface{}{
"fqdn": spec.Fqdn,
"dns_zone_id": spec.DnsZoneId,
"ttl": int(spec.Ttl),
"ptr": spec.Ptr,
}
}

return res
}

func flattenExternalIpV4AddressSpec(address *vpc.ExternalIpv4Address) []interface{} {
if address == nil {
return nil
Expand Down Expand Up @@ -1743,6 +1758,36 @@ func expandAddressRequirements(addrDesc map[string]interface{}) (*vpc.AddressReq
return &requirements, set
}

func expandVpcAddressDnsRecords(d *schema.ResourceData) ([]*vpc.DnsRecordSpec, error) {
var (
v interface{}
ok bool
)

if v, ok = d.GetOk("dns_record"); !ok {
return nil, nil
}

specs := v.([]interface{})
recs := make([]*vpc.DnsRecordSpec, len(specs))

for i, raw := range specs {
d := raw.(map[string]interface{})
r := &vpc.DnsRecordSpec{Fqdn: d["fqdn"].(string)}
if s, ok := d["dns_zone_id"]; ok {
r.DnsZoneId = s.(string)
}
if s, ok := d["ttl"]; ok {
r.Ttl = int64(s.(int))
}
if s, ok := d["ptr"]; ok {
r.Ptr = s.(bool)
}
recs[i] = r
}
return recs, nil
}

func expandExternalIpv4Address(d *schema.ResourceData) (*vpc.ExternalIpv4AddressSpec, error) {
var (
v interface{}
Expand Down

0 comments on commit a441b4e

Please sign in to comment.