blob: e3331c4de3d3bc9f35cf96cc6dbf4be3c56d8176 [file] [log] [blame]
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +04001package installer
2
3import (
4 "context"
5 _ "embed"
6 "fmt"
7 "log"
8 "net/netip"
9 "path/filepath"
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +040010 "strings"
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040011 "time"
12
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040013 "helm.sh/helm/v3/pkg/action"
14 "helm.sh/helm/v3/pkg/chart"
15 "helm.sh/helm/v3/pkg/chart/loader"
16
17 "github.com/giolekva/pcloud/core/installer/soft"
18)
19
20const IPAddressPoolLocal = "local"
21const IPAddressPoolConfigRepo = "config-repo"
22const IPAddressPoolIngressPublic = "ingress-public"
23
Giorgi Lekveishvili5c2c0b92023-12-07 17:35:40 +040024const dnsAPIConfigMapName = "api-config"
25
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040026type Bootstrapper struct {
27 cl ChartLoader
28 ns NamespaceCreator
29 ha HelmActionConfigFactory
30}
31
32func NewBootstrapper(cl ChartLoader, ns NamespaceCreator, ha HelmActionConfigFactory) Bootstrapper {
33 return Bootstrapper{cl, ns, ha}
34}
35
36func (b Bootstrapper) Run(env EnvConfig) error {
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +040037 if err := b.ns.Create(env.Name); err != nil {
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040038 return err
39 }
40 if err := b.installMetallb(env); err != nil {
41 return err
42 }
43 if err := b.installLonghorn(env.Name, env.StorageDir, env.VolumeDefaultReplicaCount); err != nil {
44 return err
45 }
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +040046 bootstrapJobKeys, err := NewSSHKeyPair("bootstrapper")
47 if err != nil {
48 return err
49 }
50 if err := b.installSoftServe(bootstrapJobKeys.AuthorizedKey(), env.Name, env.ServiceIPs.ConfigRepo); err != nil {
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040051 return err
52 }
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +040053 ss, err := soft.WaitForClient(
54 netip.AddrPortFrom(env.ServiceIPs.ConfigRepo, 22).String(),
55 bootstrapJobKeys.RawPrivateKey(),
56 log.Default())
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040057 if err != nil {
58 return err
59 }
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +040060 defer func() {
61 if ss.RemovePublicKey("admin", bootstrapJobKeys.AuthorizedKey()); err != nil {
62 fmt.Printf("Failed to remove admin public key: %s\n", err.Error())
63 }
64 }()
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040065 if ss.AddPublicKey("admin", string(env.AdminPublicKey)); err != nil {
66 return err
67 }
68 if err := b.installFluxcd(ss, env.Name); err != nil {
69 return err
70 }
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +040071 fmt.Println("Fluxcd installed")
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +040072 repo, err := ss.GetRepo("config")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040073 if err != nil {
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +040074 fmt.Println("Failed to get config repo")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040075 return err
76 }
77 repoIO := NewRepoIO(repo, ss.Signer)
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +040078 fmt.Println("Configuring main repo")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040079 if err := configureMainRepo(repoIO, env); err != nil {
80 return err
81 }
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +040082 fmt.Println("Installing infrastructure services")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040083 nsGen := NewPrefixGenerator(env.NamespacePrefix)
84 if err := b.installInfrastructureServices(repoIO, nsGen, b.ns, env); err != nil {
85 return err
86 }
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +040087 fmt.Println("Installing DNS Zone Manager")
88 if err := b.installDNSZoneManager(ss, repoIO, nsGen, b.ns, env); err != nil {
89 return err
90 }
Giorgi Lekveishvili2df23db2023-12-14 07:55:22 +040091 fmt.Println("Installing Fluxcd Reconciler")
92 if err := b.installFluxcdReconciler(ss, repoIO, nsGen, b.ns, env); err != nil {
93 return err
94 }
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +040095 fmt.Println("Installing env manager")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +040096 if err := b.installEnvManager(ss, repoIO, nsGen, b.ns, env); err != nil {
97 return err
98 }
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +040099 fmt.Println("Environment ready to use")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400100 return nil
101}
102
103func (b Bootstrapper) installMetallb(env EnvConfig) error {
104 if err := b.installMetallbNamespace(env); err != nil {
105 return err
106 }
107 if err := b.installMetallbService(); err != nil {
108 return err
109 }
110 if err := b.installMetallbIPAddressPool(IPAddressPoolLocal, true, env.ServiceIPs.From, env.ServiceIPs.To); err != nil {
111 return err
112 }
113 if err := b.installMetallbIPAddressPool(IPAddressPoolConfigRepo, false, env.ServiceIPs.ConfigRepo, env.ServiceIPs.ConfigRepo); err != nil {
114 return err
115 }
116 if err := b.installMetallbIPAddressPool(IPAddressPoolIngressPublic, false, env.ServiceIPs.IngressPublic, env.ServiceIPs.IngressPublic); err != nil {
117 return err
118 }
119 return nil
120}
121
122func (b Bootstrapper) installMetallbNamespace(env EnvConfig) error {
123 fmt.Println("Installing metallb namespace")
124 config, err := b.ha.New(env.Name)
125 if err != nil {
126 return err
127 }
128 chart, err := b.cl.Load("namespace")
129 if err != nil {
130 return err
131 }
132 values := map[string]any{
133 "namespace": "metallb-system",
134 "labels": []string{
135 "pod-security.kubernetes.io/audit: privileged",
136 "pod-security.kubernetes.io/enforce: privileged",
137 "pod-security.kubernetes.io/warn: privileged",
138 },
139 }
140 installer := action.NewInstall(config)
141 installer.Namespace = env.Name
142 installer.ReleaseName = "metallb-ns"
143 installer.Wait = true
144 installer.WaitForJobs = true
145 if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
146 return err
147 }
148 return nil
149}
150
151func (b Bootstrapper) installMetallbService() error {
152 fmt.Println("Installing metallb")
153 config, err := b.ha.New("metallb-system")
154 if err != nil {
155 return err
156 }
157 chart, err := b.cl.Load("metallb")
158 if err != nil {
159 return err
160 }
161 values := map[string]any{ // TODO(giolekva): add loadBalancerClass?
162 "controller": map[string]any{
163 "image": map[string]any{
164 "repository": "quay.io/metallb/controller",
Giorgi Lekveishvilic06164d2023-11-22 13:51:29 +0400165 "tag": "v0.13.12",
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400166 "pullPolicy": "IfNotPresent",
167 },
168 "logLevel": "info",
169 },
170 "speaker": map[string]any{
171 "image": map[string]any{
172 "repository": "quay.io/metallb/speaker",
Giorgi Lekveishvilic06164d2023-11-22 13:51:29 +0400173 "tag": "v0.13.12",
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400174 "pullPolicy": "IfNotPresent",
175 },
176 "logLevel": "info",
177 },
178 }
179 installer := action.NewInstall(config)
180 installer.Namespace = "metallb-system"
181 installer.CreateNamespace = true
182 installer.ReleaseName = "metallb"
183 installer.IncludeCRDs = true
184 installer.Wait = true
185 installer.WaitForJobs = true
186 installer.Timeout = 20 * time.Minute
187 if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
188 return err
189 }
190 return nil
191}
192
193func (b Bootstrapper) installMetallbIPAddressPool(name string, autoAssign bool, from, to netip.Addr) error {
194 fmt.Printf("Installing metallb-ipaddresspool: %s\n", name)
195 config, err := b.ha.New("metallb-system")
196 if err != nil {
197 return err
198 }
199 chart, err := b.cl.Load("metallb-ipaddresspool")
200 if err != nil {
201 return err
202 }
203 values := map[string]any{
204 "name": name,
205 "autoAssign": autoAssign,
206 "from": from.String(),
207 "to": to.String(),
208 }
209 installer := action.NewInstall(config)
210 installer.Namespace = "metallb-system"
211 installer.CreateNamespace = true
212 installer.ReleaseName = name
213 installer.Wait = true
214 installer.WaitForJobs = true
215 installer.Timeout = 20 * time.Minute
216 if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
217 return err
218 }
219 return nil
220}
221
222func (b Bootstrapper) installLonghorn(envName string, storageDir string, volumeDefaultReplicaCount int) error {
223 fmt.Println("Installing Longhorn")
224 config, err := b.ha.New(envName)
225 if err != nil {
226 return err
227 }
228 chart, err := b.cl.Load("longhorn")
229 if err != nil {
230 return err
231 }
232 values := map[string]any{
233 "defaultSettings": map[string]any{
234 "defaultDataPath": storageDir,
235 },
236 "persistence": map[string]any{
237 "defaultClassReplicaCount": volumeDefaultReplicaCount,
238 },
239 "service": map[string]any{
240 "ui": map[string]any{
241 "type": "LoadBalancer",
242 },
243 },
244 "ingress": map[string]any{
245 "enabled": false,
246 },
247 }
248 installer := action.NewInstall(config)
249 installer.Namespace = "longhorn-system"
250 installer.CreateNamespace = true
251 installer.ReleaseName = "longhorn"
252 installer.Wait = true
253 installer.WaitForJobs = true
254 installer.Timeout = 20 * time.Minute
255 if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
256 return err
257 }
258 return nil
259}
260
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400261func (b Bootstrapper) installSoftServe(adminPublicKey string, namespace string, repoIP netip.Addr) error {
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400262 fmt.Println("Installing SoftServe")
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +0400263 keys, err := NewSSHKeyPair("soft-serve")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400264 if err != nil {
265 return err
266 }
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400267 config, err := b.ha.New(namespace)
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400268 if err != nil {
269 return err
270 }
271 chart, err := b.cl.Load("soft-serve")
272 if err != nil {
273 return err
274 }
275 values := map[string]any{
276 "image": map[string]any{
277 "repository": "charmcli/soft-serve",
Giorgi Lekveishvilic06164d2023-11-22 13:51:29 +0400278 "tag": "v0.7.1",
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400279 "pullPolicy": "IfNotPresent",
280 },
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400281 "privateKey": string(keys.RawPrivateKey()),
282 "publicKey": string(keys.RawAuthorizedKey()),
283 "adminKey": adminPublicKey,
284 "reservedIP": repoIP.String(),
285 "serviceType": "LoadBalancer",
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400286 }
287 installer := action.NewInstall(config)
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400288 installer.Namespace = namespace
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400289 installer.CreateNamespace = true
290 installer.ReleaseName = "soft-serve"
291 installer.Wait = true
292 installer.WaitForJobs = true
293 installer.Timeout = 20 * time.Minute
294 if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
295 return err
296 }
297 return nil
298}
299
300func (b Bootstrapper) installFluxcd(ss *soft.Client, envName string) error {
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +0400301 keys, err := NewSSHKeyPair("fluxcd")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400302 if err != nil {
303 return err
304 }
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +0400305 if err := ss.AddUser("flux", keys.AuthorizedKey()); err != nil {
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400306 return err
307 }
308 if err := ss.MakeUserAdmin("flux"); err != nil {
309 return err
310 }
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400311 if err := ss.AddRepository("config"); err != nil {
312 return err
313 }
314 repo, err := ss.GetRepo("config")
315 if err != nil {
316 return err
317 }
318 repoIO := NewRepoIO(repo, ss.Signer)
319 if err := repoIO.WriteCommitAndPush("README.md", fmt.Sprintf("# %s systems", envName), "readme"); err != nil {
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400320 return err
321 }
322 fmt.Println("Installing Flux")
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +0400323 ssPublicKeys, err := ss.GetPublicKeys()
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400324 if err != nil {
325 return err
326 }
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400327 host := strings.Split(ss.Addr, ":")[0]
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400328 if err := b.installFluxBootstrap(
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400329 ss.GetRepoAddress("config"),
330 host,
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +0400331 ssPublicKeys,
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +0400332 string(keys.RawPrivateKey()),
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400333 envName,
334 ); err != nil {
335 return err
336 }
337 return nil
338}
339
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +0400340func (b Bootstrapper) installFluxBootstrap(repoAddr, repoHost string, repoHostPubKeys []string, privateKey, envName string) error {
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400341 config, err := b.ha.New(envName)
342 if err != nil {
343 return err
344 }
345 chart, err := b.cl.Load("flux-bootstrap")
346 if err != nil {
347 return err
348 }
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +0400349 var lines []string
350 for _, k := range repoHostPubKeys {
351 lines = append(lines, fmt.Sprintf("%s %s", repoHost, k))
352 }
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400353 values := map[string]any{
354 "image": map[string]any{
Giorgi Lekveishvilic06164d2023-11-22 13:51:29 +0400355 "repository": "fluxcd/flux-cli",
356 "tag": "v2.1.2",
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400357 "pullPolicy": "IfNotPresent",
358 },
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +0400359 "repositoryAddress": repoAddr,
360 "repositoryHost": repoHost,
361 "repositoryHostPublicKeys": strings.Join(lines, "\n"),
362 "privateKey": privateKey,
363 "installationNamespace": fmt.Sprintf("%s-flux", envName),
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400364 }
365 installer := action.NewInstall(config)
366 installer.Namespace = envName
367 installer.CreateNamespace = true
368 installer.ReleaseName = "flux"
369 installer.Wait = true
370 installer.WaitForJobs = true
371 installer.Timeout = 20 * time.Minute
372 if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
373 return err
374 }
375 return nil
376}
377
378func (b Bootstrapper) installInfrastructureServices(repo RepoIO, nsGen NamespaceGenerator, nsCreator NamespaceCreator, env EnvConfig) error {
379 appRepo := NewInMemoryAppRepository(CreateAllApps())
380 install := func(name string) error {
381 app, err := appRepo.Find(name)
382 if err != nil {
383 return err
384 }
385 namespaces := make([]string, len(app.Namespaces))
386 for i, n := range app.Namespaces {
387 namespaces[i], err = nsGen.Generate(n)
388 if err != nil {
389 return err
390 }
391 }
392 for _, n := range namespaces {
393 if err := nsCreator.Create(n); err != nil {
394 return err
395 }
396 }
397 derived := Derived{
398 Global: Values{
399 PCloudEnvName: env.Name,
400 },
401 }
402 if len(namespaces) > 0 {
403 derived.Release.Namespace = namespaces[0]
404 }
405 values := map[string]any{
406 "IngressPublicIP": env.ServiceIPs.IngressPublic.String(),
407 }
408 return repo.InstallApp(*app, filepath.Join("/infrastructure", app.Name), values, derived)
409 }
410 appsToInstall := []string{
411 "resource-renderer-controller",
412 "headscale-controller",
413 "csi-driver-smb",
414 "ingress-public",
415 "cert-manager",
Giorgi Lekveishvili5c2c0b92023-12-07 17:35:40 +0400416 "cert-manager-webhook-pcloud",
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400417 }
418 for _, name := range appsToInstall {
419 if err := install(name); err != nil {
420 return err
421 }
422 }
423 return nil
424}
425
426func configureMainRepo(repo RepoIO, env EnvConfig) error {
427 if err := repo.WriteYaml("config.yaml", env); err != nil {
428 return err
429 }
430 kust := NewKustomization()
431 kust.AddResources(
432 fmt.Sprintf("%s-flux", env.Name),
433 "infrastructure",
434 "environments",
435 )
436 if err := repo.WriteKustomization("kustomization.yaml", kust); err != nil {
437 return err
438 }
439 {
440 out, err := repo.Writer("infrastructure/pcloud-charts.yaml")
441 if err != nil {
442 return err
443 }
444 defer out.Close()
445 _, err = out.Write([]byte(fmt.Sprintf(`
446apiVersion: source.toolkit.fluxcd.io/v1
447kind: GitRepository
448metadata:
449 name: pcloud # TODO(giolekva): use more generic name
450 namespace: %s
451spec:
452 interval: 1m0s
453 url: https://github.com/giolekva/pcloud
454 ref:
455 branch: main
456`, env.Name)))
457 if err != nil {
458 return err
459 }
460 }
461 infraKust := NewKustomization()
462 infraKust.AddResources("pcloud-charts.yaml")
463 if err := repo.WriteKustomization("infrastructure/kustomization.yaml", infraKust); err != nil {
464 return err
465 }
466 if err := repo.WriteKustomization("environments/kustomization.yaml", NewKustomization()); err != nil {
467 return err
468 }
469 if err := repo.CommitAndPush("initialize pcloud directory structure"); err != nil {
470 return err
471 }
472 return nil
473}
474
475func (b Bootstrapper) installEnvManager(ss *soft.Client, repo RepoIO, nsGen NamespaceGenerator, nsCreator NamespaceCreator, env EnvConfig) error {
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +0400476 keys, err := NewSSHKeyPair("env-manager")
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400477 if err != nil {
478 return err
479 }
480 user := fmt.Sprintf("%s-env-manager", env.Name)
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +0400481 if err := ss.AddUser(user, keys.AuthorizedKey()); err != nil {
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400482 return err
483 }
484 if err := ss.MakeUserAdmin(user); err != nil {
485 return err
486 }
487 appRepo := NewInMemoryAppRepository(CreateAllApps())
488 app, err := appRepo.Find("env-manager")
489 if err != nil {
490 return err
491 }
492 namespaces := make([]string, len(app.Namespaces))
493 for i, n := range app.Namespaces {
494 namespaces[i], err = nsGen.Generate(n)
495 if err != nil {
496 return err
497 }
498 }
499 for _, n := range namespaces {
500 if err := nsCreator.Create(n); err != nil {
501 return err
502 }
503 }
504 derived := Derived{
505 Global: Values{
506 PCloudEnvName: env.Name,
507 },
508 Values: map[string]any{
509 "RepoIP": env.ServiceIPs.ConfigRepo,
510 "RepoPort": 22,
Giorgi Lekveishvili724885f2023-11-29 16:18:42 +0400511 "RepoName": "config",
Giorgi Lekveishvilia1e77902023-11-06 14:48:27 +0400512 "SSHPrivateKey": string(keys.RawPrivateKey()),
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400513 },
514 }
515 if len(namespaces) > 0 {
516 derived.Release.Namespace = namespaces[0]
517 }
518 return repo.InstallApp(*app, filepath.Join("/infrastructure", app.Name), derived.Values, derived)
519}
520
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +0400521func (b Bootstrapper) installDNSZoneManager(ss *soft.Client, repo RepoIO, nsGen NamespaceGenerator, nsCreator NamespaceCreator, env EnvConfig) error {
522 const (
523 volumeClaimName = "dns-zone-configs"
524 volumeMountPath = "/etc/pcloud/dns-zone-configs"
525 )
526 ns, err := nsGen.Generate("dns-zone-manager")
527 if err != nil {
528 return err
529 }
530 if err := nsCreator.Create(ns); err != nil {
531 return err
532 }
533 appRepo := NewInMemoryAppRepository(CreateAllApps())
534 {
535 app, err := appRepo.Find("dns-zone-manager")
536 if err != nil {
537 return err
538 }
539 derived := Derived{
540 Global: Values{
541 PCloudEnvName: env.Name,
542 },
543 Values: map[string]any{
544 "Volume": map[string]any{
545 "ClaimName": volumeClaimName,
546 "MountPath": volumeMountPath,
547 "Size": "1Gi",
548 },
Giorgi Lekveishvili5c2c0b92023-12-07 17:35:40 +0400549 "APIConfigMapName": dnsAPIConfigMapName,
Giorgi Lekveishvili106a9352023-12-04 11:20:11 +0400550 },
551 Release: Release{
552 Namespace: ns,
553 },
554 }
555 if err := repo.InstallApp(*app, filepath.Join("/infrastructure", app.Name), derived.Values, derived); err != nil {
556 return err
557 }
558 }
559 return nil
560}
561
Giorgi Lekveishvili2df23db2023-12-14 07:55:22 +0400562func (b Bootstrapper) installFluxcdReconciler(ss *soft.Client, repo RepoIO, nsGen NamespaceGenerator, nsCreator NamespaceCreator, env EnvConfig) error {
563 appRepo := NewInMemoryAppRepository(CreateAllApps())
564 app, err := appRepo.Find("fluxcd-reconciler")
565 if err != nil {
566 return err
567 }
568 ns, err := nsGen.Generate(app.Namespaces[0])
569 if err != nil {
570 return err
571 }
572 if err := nsCreator.Create(ns); err != nil {
573 return err
574 }
575 derived := Derived{
576 Global: Values{
577 PCloudEnvName: env.Name,
578 },
579 Values: map[string]any{},
580 Release: Release{
581 Namespace: ns,
582 },
583 }
584 if err := repo.InstallApp(*app, filepath.Join("/infrastructure", app.Name), derived.Values, derived); err != nil {
585 return err
586 }
587 return nil
588}
589
Giorgi Lekveishvili94cda9d2023-07-20 10:16:09 +0400590type HelmActionConfigFactory interface {
591 New(namespace string) (*action.Configuration, error)
592}
593
594type ChartLoader interface {
595 Load(name string) (*chart.Chart, error)
596}
597
598type fsChartLoader struct {
599 baseDir string
600}
601
602func NewFSChartLoader(baseDir string) ChartLoader {
603 return &fsChartLoader{baseDir}
604}
605
606func (l *fsChartLoader) Load(name string) (*chart.Chart, error) {
607 return loader.Load(filepath.Join(l.baseDir, name))
608}