blob: 4e676cd9e27dc7702ab79a373834fe5bc37036d4 [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"
9 "github.com/giolekva/pcloud/core/installer/soft"
10)
11
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040012func SetupConfigRepoTask(env Env, st *state) Task {
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040013 ret := newSequentialParentTask(
14 "Configure Git repository",
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040015 true,
16 newSequentialParentTask(
17 "Start up Git server",
18 false,
19 NewCreateConfigRepoTask(env, st),
20 CreateGitClientTask(env, st),
21 ),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040022 NewInitConfigRepoTask(env, st),
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040023 NewActivateEnvTask(env, st),
24 newSequentialParentTask(
25 "Create initial commit",
26 false,
27 CreateRepoClient(env, st),
28 CommitEnvironmentConfiguration(env, st),
29 ConfigureFirstAccount(env, st),
30 ),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040031 )
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040032 ret.beforeStart = func() {
33 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).")
34 }
35 return ret
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040036}
37
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040038func NewCreateConfigRepoTask(env Env, st *state) Task {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040039 t := newLeafTask("Install Git server", func() error {
40 appsRepo := installer.NewInMemoryAppRepository(installer.CreateAllApps())
gio3cdee592024-04-17 10:15:56 +040041 app, err := installer.FindInfraApp(appsRepo, "config-repo")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040042 if err != nil {
43 return err
44 }
gio3cdee592024-04-17 10:15:56 +040045 adminKeys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-admin-keys", env.Name))
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040046 if err != nil {
47 return err
48 }
gio3cdee592024-04-17 10:15:56 +040049 st.ssAdminKeys = adminKeys
50 keys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-keys", env.Name))
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040051 if err != nil {
52 return err
53 }
gio3cdee592024-04-17 10:15:56 +040054 appDir := filepath.Join("/environments", env.Name, "config-repo")
55 return st.infraAppManager.Install(app, appDir, env.Name, map[string]any{
56 "privateKey": string(keys.RawPrivateKey()),
57 "publicKey": string(keys.RawAuthorizedKey()),
58 "adminKey": string(adminKeys.RawAuthorizedKey()),
59 })
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040060 })
61 return &t
62}
63
64func CreateGitClientTask(env Env, st *state) Task {
65 t := newLeafTask("Wait git server to come up", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040066 ssClient, err := soft.WaitForClient(
67 fmt.Sprintf("soft-serve.%s.svc.cluster.local:%d", env.Name, 22),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040068 st.ssAdminKeys.RawPrivateKey(),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040069 log.Default())
70 if err != nil {
71 return err
72 }
73 if err := ssClient.AddPublicKey("admin", env.AdminPublicKey); err != nil {
74 return err
75 }
76 // // TODO(gio): defer?
77 // // TODO(gio): remove at the end of final task cleanup
78 // if err := ssClient.RemovePublicKey("admin", string(ssAdminKeys.RawAuthorizedKey())); err != nil {
79 // t.callDoneListeners(err)
80 // return
81 // }
82 st.ssClient = ssClient
83 return nil
84 })
85 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040086}
87
88func NewInitConfigRepoTask(env Env, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040089 t := newLeafTask("Configure access control lists", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040090 st.fluxUserName = fmt.Sprintf("flux-%s", env.Name)
91 keys, err := installer.NewSSHKeyPair(st.fluxUserName)
92 if err != nil {
93 return err
94 }
95 st.keys = keys
96 if err := st.ssClient.AddRepository("config"); err != nil {
97 return err
98 }
99 repo, err := st.ssClient.GetRepo("config")
100 if err != nil {
101 return err
102 }
gio3af43942024-04-16 08:13:50 +0400103 repoIO, err := installer.NewRepoIO(repo, st.ssClient.Signer)
104 if err != nil {
105 return err
106 }
gio308105e2024-04-19 13:12:13 +0400107 if err := repoIO.Do(func(r installer.RepoFS) (string, error) {
gio3af43942024-04-16 08:13:50 +0400108 w, err := r.Writer("README.md")
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400109 if err != nil {
gio3af43942024-04-16 08:13:50 +0400110 return "", err
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400111 }
112 defer w.Close()
113 if _, err := fmt.Fprintf(w, "# %s PCloud environment", env.Name); err != nil {
gio3af43942024-04-16 08:13:50 +0400114 return "", err
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400115 }
gio3af43942024-04-16 08:13:50 +0400116 if err := installer.WriteYaml(r, "kustomization.yaml", installer.NewKustomization()); err != nil {
117 return "", err
118 }
119 return "init", nil
120 }); err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400121 return err
122 }
123 if err := st.ssClient.AddUser(st.fluxUserName, keys.AuthorizedKey()); err != nil {
124 return err
125 }
126 if err := st.ssClient.AddReadOnlyCollaborator("config", st.fluxUserName); err != nil {
127 return err
128 }
129 return nil
130 })
131 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400132}