blob: cb546c105f763c858aa1e65ce7bf6580c7263efa [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())
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040041 ssApp, err := appsRepo.Find("config-repo")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040042 if err != nil {
43 return err
44 }
45 ssAdminKeys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-admin-keys", env.Name))
46 if err != nil {
47 return err
48 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040049 st.ssAdminKeys = ssAdminKeys
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040050 ssKeys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-keys", env.Name))
51 if err != nil {
52 return err
53 }
54 ssValues := map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +040055 "privateKey": string(ssKeys.RawPrivateKey()),
56 "publicKey": string(ssKeys.RawAuthorizedKey()),
57 "adminKey": string(ssAdminKeys.RawAuthorizedKey()),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040058 }
59 derived := installer.Derived{
60 Global: installer.Values{
61 Id: env.Name,
62 PCloudEnvName: env.PCloudEnvName,
63 },
64 Release: installer.Release{
65 Namespace: env.Name,
66 },
67 Values: ssValues,
68 }
69 if err := st.nsCreator.Create(env.Name); err != nil {
70 return err
71 }
Giorgi Lekveishvili08af67a2024-01-18 08:53:05 +040072 if err := st.repo.InstallApp(ssApp, filepath.Join("/environments", env.Name, "config-repo"), ssValues, derived); err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040073 return err
74 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040075 return nil
76 })
77 return &t
78}
79
80func CreateGitClientTask(env Env, st *state) Task {
81 t := newLeafTask("Wait git server to come up", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040082 ssClient, err := soft.WaitForClient(
83 fmt.Sprintf("soft-serve.%s.svc.cluster.local:%d", env.Name, 22),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040084 st.ssAdminKeys.RawPrivateKey(),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040085 log.Default())
86 if err != nil {
87 return err
88 }
89 if err := ssClient.AddPublicKey("admin", env.AdminPublicKey); err != nil {
90 return err
91 }
92 // // TODO(gio): defer?
93 // // TODO(gio): remove at the end of final task cleanup
94 // if err := ssClient.RemovePublicKey("admin", string(ssAdminKeys.RawAuthorizedKey())); err != nil {
95 // t.callDoneListeners(err)
96 // return
97 // }
98 st.ssClient = ssClient
99 return nil
100 })
101 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400102}
103
104func NewInitConfigRepoTask(env Env, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400105 t := newLeafTask("Configure access control lists", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400106 st.fluxUserName = fmt.Sprintf("flux-%s", env.Name)
107 keys, err := installer.NewSSHKeyPair(st.fluxUserName)
108 if err != nil {
109 return err
110 }
111 st.keys = keys
112 if err := st.ssClient.AddRepository("config"); err != nil {
113 return err
114 }
115 repo, err := st.ssClient.GetRepo("config")
116 if err != nil {
117 return err
118 }
119 repoIO := installer.NewRepoIO(repo, st.ssClient.Signer)
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400120 if err := func() error {
121 w, err := repoIO.Writer("README.md")
122 if err != nil {
123 return err
124 }
125 defer w.Close()
126 if _, err := fmt.Fprintf(w, "# %s PCloud environment", env.Name); err != nil {
127 return err
128 }
129 return nil
130 }(); err != nil {
131 return err
132 }
133 if err := repoIO.WriteKustomization("kustomization.yaml", installer.NewKustomization()); err != nil {
134 return err
135 }
136 if err := repoIO.CommitAndPush("init"); err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400137 return err
138 }
139 if err := st.ssClient.AddUser(st.fluxUserName, keys.AuthorizedKey()); err != nil {
140 return err
141 }
142 if err := st.ssClient.AddReadOnlyCollaborator("config", st.fluxUserName); err != nil {
143 return err
144 }
145 return nil
146 })
147 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400148}