blob: 7db2c3a067777e0244aa40002f868cf468f3d316 [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())
gio778577f2024-04-29 09:44:38 +040052 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
gioe72b54f2024-04-22 10:44:41 +040053 "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 {
gioe72b54f2024-04-22 10:44:41 +040063 cfg, err := st.infraAppManager.FindInstance("dns-gateway")
64 if err != nil {
65 return err
66 }
67 serversJSON, ok := cfg.Values["servers"]
68 if !ok {
69 serversJSON = []installer.EnvDNS{}
70 }
71 serversTmp, err := json.Marshal(serversJSON)
72 if err != nil {
73 return err
74 }
75 servers := []installer.EnvDNS{}
76 if err := json.Unmarshal(serversTmp, &servers); err != nil {
77 return err
78 }
79 servers = append(servers, installer.EnvDNS{
80 env.Domain,
81 env.Network.DNSInClusterIP.String(),
82 })
giof8843412024-05-22 16:38:05 +040083 if _, err := st.infraAppManager.Update("dns-gateway", map[string]any{
gioe72b54f2024-04-22 10:44:41 +040084 "servers": servers,
85 }); err != nil {
86 return err
87 }
88 }
89 {
90 for {
91 if _, err := st.dnsFetcher.Fetch(fmt.Sprintf("http://dns-api.%sdns.svc.cluster.local/records-to-publish", env.NamespacePrefix)); err != nil {
92 time.Sleep(5 * time.Second)
93 } else {
94 break
95 }
96 }
97 }
98 return nil
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040099 })
100 return &t
101}
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400102
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400103func WaitToPropagate(
gioe72b54f2024-04-22 10:44:41 +0400104 client dns.Client,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400105 name string,
106 expected []net.IP,
107) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400108 t := newLeafTask("Wait to propagate", func() error {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400109 ctx := context.TODO()
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400110 gotExpectedIPs := func(actual []net.IP) bool {
111 for _, a := range actual {
112 found := false
113 for _, e := range expected {
114 if a.Equal(e) {
115 found = true
116 break
117 }
118 }
119 if !found {
120 return false
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400121 }
122 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400123 return true
124 }
125 check := func(check Check) error {
gioe72b54f2024-04-22 10:44:41 +0400126 addrs, err := client.Lookup(name)
Giorgi Lekveishvili1caed362023-12-13 16:29:43 +0400127 fmt.Printf("DNS LOOKUP: %+v\n", addrs)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400128 if err == nil && gotExpectedIPs(addrs) {
129 return err
130 }
131 select {
132 case <-ctx.Done():
133 return nil
134 case <-time.After(5 * time.Second):
135 return check(check)
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400136 }
137 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400138 return check(check)
139 })
140 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400141}