readysite / pkg / platform / providers / gcp / dns.go
2.6 KB
dns.go
package gcp

import (
	"fmt"
	"strings"

	"github.com/readysite/readysite/pkg/platform"
	"google.golang.org/api/dns/v1"
)

// CreateDNSZone creates a Cloud DNS managed zone
func (b *backend) CreateDNSZone(domain string) (*platform.DNSZone, error) {
	// Zone name must be lowercase alphanumeric with dashes
	zoneName := strings.ReplaceAll(domain, ".", "-")

	zone := &dns.ManagedZone{
		Name:        zoneName,
		DnsName:     domain + ".",
		Description: "Managed by ReadySite",
	}

	created, err := b.dns.ManagedZones.Create(b.project, zone).Context(b.ctx).Do()
	if err != nil {
		return nil, fmt.Errorf("create managed zone: %w", err)
	}

	return &platform.DNSZone{
		Name: strings.TrimSuffix(created.DnsName, "."),
		TTL:  300,
	}, nil
}

// GetDNSZone retrieves a Cloud DNS managed zone
func (b *backend) GetDNSZone(domain string) (*platform.DNSZone, error) {
	zoneName := strings.ReplaceAll(domain, ".", "-")

	zone, err := b.dns.ManagedZones.Get(b.project, zoneName).Context(b.ctx).Do()
	if err != nil {
		if strings.Contains(err.Error(), "not found") || strings.Contains(err.Error(), "404") {
			return nil, platform.ErrNotFound
		}
		return nil, fmt.Errorf("get managed zone: %w", err)
	}

	return &platform.DNSZone{
		Name: strings.TrimSuffix(zone.DnsName, "."),
		TTL:  300,
	}, nil
}

// AddDNSRecord adds a Cloud DNS record
func (b *backend) AddDNSRecord(zone string, record platform.DNSRecord) error {
	zoneName := strings.ReplaceAll(zone, ".", "-")

	name := record.Name
	if name == "@" {
		name = zone + "."
	} else {
		name = record.Name + "." + zone + "."
	}

	rrset := &dns.ResourceRecordSet{
		Name:    name,
		Type:    record.Type,
		Ttl:     int64(record.TTL),
		Rrdatas: []string{record.Value},
	}

	change := &dns.Change{
		Additions: []*dns.ResourceRecordSet{rrset},
	}

	_, err := b.dns.Changes.Create(b.project, zoneName, change).Context(b.ctx).Do()
	if err != nil {
		return fmt.Errorf("create record: %w", err)
	}
	return nil
}

// DeleteDNSRecord removes a Cloud DNS record
func (b *backend) DeleteDNSRecord(zone, recordID string) error {
	zoneName := strings.ReplaceAll(zone, ".", "-")

	// recordID format: "TYPE:NAME:VALUE"
	parts := strings.SplitN(recordID, ":", 3)
	if len(parts) != 3 {
		return fmt.Errorf("invalid record ID format (expected TYPE:NAME:VALUE)")
	}

	rrset := &dns.ResourceRecordSet{
		Name:    parts[1],
		Type:    parts[0],
		Ttl:     300,
		Rrdatas: []string{parts[2]},
	}

	change := &dns.Change{
		Deletions: []*dns.ResourceRecordSet{rrset},
	}

	_, err := b.dns.Changes.Create(b.project, zoneName, change).Context(b.ctx).Do()
	if err != nil {
		return fmt.Errorf("delete record: %w", err)
	}
	return nil
}
← Back