blob: 02d8fee07f4d03093506414256a6e32f291a2e1f [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 Lekveishvili378ea882023-12-12 13:59:18 +040017func SetupZoneTask(env Env, st *state) Task {
18 return newSequentialParentTask(
19 fmt.Sprintf("Setup DNS zone records for %s", env.Domain),
20 CreateZoneRecords(env.Domain, st.publicIPs, env, st),
21 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 Lekveishvili46743d42023-12-10 15:47:23 +040028 env Env,
29 st *state,
30) Task {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040031 t := newLeafTask("Configure DNS", func() error {
32 repo, err := st.ssClient.GetRepo("config")
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040033 if err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040034 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040035 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040036 r := installer.NewRepoIO(repo, st.ssClient.Signer)
37 {
38 key, err := newDNSSecKey(env.Domain)
39 if err != nil {
40 return err
41 }
42 out, err := r.Writer("dns-zone.yaml")
43 if err != nil {
44 return err
45 }
46 defer out.Close()
47 dnsZoneTmpl, err := template.New("config").Funcs(sprig.TxtFuncMap()).Parse(`
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040048apiVersion: dodo.cloud.dodo.cloud/v1
49kind: DNSZone
50metadata:
51 name: dns-zone
52 namespace: {{ .namespace }}
53spec:
54 zone: {{ .zone }}
55 privateIP: 10.1.0.1
56 publicIPs:
57{{ range .publicIPs }}
58 - {{ .String }}
59{{ end }}
60 nameservers:
61{{ range .publicIPs }}
62 - {{ .String }}
63{{ end }}
64 dnssec:
65 enabled: true
66 secretName: dnssec-key
67---
68apiVersion: v1
69kind: Secret
70metadata:
71 name: dnssec-key
72 namespace: {{ .namespace }}
73type: Opaque
74data:
75 basename: {{ .dnssec.Basename | b64enc }}
76 key: {{ .dnssec.Key | toString | b64enc }}
77 private: {{ .dnssec.Private | toString | b64enc }}
78 ds: {{ .dnssec.DS | toString | b64enc }}
79`)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040080 if err != nil {
81 return err
82 }
83 if err := dnsZoneTmpl.Execute(out, map[string]any{
84 "namespace": env.Name,
85 "zone": env.Domain,
86 "dnssec": key,
87 "publicIPs": st.publicIPs,
88 }); err != nil {
89 return err
90 }
91 rootKust := installer.NewKustomization()
92 rootKust.AddResources("dns-zone.yaml")
93 if err := r.WriteKustomization("kustomization.yaml", rootKust); err != nil {
94 return err
95 }
96 r.CommitAndPush("configure dns zone")
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040097 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040098 return nil
99 })
100 return &t
101}
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400102
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400103func WaitToPropagate(
104 name string,
105 expected []net.IP,
106) Task {
107 t := newLeafTask("Propagate DNS records", func() error {
108 ctx := context.TODO()
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400109 gotExpectedIPs := func(actual []net.IP) bool {
110 for _, a := range actual {
111 found := false
112 for _, e := range expected {
113 if a.Equal(e) {
114 found = true
115 break
116 }
117 }
118 if !found {
119 return false
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400120 }
121 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400122 return true
123 }
124 check := func(check Check) error {
125 addrs, err := net.LookupIP(name)
Giorgi Lekveishvili1caed362023-12-13 16:29:43 +0400126 fmt.Printf("DNS LOOKUP: %+v\n", addrs)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400127 if err == nil && gotExpectedIPs(addrs) {
128 return err
129 }
130 select {
131 case <-ctx.Done():
132 return nil
133 case <-time.After(5 * time.Second):
134 return check(check)
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400135 }
136 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400137 return check(check)
138 })
139 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400140}