blob: 60a8a9d969a800eef6ff53cab2f459f937a5f13a [file] [log] [blame]
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04001package tasks
2
3import (
4 "context"
5 "fmt"
6 "net"
7 "text/template"
8 "time"
9
10 "github.com/Masterminds/sprig/v3"
11
12 "github.com/giolekva/pcloud/core/installer"
13)
14
15type dnsResolver struct {
16 basicTask
17 name string
18 expected []net.IP
19 ctx context.Context
20 env Env
21 st *state
22}
23
24func NewDNSResolverTask(
25 name string,
26 expected []net.IP,
27 ctx context.Context,
28 env Env,
29 st *state,
30) Task {
31 return &dnsResolver{
32 basicTask: basicTask{
33 title: "Configure DNS",
34 },
35 name: name,
36 expected: expected,
37 ctx: ctx,
38 env: env,
39 st: st,
40 }
41}
42
43func (t *dnsResolver) Start() {
44 repo, err := t.st.ssClient.GetRepo("config")
45 if err != nil {
46 t.callDoneListeners(err)
47 return
48 }
49 r := installer.NewRepoIO(repo, t.st.ssClient.Signer)
50 {
51 key, err := newDNSSecKey(t.env.Domain)
52 if err != nil {
53 t.callDoneListeners(err)
54 return
55 }
56 out, err := r.Writer("dns-zone.yaml")
57 if err != nil {
58 t.callDoneListeners(err)
59 return
60 }
61 defer out.Close()
62 dnsZoneTmpl, err := template.New("config").Funcs(sprig.TxtFuncMap()).Parse(`
63apiVersion: dodo.cloud.dodo.cloud/v1
64kind: DNSZone
65metadata:
66 name: dns-zone
67 namespace: {{ .namespace }}
68spec:
69 zone: {{ .zone }}
70 privateIP: 10.1.0.1
71 publicIPs:
72{{ range .publicIPs }}
73 - {{ .String }}
74{{ end }}
75 nameservers:
76{{ range .publicIPs }}
77 - {{ .String }}
78{{ end }}
79 dnssec:
80 enabled: true
81 secretName: dnssec-key
82---
83apiVersion: v1
84kind: Secret
85metadata:
86 name: dnssec-key
87 namespace: {{ .namespace }}
88type: Opaque
89data:
90 basename: {{ .dnssec.Basename | b64enc }}
91 key: {{ .dnssec.Key | toString | b64enc }}
92 private: {{ .dnssec.Private | toString | b64enc }}
93 ds: {{ .dnssec.DS | toString | b64enc }}
94`)
95 if err != nil {
96 t.callDoneListeners(err)
97 return
98 }
99 if err := dnsZoneTmpl.Execute(out, map[string]any{
100 "namespace": t.env.Name,
101 "zone": t.env.Domain,
102 "dnssec": key,
103 "publicIPs": t.st.publicIPs,
104 }); err != nil {
105 t.callDoneListeners(err)
106 return
107 }
108 rootKust := installer.NewKustomization()
109 rootKust.AddResources("dns-zone.yaml")
110 if err := r.WriteKustomization("kustomization.yaml", rootKust); err != nil {
111 t.callDoneListeners(err)
112 return
113 }
114 r.CommitAndPush("configure dns zone")
115 }
116
117 gotExpectedIPs := func(actual []net.IP) bool {
118 for _, a := range actual {
119 found := false
120 for _, e := range t.expected {
121 if a.Equal(e) {
122 found = true
123 break
124 }
125 }
126 if !found {
127 return false
128 }
129 }
130 return true
131 }
132 check := func(check Check) {
133 addrs, err := net.LookupIP(t.name)
134 if err == nil && gotExpectedIPs(addrs) {
135 t.callDoneListeners(nil)
136 return
137 }
138 select {
139 case <-t.ctx.Done():
140 t.callDoneListeners(fmt.Errorf("deadline exceeded"))
141 return
142 case <-time.After(5 * time.Second):
143 check(check)
144 }
145 }
146 check(check)
147}
148
149type Check func(ch Check)