1package internal
2
3import (
4	"fmt"
5
6	"github.com/softlayer/softlayer-go/datatypes"
7	"github.com/softlayer/softlayer-go/services"
8	"github.com/softlayer/softlayer-go/session"
9	"github.com/softlayer/softlayer-go/sl"
10)
11
12type Wrapper struct {
13	session *session.Session
14}
15
16func NewWrapper(sess *session.Session) *Wrapper {
17	return &Wrapper{session: sess}
18}
19
20func (w Wrapper) AddTXTRecord(fqdn, domain, value string, ttl int) error {
21	service := services.GetDnsDomainService(w.session)
22
23	domainID, err := getDomainID(service, domain)
24	if err != nil {
25		return fmt.Errorf("failed to get domain ID: %w", err)
26	}
27
28	service.Options.Id = domainID
29
30	if _, err := service.CreateTxtRecord(sl.String(fqdn), sl.String(value), sl.Int(ttl)); err != nil {
31		return fmt.Errorf("failed to create TXT record: %w", err)
32	}
33
34	return nil
35}
36
37func (w Wrapper) CleanupTXTRecord(fqdn, domain string) error {
38	service := services.GetDnsDomainService(w.session)
39
40	domainID, err := getDomainID(service, domain)
41	if err != nil {
42		return fmt.Errorf("failed to get domain ID: %w", err)
43	}
44
45	service.Options.Id = domainID
46
47	records, err := findTxtRecords(service, fqdn)
48	if err != nil {
49		return fmt.Errorf("failed to find TXT records: %w", err)
50	}
51
52	return deleteResourceRecords(service, records)
53}
54
55func getDomainID(service services.Dns_Domain, domain string) (*int, error) {
56	res, err := service.GetByDomainName(sl.String(domain))
57	if err != nil {
58		return nil, err
59	}
60
61	for _, r := range res {
62		if r.Id == nil || toString(r.Name) != domain {
63			continue
64		}
65
66		return r.Id, nil
67	}
68
69	return nil, fmt.Errorf("no data found of domain: %s", domain)
70}
71
72func findTxtRecords(service services.Dns_Domain, fqdn string) ([]datatypes.Dns_Domain_ResourceRecord, error) {
73	var results []datatypes.Dns_Domain_ResourceRecord
74
75	records, err := service.GetResourceRecords()
76	if err != nil {
77		return nil, err
78	}
79
80	for _, record := range records {
81		if toString(record.Host) == fqdn && toString(record.Type) == "txt" {
82			results = append(results, record)
83		}
84	}
85
86	if len(results) == 0 {
87		return nil, fmt.Errorf("no data found of fqdn: %s", fqdn)
88	}
89
90	return results, nil
91}
92
93func deleteResourceRecords(service services.Dns_Domain, records []datatypes.Dns_Domain_ResourceRecord) error {
94	resourceRecord := services.GetDnsDomainResourceRecordService(service.Session)
95
96	// TODO maybe a bug: only the last record will be deleted
97	for _, record := range records {
98		resourceRecord.Options.Id = record.Id
99	}
100
101	_, err := resourceRecord.DeleteObject()
102	if err != nil {
103		return fmt.Errorf("no data found of fqdn: %w", err)
104	}
105
106	return nil
107}
108
109func toString(v *string) string {
110	if v == nil {
111		return ""
112	}
113
114	return *v
115}
116