2021-09-11 15:52:37 +00:00
|
|
|
package internal
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-12-06 17:51:44 +00:00
|
|
|
"strings"
|
2021-09-11 15:52:37 +00:00
|
|
|
|
|
|
|
"github.com/softlayer/softlayer-go/datatypes"
|
|
|
|
"github.com/softlayer/softlayer-go/services"
|
|
|
|
"github.com/softlayer/softlayer-go/session"
|
|
|
|
"github.com/softlayer/softlayer-go/sl"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Wrapper struct {
|
|
|
|
session *session.Session
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewWrapper(sess *session.Session) *Wrapper {
|
|
|
|
return &Wrapper{session: sess}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w Wrapper) AddTXTRecord(fqdn, domain, value string, ttl int) error {
|
|
|
|
service := services.GetDnsDomainService(w.session)
|
|
|
|
|
|
|
|
domainID, err := getDomainID(service, domain)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get domain ID: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
service.Options.Id = domainID
|
|
|
|
|
|
|
|
if _, err := service.CreateTxtRecord(sl.String(fqdn), sl.String(value), sl.Int(ttl)); err != nil {
|
|
|
|
return fmt.Errorf("failed to create TXT record: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w Wrapper) CleanupTXTRecord(fqdn, domain string) error {
|
|
|
|
service := services.GetDnsDomainService(w.session)
|
|
|
|
|
|
|
|
domainID, err := getDomainID(service, domain)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get domain ID: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
service.Options.Id = domainID
|
|
|
|
|
|
|
|
records, err := findTxtRecords(service, fqdn)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to find TXT records: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return deleteResourceRecords(service, records)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getDomainID(service services.Dns_Domain, domain string) (*int, error) {
|
|
|
|
res, err := service.GetByDomainName(sl.String(domain))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, r := range res {
|
|
|
|
if r.Id == nil || toString(r.Name) != domain {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Id, nil
|
|
|
|
}
|
|
|
|
|
2022-12-06 17:51:44 +00:00
|
|
|
// The domain was not found by name.
|
|
|
|
// For subdomains this is not unusual in softlayer.
|
|
|
|
// So in case a subdomain like `sub.toplevel.tld` was used try again using the parent domain
|
|
|
|
// (strip the first part in the domain string -> `toplevel.tld`).
|
|
|
|
_, parent, found := strings.Cut(domain, ".")
|
|
|
|
if !found || !strings.Contains(parent, ".") {
|
|
|
|
return nil, fmt.Errorf("no data found for domain: %s", domain)
|
|
|
|
}
|
|
|
|
|
|
|
|
return getDomainID(service, parent)
|
2021-09-11 15:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func findTxtRecords(service services.Dns_Domain, fqdn string) ([]datatypes.Dns_Domain_ResourceRecord, error) {
|
|
|
|
var results []datatypes.Dns_Domain_ResourceRecord
|
|
|
|
|
|
|
|
records, err := service.GetResourceRecords()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, record := range records {
|
|
|
|
if toString(record.Host) == fqdn && toString(record.Type) == "txt" {
|
|
|
|
results = append(results, record)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(results) == 0 {
|
|
|
|
return nil, fmt.Errorf("no data found of fqdn: %s", fqdn)
|
|
|
|
}
|
|
|
|
|
|
|
|
return results, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func deleteResourceRecords(service services.Dns_Domain, records []datatypes.Dns_Domain_ResourceRecord) error {
|
|
|
|
resourceRecord := services.GetDnsDomainResourceRecordService(service.Session)
|
|
|
|
|
|
|
|
// TODO maybe a bug: only the last record will be deleted
|
|
|
|
for _, record := range records {
|
|
|
|
resourceRecord.Options.Id = record.Id
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := resourceRecord.DeleteObject()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("no data found of fqdn: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func toString(v *string) string {
|
|
|
|
if v == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
return *v
|
|
|
|
}
|