blob: 2b865cee319bbe82432136adf9507b75d67d409b [file] [log] [blame]
Giorgi Lekveishvilie8b2f012023-11-30 19:05:03 +04001package controllers
2
3import (
4 "fmt"
5 "io"
6 "io/fs"
7 "os"
8 "text/template"
9
10 "github.com/Masterminds/sprig/v3"
11 "github.com/go-git/go-billy/v5"
12 "github.com/go-git/go-billy/v5/util"
13)
14
15const zoneConfigFilename = "coredns.conf"
16const rootConfigFilename = "coredns.conf"
17const importAllConfigFiles = "import */" + zoneConfigFilename
18
19type ZoneStore interface {
20 ConfigPath() string
21 AddDNSSec(key DNSSecKey) error
22}
23
24type ZoneConfig struct {
25 Zone string
26 PublicIPs []string
27 PrivateIP string
28 Nameservers []string
29 DNSSec *DNSSecKey
30}
31
32type ZoneStoreFactory interface {
33 ConfigPath() string
34 Create(zone ZoneConfig) (ZoneStore, error)
35 Debug()
36}
37
38type fsZoneStoreFactory struct {
39 fs billy.Filesystem
40}
41
42func NewFSZoneStoreFactory(fs billy.Filesystem) (ZoneStoreFactory, error) {
43 if err := util.WriteFile(fs, rootConfigFilename, []byte(importAllConfigFiles), os.ModePerm); err != nil {
44 return nil, err
45 }
46 return &fsZoneStoreFactory{fs}, nil
47}
48
49func (f *fsZoneStoreFactory) ConfigPath() string {
50 return f.fs.Join(f.fs.Root(), rootConfigFilename)
51}
52
53func (f *fsZoneStoreFactory) Debug() {
54 fmt.Println("------------")
55 util.Walk(f.fs, ".", func(path string, info fs.FileInfo, err error) error {
56 fmt.Println(path)
57 if !info.IsDir() {
58 r, err := f.fs.Open(path)
59 if err != nil {
60 return err
61 }
62 defer r.Close()
63 _, err = io.Copy(os.Stdout, r)
64 return err
65 }
66 return nil
67 })
68 fmt.Println("++++++++++++++")
69}
70
71func (f *fsZoneStoreFactory) Create(zone ZoneConfig) (ZoneStore, error) {
72 if err := f.fs.MkdirAll(zone.Zone, fs.ModePerm); err != nil {
73 return nil, err
74 }
75 zfs, err := f.fs.Chroot(zone.Zone)
76 if err != nil {
77 return nil, err
78 }
79 z, err := NewFSZoneStore(zone, zfs)
80 if err != nil {
81 defer func() {
82 if err := f.fs.Remove(zone.Zone); err != nil {
83 fmt.Printf("Failed to remove zone directory: %s\n", err.Error())
84 }
85 }()
86 }
87 return z, nil
88}
89
90type fsZoneStore struct {
91 zone ZoneConfig
92 fs billy.Filesystem
93}
94
95func NewFSZoneStore(zone ZoneConfig, fs billy.Filesystem) (ZoneStore, error) {
96 if zone.DNSSec != nil {
97 sec := zone.DNSSec
98 if err := util.WriteFile(fs, sec.Basename+".key", sec.Key, 0644); err != nil {
99 return nil, err
100 }
101 if err := util.WriteFile(fs, sec.Basename+".private", sec.Private, 0600); err != nil {
102 return nil, err
103 }
104 }
105 conf, err := fs.Create(zoneConfigFilename)
106 if err != nil {
107 return nil, err
108 }
109 defer conf.Close()
110 configTmpl, err := template.New("config").Funcs(sprig.TxtFuncMap()).Parse(`
111{{ .zone.Zone }}:53 {
112 file {{ .rootDir }}/zone.db
113 errors
114 {{ if .zone.DNSSec }}
115 dnssec {
116 key file {{ .rootDir}}/{{ .zone.DNSSec.Basename }}
117 }
118 {{ end }}
119 log
120 health {
121 lameduck 5s
122 }
123 ready
124 cache 30
125 loop
126 reload
127 loadbalance
128}`)
129 if err != nil {
130 return nil, err
131 }
132 if err := configTmpl.Execute(conf, map[string]any{
133 "zone": zone,
134 "rootDir": fs.Root(),
135 }); err != nil {
136 return nil, err
137 }
138 recordsTmpl, err := template.New("records").Funcs(sprig.TxtFuncMap()).Parse(`
139{{ .zone }}. IN SOA ns1.{{ .zone }}. hostmaster.{{ .zone }}. 2015082541 7200 3600 1209600 3600
140{{ range $i, $ns := .nameservers }}
141ns{{ add1 $i }} 10800 IN A {{ $ns }}
142{{ end }}
143{{ range .publicIngressIPs }}
144@ 10800 IN A {{ . }}
145{{ end }}
146* 10800 IN CNAME {{ .zone }}.
147p 10800 IN CNAME {{ .zone }}.
148*.p 10800 IN A {{ .privateIngressIP }}
149`)
150 records, err := fs.Create("zone.db")
151 if err != nil {
152 return nil, err
153 }
154 defer records.Close()
155 if err := recordsTmpl.Execute(records, map[string]any{
156 "zone": zone.Zone,
157 "publicIngressIPs": zone.PublicIPs,
158 "privateIngressIP": zone.PrivateIP,
159 "nameservers": zone.Nameservers,
160 }); err != nil {
161 return nil, err
162 }
163 return &fsZoneStore{zone, fs}, nil
164}
165
166func (s *fsZoneStore) ConfigPath() string {
167 return s.fs.Join(s.fs.Root(), zoneConfigFilename)
168}
169
170func (s *fsZoneStore) AddDNSSec(key DNSSecKey) error {
171 return nil
172}