blob: 25af4863f5eb796abca2f5c42fd275f83a748b07 [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(
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040019 "Configure DNS",
20 true,
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040021 CreateZoneRecords(env.Domain, st.publicIPs, ingressIP, env, st),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040022 WaitToPropagate(env.Domain, st.publicIPs),
23 )
24}
25
26func CreateZoneRecords(
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040027 name string,
28 expected []net.IP,
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040029 ingressIP net.IP,
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040030 env Env,
31 st *state,
32) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040033 t := newLeafTask("Generate and publish DNS records", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040034 repo, err := st.ssClient.GetRepo("config")
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040035 if err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040036 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040037 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040038 r := installer.NewRepoIO(repo, st.ssClient.Signer)
39 {
40 key, err := newDNSSecKey(env.Domain)
41 if err != nil {
42 return err
43 }
44 out, err := r.Writer("dns-zone.yaml")
45 if err != nil {
46 return err
47 }
48 defer out.Close()
49 dnsZoneTmpl, err := template.New("config").Funcs(sprig.TxtFuncMap()).Parse(`
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040050apiVersion: dodo.cloud.dodo.cloud/v1
51kind: DNSZone
52metadata:
53 name: dns-zone
54 namespace: {{ .namespace }}
55spec:
56 zone: {{ .zone }}
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040057 privateIP: {{ .ingressIP }}
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040058 publicIPs:
59{{ range .publicIPs }}
60 - {{ .String }}
61{{ end }}
62 nameservers:
63{{ range .publicIPs }}
64 - {{ .String }}
65{{ end }}
66 dnssec:
67 enabled: true
68 secretName: dnssec-key
69---
70apiVersion: v1
71kind: Secret
72metadata:
73 name: dnssec-key
74 namespace: {{ .namespace }}
75type: Opaque
76data:
77 basename: {{ .dnssec.Basename | b64enc }}
78 key: {{ .dnssec.Key | toString | b64enc }}
79 private: {{ .dnssec.Private | toString | b64enc }}
80 ds: {{ .dnssec.DS | toString | b64enc }}
81`)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040082 if err != nil {
83 return err
84 }
85 if err := dnsZoneTmpl.Execute(out, map[string]any{
86 "namespace": env.Name,
87 "zone": env.Domain,
88 "dnssec": key,
89 "publicIPs": st.publicIPs,
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +040090 "ingressIP": ingressIP.String(),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040091 }); err != nil {
92 return err
93 }
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040094 rootKust, err := r.ReadKustomization("kustomization.yaml")
95 if err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040096 return err
97 }
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040098 rootKust.AddResources("dns-zone.yaml")
99 if err := r.WriteKustomization("kustomization.yaml", *rootKust); err != nil {
100 return err
101 }
102 if err := r.CommitAndPush("configure dns zone"); err != nil {
103 return err
104 }
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400105 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400106 return nil
107 })
108 return &t
109}
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400110
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400111func WaitToPropagate(
112 name string,
113 expected []net.IP,
114) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400115 t := newLeafTask("Wait to propagate", func() error {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400116 ctx := context.TODO()
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400117 gotExpectedIPs := func(actual []net.IP) bool {
118 for _, a := range actual {
119 found := false
120 for _, e := range expected {
121 if a.Equal(e) {
122 found = true
123 break
124 }
125 }
126 if !found {
127 return false
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400128 }
129 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400130 return true
131 }
132 check := func(check Check) error {
133 addrs, err := net.LookupIP(name)
Giorgi Lekveishvili1caed362023-12-13 16:29:43 +0400134 fmt.Printf("DNS LOOKUP: %+v\n", addrs)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400135 if err == nil && gotExpectedIPs(addrs) {
136 return err
137 }
138 select {
139 case <-ctx.Done():
140 return nil
141 case <-time.After(5 * time.Second):
142 return check(check)
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400143 }
144 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400145 return check(check)
146 })
147 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400148}