blob: 30e35e027103d299c28a923f0227b7b0b8cb1ca6 [file] [log] [blame]
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04001package tasks
2
3import (
4 "fmt"
5 "log"
6 "path/filepath"
7
8 "github.com/giolekva/pcloud/core/installer"
gioe72b54f2024-04-22 10:44:41 +04009 "github.com/giolekva/pcloud/core/installer/io"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040010 "github.com/giolekva/pcloud/core/installer/soft"
11)
12
gioe72b54f2024-04-22 10:44:41 +040013func SetupConfigRepoTask(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040014 ret := newSequentialParentTask(
15 "Configure Git repository",
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040016 true,
17 newSequentialParentTask(
18 "Start up Git server",
19 false,
20 NewCreateConfigRepoTask(env, st),
21 CreateGitClientTask(env, st),
22 ),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040023 NewInitConfigRepoTask(env, st),
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040024 NewActivateEnvTask(env, st),
25 newSequentialParentTask(
26 "Create initial commit",
27 false,
28 CreateRepoClient(env, st),
29 CommitEnvironmentConfiguration(env, st),
30 ConfigureFirstAccount(env, st),
31 ),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040032 )
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040033 ret.beforeStart = func() {
34 st.infoListener("dodo is driven by GitOps, changes are committed to the repository before updating an environment. This unlocks functionalities such as: rolling back to old working state, migrating dodo to new infrastructure (for example from Cloud to on-prem).")
35 }
36 return ret
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040037}
38
gioe72b54f2024-04-22 10:44:41 +040039func NewCreateConfigRepoTask(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040040 t := newLeafTask("Install Git server", func() error {
41 appsRepo := installer.NewInMemoryAppRepository(installer.CreateAllApps())
gio3cdee592024-04-17 10:15:56 +040042 app, err := installer.FindInfraApp(appsRepo, "config-repo")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040043 if err != nil {
44 return err
45 }
gioe72b54f2024-04-22 10:44:41 +040046 adminKeys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-admin-keys", env.Id))
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040047 if err != nil {
48 return err
49 }
gio3cdee592024-04-17 10:15:56 +040050 st.ssAdminKeys = adminKeys
gioe72b54f2024-04-22 10:44:41 +040051 keys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-keys", env.Id))
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040052 if err != nil {
53 return err
54 }
gioe72b54f2024-04-22 10:44:41 +040055 appDir := filepath.Join("/environments", env.Id, "config-repo")
gio778577f2024-04-29 09:44:38 +040056 _, err = st.infraAppManager.Install(app, appDir, env.Id, map[string]any{
gio3cdee592024-04-17 10:15:56 +040057 "privateKey": string(keys.RawPrivateKey()),
58 "publicKey": string(keys.RawAuthorizedKey()),
59 "adminKey": string(adminKeys.RawAuthorizedKey()),
60 })
gio778577f2024-04-29 09:44:38 +040061 return err
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040062 })
63 return &t
64}
65
gioe72b54f2024-04-22 10:44:41 +040066func CreateGitClientTask(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040067 t := newLeafTask("Wait git server to come up", func() error {
gioe72b54f2024-04-22 10:44:41 +040068 ssClient, err := st.repoClient.Get(
69 fmt.Sprintf("soft-serve.%s.svc.cluster.local:%d", env.Id, 22),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040070 st.ssAdminKeys.RawPrivateKey(),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040071 log.Default())
72 if err != nil {
73 return err
74 }
75 if err := ssClient.AddPublicKey("admin", env.AdminPublicKey); err != nil {
76 return err
77 }
78 // // TODO(gio): defer?
79 // // TODO(gio): remove at the end of final task cleanup
80 // if err := ssClient.RemovePublicKey("admin", string(ssAdminKeys.RawAuthorizedKey())); err != nil {
81 // t.callDoneListeners(err)
82 // return
83 // }
84 st.ssClient = ssClient
85 return nil
86 })
87 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040088}
89
gioe72b54f2024-04-22 10:44:41 +040090func NewInitConfigRepoTask(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040091 t := newLeafTask("Configure access control lists", func() error {
gioe72b54f2024-04-22 10:44:41 +040092 st.fluxUserName = fmt.Sprintf("flux-%s", env.Id)
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040093 keys, err := installer.NewSSHKeyPair(st.fluxUserName)
94 if err != nil {
95 return err
96 }
97 st.keys = keys
98 if err := st.ssClient.AddRepository("config"); err != nil {
99 return err
100 }
gioe72b54f2024-04-22 10:44:41 +0400101 repoIO, err := st.ssClient.GetRepo("config")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400102 if err != nil {
103 return err
104 }
giob4a3a192024-08-19 09:55:47 +0400105 if _, err := repoIO.Do(func(r soft.RepoFS) (string, error) {
gio3af43942024-04-16 08:13:50 +0400106 w, err := r.Writer("README.md")
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400107 if err != nil {
gio3af43942024-04-16 08:13:50 +0400108 return "", err
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400109 }
110 defer w.Close()
gioe72b54f2024-04-22 10:44:41 +0400111 if _, err := fmt.Fprintf(w, "# %s PCloud environment", env.Id); err != nil {
gio3af43942024-04-16 08:13:50 +0400112 return "", err
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400113 }
gioe72b54f2024-04-22 10:44:41 +0400114 if err := soft.WriteYaml(r, "kustomization.yaml", io.NewKustomization()); err != nil {
gio3af43942024-04-16 08:13:50 +0400115 return "", err
116 }
117 return "init", nil
118 }); err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400119 return err
120 }
121 if err := st.ssClient.AddUser(st.fluxUserName, keys.AuthorizedKey()); err != nil {
122 return err
123 }
124 if err := st.ssClient.AddReadOnlyCollaborator("config", st.fluxUserName); err != nil {
125 return err
126 }
127 return nil
128 })
129 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400130}