From 4dd6accb5cee05ff1f975dab7965a0dbe1caafd9 Mon Sep 17 00:00:00 2001 From: Alex Wilcox Date: Fri, 20 Dec 2024 01:27:16 +0000 Subject: [PATCH] Add update function --- internal/services/dns/dns_zone_resource.go | 101 ++++++++++++++++++--- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/internal/services/dns/dns_zone_resource.go b/internal/services/dns/dns_zone_resource.go index f85fd608c3e8..a24c1ae49639 100644 --- a/internal/services/dns/dns_zone_resource.go +++ b/internal/services/dns/dns_zone_resource.go @@ -23,7 +23,6 @@ import ( ) var ( - _ sdk.Resource = DnsZoneResource{} _ sdk.ResourceWithUpdate = DnsZoneResource{} _ sdk.ResourceWithStateMigration = DnsZoneResource{} ) @@ -194,26 +193,24 @@ func (r DnsZoneResource) Create() sdk.ResourceFunc { } id := zones.NewDnsZoneID(subscriptionId, model.ResourceGroupName, model.Name) - if metadata.ResourceData.IsNewResource() { - existing, err := client.Get(ctx, id) - if err != nil { - if !response.WasNotFound(existing.HttpResponse) { - return fmt.Errorf("checking for presence of existing %s: %+v", id, err) - } - } - + existing, err := client.Get(ctx, id) + if err != nil { if !response.WasNotFound(existing.HttpResponse) { - return metadata.ResourceRequiresImport(r.ResourceType(), id) + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) } } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + parameters := zones.Zone{ Location: location.Normalize("global"), Tags: pointer.To(model.Tags), } if _, err := client.CreateOrUpdate(ctx, id, parameters, zones.DefaultCreateOrUpdateOperationOptions()); err != nil { - return fmt.Errorf("creating/updating %s: %+v", id, err) + return fmt.Errorf("creating %s: %+v", id, err) } if len(model.SoaRecord) == 1 { @@ -246,7 +243,7 @@ func (r DnsZoneResource) Create() sdk.ResourceFunc { soaRecordId := recordsets.NewRecordTypeID(id.SubscriptionId, id.ResourceGroupName, id.DnsZoneName, recordsets.RecordTypeSOA, "@") if _, err := recordSetsClient.CreateOrUpdate(ctx, soaRecordId, rsParameters, recordsets.DefaultCreateOrUpdateOperationOptions()); err != nil { - return fmt.Errorf("creating/updating %s: %+v", soaRecordId, err) + return fmt.Errorf("creating %s: %+v", soaRecordId, err) } } @@ -305,7 +302,85 @@ func (DnsZoneResource) Read() sdk.ResourceFunc { } func (r DnsZoneResource) Update() sdk.ResourceFunc { - return r.Create() + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Dns.Zones + recordSetsClient := metadata.Client.Dns.RecordSets + + var model DnsZoneResourceModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + id, err := zones.ParseDnsZoneID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + existing, err := client.Get(ctx, *id) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + if existing.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", id) + } + + if existing.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", id) + } + + payload := zones.Zone{ + Location: existing.Model.Location, + Tags: existing.Model.Tags, + } + + if metadata.ResourceData.HasChange("tags") { + payload.Tags = pointer.To(model.Tags) + } + + if _, err := client.CreateOrUpdate(ctx, *id, payload, zones.DefaultCreateOrUpdateOperationOptions()); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + + if metadata.ResourceData.HasChange("soa_record") && len(model.SoaRecord) == 1 { + soaRecordID := recordsets.NewRecordTypeID(id.SubscriptionId, id.ResourceGroupName, id.DnsZoneName, recordsets.RecordTypeSOA, "@") + soaRecordResp, err := recordSetsClient.Get(ctx, soaRecordID) + if err != nil { + return fmt.Errorf("retrieving %s to update SOA: %+v", id, err) + } + + props := soaRecordResp.Model.Properties + if props == nil || props.SOARecord == nil { + return fmt.Errorf("could not read SOA properties for %s", id) + } + + inputSOARecord := expandDNSZoneSOARecord(model.SoaRecord[0]) + + inputSOARecord.Host = props.SOARecord.Host + + rsParameters := recordsets.RecordSet{ + Properties: &recordsets.RecordSetProperties{ + TTL: pointer.To(model.SoaRecord[0].Ttl), + Metadata: pointer.To(model.SoaRecord[0].Tags), + SOARecord: inputSOARecord, + }, + } + + if len(id.DnsZoneName+strings.TrimSuffix(*rsParameters.Properties.SOARecord.Email, ".")) > 253 { + return fmt.Errorf("`email` which is concatenated with DNS Zone `name` cannot exceed 253 characters excluding a trailing period") + } + + soaRecordId := recordsets.NewRecordTypeID(id.SubscriptionId, id.ResourceGroupName, id.DnsZoneName, recordsets.RecordTypeSOA, "@") + if _, err := recordSetsClient.CreateOrUpdate(ctx, soaRecordId, rsParameters, recordsets.DefaultCreateOrUpdateOperationOptions()); err != nil { + return fmt.Errorf("updating %s: %+v", soaRecordId, err) + } + } + + return nil + }, + } } func (r DnsZoneResource) Delete() sdk.ResourceFunc {