blob: 1316dc06f8ca6ca06b231187edc2c49a212f9c98 [file] [log] [blame]
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04001package tasks
2
3import (
4 "context"
gioe72b54f2024-04-22 10:44:41 +04005 "encoding/json"
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +04006 "fmt"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04007 "net"
gioe72b54f2024-04-22 10:44:41 +04008 "strings"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04009 "time"
10
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040011 "github.com/giolekva/pcloud/core/installer"
gioe72b54f2024-04-22 10:44:41 +040012 "github.com/giolekva/pcloud/core/installer/dns"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040013)
14
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040015type Check func(ch Check) error
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040016
gioe72b54f2024-04-22 10:44:41 +040017func SetupZoneTask(env installer.EnvConfig, mgr *installer.InfraAppManager, st *state) Task {
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040018 ret := newSequentialParentTask(
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040019 "Configure DNS",
20 true,
gioe72b54f2024-04-22 10:44:41 +040021 SetupDNSServer(env, st),
22 WaitToPropagate(st.dnsClient, env.Domain, env.PublicIP),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040023 )
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040024 ret.beforeStart = func() {
25 st.infoListener(fmt.Sprintf("Generating DNS zone records for %s", env.Domain))
26 }
27 ret.afterDone = func() {
28 st.infoListener("DNS zone records have been propagated.")
29 }
30 return ret
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040031}
32
gioe72b54f2024-04-22 10:44:41 +040033func join[T fmt.Stringer](items []T, sep string) string {
34 var tmp []string
35 for _, i := range items {
36 tmp = append(tmp, i.String())
37 }
38 return strings.Join(tmp, ",")
39}
40
41func SetupDNSServer(env installer.EnvConfig, st *state) Task {
42 t := newLeafTask("Start up DNS server", func() error {
43 addressPool := fmt.Sprintf("%s-dns", env.Id)
44 {
45 app, err := installer.FindEnvApp(st.appsRepo, "env-dns")
46 if err != nil {
47 return err
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040048 }
gio44f621b2024-04-29 09:44:38 +040049 instanceId := app.Slug()
gioe72b54f2024-04-22 10:44:41 +040050 appDir := fmt.Sprintf("/apps/%s", instanceId)
51 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
52 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
53 "addressPool": addressPool,
54 "inClusterIP": env.Network.DNSInClusterIP.String(),
55 "publicIP": join(env.PublicIP, ","),
56 "privateIP": env.Network.Ingress.String(),
57 "nameserverIP": join(env.NameserverIP, ","),
58 }); err != nil {
59 return err
60 }
61 }
62 {
63 app, err := installer.FindInfraApp(st.appsRepo, "dns-gateway")
64 if err != nil {
65 return err
66 }
67 cfg, err := st.infraAppManager.FindInstance("dns-gateway")
68 if err != nil {
69 return err
70 }
71 serversJSON, ok := cfg.Values["servers"]
72 if !ok {
73 serversJSON = []installer.EnvDNS{}
74 }
75 serversTmp, err := json.Marshal(serversJSON)
76 if err != nil {
77 return err
78 }
79 servers := []installer.EnvDNS{}
80 if err := json.Unmarshal(serversTmp, &servers); err != nil {
81 return err
82 }
83 servers = append(servers, installer.EnvDNS{
84 env.Domain,
85 env.Network.DNSInClusterIP.String(),
86 })
87 if err := st.infraAppManager.Update(app, "dns-gateway", map[string]any{
88 "servers": servers,
89 }); err != nil {
90 return err
91 }
92 }
93 {
94 for {
95 if _, err := st.dnsFetcher.Fetch(fmt.Sprintf("http://dns-api.%sdns.svc.cluster.local/records-to-publish", env.NamespacePrefix)); err != nil {
96 time.Sleep(5 * time.Second)
97 } else {
98 break
99 }
100 }
101 }
102 return nil
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400103 })
104 return &t
105}
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400106
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400107func WaitToPropagate(
gioe72b54f2024-04-22 10:44:41 +0400108 client dns.Client,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400109 name string,
110 expected []net.IP,
111) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400112 t := newLeafTask("Wait to propagate", func() error {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400113 ctx := context.TODO()
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400114 gotExpectedIPs := func(actual []net.IP) bool {
115 for _, a := range actual {
116 found := false
117 for _, e := range expected {
118 if a.Equal(e) {
119 found = true
120 break
121 }
122 }
123 if !found {
124 return false
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400125 }
126 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400127 return true
128 }
129 check := func(check Check) error {
gioe72b54f2024-04-22 10:44:41 +0400130 addrs, err := client.Lookup(name)
Giorgi Lekveishvili1caed362023-12-13 16:29:43 +0400131 fmt.Printf("DNS LOOKUP: %+v\n", addrs)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400132 if err == nil && gotExpectedIPs(addrs) {
133 return err
134 }
135 select {
136 case <-ctx.Done():
137 return nil
138 case <-time.After(5 * time.Second):
139 return check(check)
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400140 }
141 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400142 return check(check)
143 })
144 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400145}