blob: 088078281b7ebad60c02427ed4be9e3344bbd334 [file] [log] [blame]
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04001package tasks
2
3import (
4 "context"
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +04005 "fmt"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04006 "net"
7 "text/template"
8 "time"
9
10 "github.com/Masterminds/sprig/v3"
11
12 "github.com/giolekva/pcloud/core/installer"
13)
14
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040015type Check func(ch Check) error
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040016
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040017func SetupZoneTask(env Env, ingressIP net.IP, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040018 return newSequentialParentTask(
19 fmt.Sprintf("Setup DNS zone records for %s", env.Domain),
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040020 CreateZoneRecords(env.Domain, st.publicIPs, ingressIP, env, st),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040021 WaitToPropagate(env.Domain, st.publicIPs),
22 )
23}
24
25func CreateZoneRecords(
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040026 name string,
27 expected []net.IP,
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040028 ingressIP net.IP,
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040029 env Env,
30 st *state,
31) Task {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040032 t := newLeafTask("Configure DNS", func() error {
33 repo, err := st.ssClient.GetRepo("config")
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040034 if err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040035 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040036 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040037 r := installer.NewRepoIO(repo, st.ssClient.Signer)
38 {
39 key, err := newDNSSecKey(env.Domain)
40 if err != nil {
41 return err
42 }
43 out, err := r.Writer("dns-zone.yaml")
44 if err != nil {
45 return err
46 }
47 defer out.Close()
48 dnsZoneTmpl, err := template.New("config").Funcs(sprig.TxtFuncMap()).Parse(`
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040049apiVersion: dodo.cloud.dodo.cloud/v1
50kind: DNSZone
51metadata:
52 name: dns-zone
53 namespace: {{ .namespace }}
54spec:
55 zone: {{ .zone }}
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040056 privateIP: {{ .ingressIP }}
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040057 publicIPs:
58{{ range .publicIPs }}
59 - {{ .String }}
60{{ end }}
61 nameservers:
62{{ range .publicIPs }}
63 - {{ .String }}
64{{ end }}
65 dnssec:
66 enabled: true
67 secretName: dnssec-key
68---
69apiVersion: v1
70kind: Secret
71metadata:
72 name: dnssec-key
73 namespace: {{ .namespace }}
74type: Opaque
75data:
76 basename: {{ .dnssec.Basename | b64enc }}
77 key: {{ .dnssec.Key | toString | b64enc }}
78 private: {{ .dnssec.Private | toString | b64enc }}
79 ds: {{ .dnssec.DS | toString | b64enc }}
80`)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040081 if err != nil {
82 return err
83 }
84 if err := dnsZoneTmpl.Execute(out, map[string]any{
85 "namespace": env.Name,
86 "zone": env.Domain,
87 "dnssec": key,
88 "publicIPs": st.publicIPs,
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040089 "ingressIP": ingressIP.String(),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040090 }); err != nil {
91 return err
92 }
93 rootKust := installer.NewKustomization()
94 rootKust.AddResources("dns-zone.yaml")
95 if err := r.WriteKustomization("kustomization.yaml", rootKust); err != nil {
96 return err
97 }
98 r.CommitAndPush("configure dns zone")
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040099 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400100 return nil
101 })
102 return &t
103}
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400104
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400105func WaitToPropagate(
106 name string,
107 expected []net.IP,
108) Task {
109 t := newLeafTask("Propagate DNS records", func() error {
110 ctx := context.TODO()
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400111 gotExpectedIPs := func(actual []net.IP) bool {
112 for _, a := range actual {
113 found := false
114 for _, e := range expected {
115 if a.Equal(e) {
116 found = true
117 break
118 }
119 }
120 if !found {
121 return false
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400122 }
123 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400124 return true
125 }
126 check := func(check Check) error {
127 addrs, err := net.LookupIP(name)
Giorgi Lekveishvili1caed362023-12-13 16:29:43 +0400128 fmt.Printf("DNS LOOKUP: %+v\n", addrs)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400129 if err == nil && gotExpectedIPs(addrs) {
130 return err
131 }
132 select {
133 case <-ctx.Done():
134 return nil
135 case <-time.After(5 * time.Second):
136 return check(check)
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400137 }
138 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400139 return check(check)
140 })
141 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400142}