installer: split up new env creation into chain of tasks
diff --git a/core/installer/tasks/init.go b/core/installer/tasks/init.go
new file mode 100644
index 0000000..1e4ada4
--- /dev/null
+++ b/core/installer/tasks/init.go
@@ -0,0 +1,142 @@
+package tasks
+
+import (
+ "fmt"
+ "log"
+ "path/filepath"
+
+ "github.com/giolekva/pcloud/core/installer"
+ "github.com/giolekva/pcloud/core/installer/soft"
+)
+
+type createConfigRepoTask struct {
+ basicTask
+ env Env
+ st *state
+}
+
+func NewCreateConfigRepoTask(env Env, st *state) Task {
+ return &createConfigRepoTask{
+ basicTask: basicTask{
+ title: "Install Git server",
+ },
+ env: env,
+ st: st,
+ }
+}
+
+func (t *createConfigRepoTask) Start() {
+ appsRepo := installer.NewInMemoryAppRepository(installer.CreateAllApps())
+ ssApp, err := appsRepo.Find("soft-serve")
+ if err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ ssAdminKeys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-admin-keys", t.env.Name))
+ if err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ ssKeys, err := installer.NewSSHKeyPair(fmt.Sprintf("%s-config-repo-keys", t.env.Name))
+ if err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ ssValues := map[string]any{
+ "ChartRepositoryNamespace": t.env.PCloudEnvName,
+ "ServiceType": "ClusterIP",
+ "PrivateKey": string(ssKeys.RawPrivateKey()),
+ "PublicKey": string(ssKeys.RawAuthorizedKey()),
+ "AdminKey": string(ssAdminKeys.RawAuthorizedKey()),
+ "Ingress": map[string]any{
+ "Enabled": false,
+ },
+ }
+ derived := installer.Derived{
+ Global: installer.Values{
+ Id: t.env.Name,
+ PCloudEnvName: t.env.PCloudEnvName,
+ },
+ Release: installer.Release{
+ Namespace: t.env.Name,
+ },
+ Values: ssValues,
+ }
+ if err := t.st.nsCreator.Create(t.env.Name); err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ if err := t.st.repo.InstallApp(*ssApp, filepath.Join("/environments", t.env.Name, "config-repo"), ssValues, derived); err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ ssClient, err := soft.WaitForClient(
+ fmt.Sprintf("soft-serve.%s.svc.cluster.local:%d", t.env.Name, 22),
+ ssAdminKeys.RawPrivateKey(),
+ log.Default())
+ if err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ if err := ssClient.AddPublicKey("admin", t.env.AdminPublicKey); err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ // // TODO(gio): defer?
+ // // TODO(gio): remove at the end of final task cleanup
+ // if err := ssClient.RemovePublicKey("admin", string(ssAdminKeys.RawAuthorizedKey())); err != nil {
+ // t.callDoneListeners(err)
+ // return
+ // }
+ t.st.ssClient = ssClient
+ t.callDoneListeners(nil)
+}
+
+type initConfigRepoTask struct {
+ basicTask
+ env Env
+ st *state
+}
+
+func NewInitConfigRepoTask(env Env, st *state) Task {
+ return &initConfigRepoTask{
+ basicTask: basicTask{
+ title: "Create Git repository for environment configuration",
+ },
+ env: env,
+ st: st,
+ }
+}
+
+func (t *initConfigRepoTask) Start() {
+ t.st.fluxUserName = fmt.Sprintf("flux-%s", t.env.Name)
+ keys, err := installer.NewSSHKeyPair(t.st.fluxUserName)
+ if err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ t.st.keys = keys
+ if err := t.st.ssClient.AddRepository("config"); err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ repo, err := t.st.ssClient.GetRepo("config")
+ if err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ repoIO := installer.NewRepoIO(repo, t.st.ssClient.Signer)
+ if err := repoIO.WriteCommitAndPush("README.md", fmt.Sprintf("# %s PCloud environment", t.env.Name), "readme"); err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ if err := t.st.ssClient.AddUser(t.st.fluxUserName, keys.AuthorizedKey()); err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ if err := t.st.ssClient.AddReadOnlyCollaborator("config", t.st.fluxUserName); err != nil {
+ t.callDoneListeners(err)
+ return
+ }
+ t.callDoneListeners(nil)
+}