blob: 4ed71762cb0128eaae3dc6630e4bcfeef543f9cf [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 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040054 derived := installer.Derived{
55 Global: installer.Values{
56 Id: env.Name,
57 PCloudEnvName: env.PCloudEnvName,
58 },
gio3af43942024-04-16 08:13:50 +040059 Values: map[string]any{
60 "privateKey": string(ssKeys.RawPrivateKey()),
61 "publicKey": string(ssKeys.RawAuthorizedKey()),
62 "adminKey": string(ssAdminKeys.RawAuthorizedKey()),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040063 },
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040064 }
gio3af43942024-04-16 08:13:50 +040065 return installer.InstallApp(st.repo, st.nsCreator, ssApp, filepath.Join("/environments", env.Name, "config-repo"), env.Name, derived.Values, derived)
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040066 })
67 return &t
68}
69
70func CreateGitClientTask(env Env, st *state) Task {
71 t := newLeafTask("Wait git server to come up", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040072 ssClient, err := soft.WaitForClient(
73 fmt.Sprintf("soft-serve.%s.svc.cluster.local:%d", env.Name, 22),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040074 st.ssAdminKeys.RawPrivateKey(),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040075 log.Default())
76 if err != nil {
77 return err
78 }
79 if err := ssClient.AddPublicKey("admin", env.AdminPublicKey); err != nil {
80 return err
81 }
82 // // TODO(gio): defer?
83 // // TODO(gio): remove at the end of final task cleanup
84 // if err := ssClient.RemovePublicKey("admin", string(ssAdminKeys.RawAuthorizedKey())); err != nil {
85 // t.callDoneListeners(err)
86 // return
87 // }
88 st.ssClient = ssClient
89 return nil
90 })
91 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040092}
93
94func NewInitConfigRepoTask(env Env, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040095 t := newLeafTask("Configure access control lists", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040096 st.fluxUserName = fmt.Sprintf("flux-%s", env.Name)
97 keys, err := installer.NewSSHKeyPair(st.fluxUserName)
98 if err != nil {
99 return err
100 }
101 st.keys = keys
102 if err := st.ssClient.AddRepository("config"); err != nil {
103 return err
104 }
105 repo, err := st.ssClient.GetRepo("config")
106 if err != nil {
107 return err
108 }
gio3af43942024-04-16 08:13:50 +0400109 repoIO, err := installer.NewRepoIO(repo, st.ssClient.Signer)
110 if err != nil {
111 return err
112 }
113 if err := repoIO.Atomic(func(r installer.RepoFS) (string, error) {
114 w, err := r.Writer("README.md")
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400115 if err != nil {
gio3af43942024-04-16 08:13:50 +0400116 return "", err
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400117 }
118 defer w.Close()
119 if _, err := fmt.Fprintf(w, "# %s PCloud environment", env.Name); err != nil {
gio3af43942024-04-16 08:13:50 +0400120 return "", err
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400121 }
gio3af43942024-04-16 08:13:50 +0400122 if err := installer.WriteYaml(r, "kustomization.yaml", installer.NewKustomization()); err != nil {
123 return "", err
124 }
125 return "init", nil
126 }); err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400127 return err
128 }
129 if err := st.ssClient.AddUser(st.fluxUserName, keys.AuthorizedKey()); err != nil {
130 return err
131 }
132 if err := st.ssClient.AddReadOnlyCollaborator("config", st.fluxUserName); err != nil {
133 return err
134 }
135 return nil
136 })
137 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400138}