nixfiles/iac/record.go
2023-02-12 05:49:50 -08:00

186 lines
4.8 KiB
Go

package iac
import (
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/creasty/defaults"
"github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"strings"
)
type DNSRecordType string
type HigherType uint16
const (
A DNSRecordType = "a"
AAAA = "aaaa"
MX = "mx"
TXT = "txt"
CAA = "caa"
CNAME = "cname"
IDOutput HigherType = 0
RawValue = 1
String = 2
)
type DNSRecord struct {
CFRecord *cloudflare.Record
Zone *Zone
Higher HigherType `default:"0""`
Name string `default:"@" yaml:"name"`
Kind DNSRecordType `yaml:"kind"`
RawValue pulumi.StringOutput
Value string `yaml:"value,omitempty"`
Priority int `yaml:"priority,omitempty"`
Flags string `yaml:"flags,omitempty"`
Tag string `yaml:"tag,omitempty"`
Ttl int `default:"3600" yaml:"ttl,omitempty"`
}
func (r *DNSRecord) UnmarshalYAML(unmarshal func(interface{}) error) (err error) {
err = defaults.Set(r)
if err != nil {
return err
}
type plain DNSRecord
if err := unmarshal((*plain)(r)); err != nil {
return err
}
return err
}
func (r *DNSRecord) getZone() pulumi.IDOutput {
return r.Zone.CFZone.ID()
}
func (r *DNSRecord) getName() string {
var base string
var hash [16]byte
if r.Higher == 0 {
base = fmt.Sprintf("%s-%s-%s", r.Zone.Alias, r.Kind, r.Name)
hash = md5.Sum([]byte(r.Value))
} else {
base = fmt.Sprintf("%s-%s", r.Kind, r.Name)
hash = md5.Sum([]byte(r.Name))
}
hashString := hex.EncodeToString(hash[:])[:5]
suffix := ""
switch r.Kind {
case MX:
suffix = fmt.Sprintf("-%d-%s", r.Priority, hashString)
case CAA:
suffix = fmt.Sprintf("%s-%s", r.Flags, r.Tag)
case A, AAAA, TXT, CNAME:
suffix = fmt.Sprintf("-%s", hashString)
}
built := base + suffix
return built
}
func (r *DNSRecord) handleOutput(ctx *pulumi.Context, zone *Zone) (err error) {
r.Zone = zone
var recordArgs *cloudflare.RecordArgs
switch r.Kind {
case CAA:
recordArgs = &cloudflare.RecordArgs{
ZoneId: r.Zone.CFZone.ID(),
Name: pulumi.String(r.Name),
Type: pulumi.String(strings.ToUpper(string(r.Kind))),
Ttl: pulumi.Int(r.Ttl),
Data: &cloudflare.RecordDataArgs{
Flags: pulumi.String(r.Flags),
Tag: pulumi.String(r.Tag),
Value: r.RawValue,
},
}
default:
recordArgs = &cloudflare.RecordArgs{
ZoneId: r.Zone.CFZone.ID(),
Name: pulumi.String(r.Name),
Type: pulumi.String(strings.ToUpper(string(r.Kind))),
Ttl: pulumi.Int(r.Ttl),
Priority: pulumi.Int(r.Priority),
Value: r.RawValue,
}
}
r.CFRecord, err = cloudflare.NewRecord(ctx, r.getName(), recordArgs, pulumi.DependsOn([]pulumi.Resource{r.Zone.CFZone}))
return err
}
func (r *DNSRecord) handle(ctx *pulumi.Context, zone *Zone) (err error) {
r.Zone = zone
cfzone := zone.CFZone
return r.handleCF(ctx, cfzone)
}
func (r *DNSRecord) handleCF(ctx *pulumi.Context, zone *cloudflare.Zone) (err error) {
zoneID := zone.ID()
depends := pulumi.DependsOn([]pulumi.Resource{zone})
return r.handleID(ctx, zoneID, depends)
}
func (r *DNSRecord) handleValue(ctx *pulumi.Context, zone *cloudflare.LookupZoneResult) (err error) {
var recordArgs *cloudflare.RecordArgs
switch r.Kind {
case CAA:
recordArgs = &cloudflare.RecordArgs{
ZoneId: pulumi.String(zone.ZoneId),
Name: pulumi.String(r.Name),
Type: pulumi.String(strings.ToUpper(string(r.Kind))),
Ttl: pulumi.Int(r.Ttl),
Data: &cloudflare.RecordDataArgs{
Flags: pulumi.String(r.Flags),
Tag: pulumi.String(r.Tag),
Value: r.RawValue,
},
}
default:
recordArgs = &cloudflare.RecordArgs{
ZoneId: pulumi.String(zone.ZoneId),
Name: pulumi.String(r.Name),
Type: pulumi.String(strings.ToUpper(string(r.Kind))),
Ttl: pulumi.Int(r.Ttl),
Priority: pulumi.Int(r.Priority),
Value: r.RawValue,
}
}
r.CFRecord, err = cloudflare.NewRecord(ctx, r.getName(), recordArgs)
return err
}
func (r *DNSRecord) handleID(ctx *pulumi.Context, zoneID pulumi.IDOutput, depends pulumi.ResourceOption) (err error) {
var recordArgs *cloudflare.RecordArgs
switch r.Kind {
case CAA:
recordArgs = &cloudflare.RecordArgs{
ZoneId: zoneID,
Name: pulumi.String(r.Name),
Type: pulumi.String(strings.ToUpper(string(r.Kind))),
Ttl: pulumi.Int(r.Ttl),
Data: &cloudflare.RecordDataArgs{
Flags: pulumi.String(r.Flags),
Tag: pulumi.String(r.Tag),
Value: pulumi.String(r.Value),
},
}
default:
recordArgs = &cloudflare.RecordArgs{
ZoneId: zoneID,
Name: pulumi.String(r.Name),
Type: pulumi.String(strings.ToUpper(string(r.Kind))),
Ttl: pulumi.Int(r.Ttl),
Priority: pulumi.Int(r.Priority),
Value: pulumi.String(r.Value),
}
}
r.CFRecord, err = cloudflare.NewRecord(ctx, r.getName(), recordArgs, depends)
return err
}