env-manager: ui polish (#127)
* env-manager: migrate to pico 2.0.6
* env: option to hide children from ui
* introduce template hierarchy
* style: improve menu styling
* env: reorganize tasks, pull before install
---------
Co-authored-by: Giorgi Lekveishvili <lekva@gl-mbp-m1-max.local>
diff --git a/core/installer/tasks/activate.go b/core/installer/tasks/activate.go
index 0980dee..1333f28 100644
--- a/core/installer/tasks/activate.go
+++ b/core/installer/tasks/activate.go
@@ -13,15 +13,10 @@
//go:embed env-tmpl
var filesTmpls embed.FS
-type activateEnvTask struct {
- basicTask
- env Env
- st *state
-}
-
func NewActivateEnvTask(env Env, st *state) Task {
return newSequentialParentTask(
- fmt.Sprintf("Activate new %s instance", env.PCloudEnvName),
+ "Activate GitOps",
+ false,
AddNewEnvTask(env, st),
// TODO(gio): sync dodo-flux
)
diff --git a/core/installer/tasks/dns.go b/core/installer/tasks/dns.go
index 0880782..25af486 100644
--- a/core/installer/tasks/dns.go
+++ b/core/installer/tasks/dns.go
@@ -16,7 +16,8 @@
func SetupZoneTask(env Env, ingressIP net.IP, st *state) Task {
return newSequentialParentTask(
- fmt.Sprintf("Setup DNS zone records for %s", env.Domain),
+ "Configure DNS",
+ true,
CreateZoneRecords(env.Domain, st.publicIPs, ingressIP, env, st),
WaitToPropagate(env.Domain, st.publicIPs),
)
@@ -29,7 +30,7 @@
env Env,
st *state,
) Task {
- t := newLeafTask("Configure DNS", func() error {
+ t := newLeafTask("Generate and publish DNS records", func() error {
repo, err := st.ssClient.GetRepo("config")
if err != nil {
return err
@@ -90,12 +91,17 @@
}); err != nil {
return err
}
- rootKust := installer.NewKustomization()
- rootKust.AddResources("dns-zone.yaml")
- if err := r.WriteKustomization("kustomization.yaml", rootKust); err != nil {
+ rootKust, err := r.ReadKustomization("kustomization.yaml")
+ if err != nil {
return err
}
- r.CommitAndPush("configure dns zone")
+ rootKust.AddResources("dns-zone.yaml")
+ if err := r.WriteKustomization("kustomization.yaml", *rootKust); err != nil {
+ return err
+ }
+ if err := r.CommitAndPush("configure dns zone"); err != nil {
+ return err
+ }
}
return nil
})
@@ -106,7 +112,7 @@
name string,
expected []net.IP,
) Task {
- t := newLeafTask("Propagate DNS records", func() error {
+ t := newLeafTask("Wait to propagate", func() error {
ctx := context.TODO()
gotExpectedIPs := func(actual []net.IP) bool {
for _, a := range actual {
diff --git a/core/installer/tasks/env.go b/core/installer/tasks/env.go
index eb537da..80289c4 100644
--- a/core/installer/tasks/env.go
+++ b/core/installer/tasks/env.go
@@ -52,14 +52,10 @@
}
t := newSequentialParentTask(
"Create env",
- append(
- []Task{
- SetupConfigRepoTask(env, &st),
- NewActivateEnvTask(env, &st),
- SetupZoneTask(env, startIP, &st),
- },
- SetupInfra(env, startIP, &st)...,
- )...,
+ true,
+ SetupConfigRepoTask(env, &st),
+ SetupZoneTask(env, startIP, &st),
+ SetupInfra(env, startIP, &st),
)
rctx, done := context.WithCancel(context.Background())
t.OnDone(func(_ error) {
diff --git a/core/installer/tasks/infra.go b/core/installer/tasks/infra.go
index 0216f84..0685a6d 100644
--- a/core/installer/tasks/infra.go
+++ b/core/installer/tasks/infra.go
@@ -13,8 +13,8 @@
var initGroups = []string{"admin"}
-func SetupInfra(env Env, startIP net.IP, st *state) []Task {
- t := newLeafTask("Create client", func() error {
+func CreateRepoClient(env Env, st *state) Task {
+ t := newLeafTask("Create repo client", func() error {
repo, err := st.ssClient.GetRepo("config")
if err != nil {
return err
@@ -30,25 +30,25 @@
st.emptySuffixGen = installer.NewEmptySuffixGenerator()
return nil
})
- return []Task{
- CommitEnvironmentConfiguration(env, st),
- ConfigureFirstAccount(env, st),
- &t,
- newConcurrentParentTask(
- "Core services",
- SetupNetwork(env, startIP, st),
- SetupCertificateIssuers(env, st),
- SetupAuth(env, st),
- SetupGroupMemberships(env, st),
- SetupHeadscale(env, startIP, st),
- SetupWelcome(env, st),
- SetupAppStore(env, st),
- ),
- }
+ return &t
+}
+
+func SetupInfra(env Env, startIP net.IP, st *state) Task {
+ return newConcurrentParentTask(
+ "Setup core services",
+ true,
+ SetupNetwork(env, startIP, st),
+ SetupCertificateIssuers(env, st),
+ SetupAuth(env, st),
+ SetupGroupMemberships(env, st),
+ SetupHeadscale(env, startIP, st),
+ SetupWelcome(env, st),
+ SetupAppStore(env, st),
+ )
}
func CommitEnvironmentConfiguration(env Env, st *state) Task {
- t := newLeafTask("Configure environment infrastructure", func() error {
+ t := newLeafTask("commit config", func() error {
repo, err := st.ssClient.GetRepo("config")
if err != nil {
return err
@@ -129,7 +129,7 @@
}
func SetupNetwork(env Env, startIP net.IP, st *state) Task {
- t := newLeafTask("Setup network", func() error {
+ t := newLeafTask("Setup private and public networks", func() error {
startAddr, err := netip.ParseAddr(startIP.String())
if err != nil {
return err
@@ -232,7 +232,7 @@
}
return nil
})
- return newSequentialParentTask("Configure TLS certificate issuers", &pub, &priv)
+ return newSequentialParentTask("Configure TLS certificate issuers", false, &pub, &priv)
}
func SetupAuth(env Env, st *state) Task {
@@ -250,6 +250,7 @@
})
return newSequentialParentTask(
"Authentication services",
+ false,
&t,
waitForAddr(fmt.Sprintf("https://accounts-ui.%s", env.Domain)),
)
@@ -269,7 +270,8 @@
return nil
})
return newSequentialParentTask(
- "Group Membership",
+ "Group membership",
+ false,
&t,
waitForAddr(fmt.Sprintf("https://memberships.p.%s", env.Domain)),
)
@@ -290,7 +292,8 @@
return nil
})
return newSequentialParentTask(
- "Headscale service",
+ "Setup mesh VPN",
+ false,
&t,
waitForAddr(fmt.Sprintf("https://headscale.%s/apple", env.Domain)),
)
@@ -323,6 +326,7 @@
})
return newSequentialParentTask(
"Welcome service",
+ false,
&t,
waitForAddr(fmt.Sprintf("https://welcome.%s", env.Domain)),
)
diff --git a/core/installer/tasks/init.go b/core/installer/tasks/init.go
index f898a1f..e6dd47e 100644
--- a/core/installer/tasks/init.go
+++ b/core/installer/tasks/init.go
@@ -11,10 +11,23 @@
func SetupConfigRepoTask(env Env, st *state) Task {
return newSequentialParentTask(
- "Configuration repository",
- NewCreateConfigRepoTask(env, st),
- CreateGitClientTask(env, st),
+ "Configure Git repository for new environment",
+ true,
+ newSequentialParentTask(
+ "Start up Git server",
+ false,
+ NewCreateConfigRepoTask(env, st),
+ CreateGitClientTask(env, st),
+ ),
NewInitConfigRepoTask(env, st),
+ NewActivateEnvTask(env, st),
+ newSequentialParentTask(
+ "Create initial commit",
+ false,
+ CreateRepoClient(env, st),
+ CommitEnvironmentConfiguration(env, st),
+ ConfigureFirstAccount(env, st),
+ ),
)
}
@@ -85,7 +98,7 @@
}
func NewInitConfigRepoTask(env Env, st *state) Task {
- t := newLeafTask("Create Git repository for environment configuration", func() error {
+ t := newLeafTask("Configure access control lists", func() error {
st.fluxUserName = fmt.Sprintf("flux-%s", env.Name)
keys, err := installer.NewSSHKeyPair(st.fluxUserName)
if err != nil {
@@ -100,7 +113,23 @@
return err
}
repoIO := installer.NewRepoIO(repo, st.ssClient.Signer)
- if err := repoIO.WriteCommitAndPush("README.md", fmt.Sprintf("# %s PCloud environment", env.Name), "readme"); err != nil {
+ if err := func() error {
+ w, err := repoIO.Writer("README.md")
+ if err != nil {
+ return err
+ }
+ defer w.Close()
+ if _, err := fmt.Fprintf(w, "# %s PCloud environment", env.Name); err != nil {
+ return err
+ }
+ return nil
+ }(); err != nil {
+ return err
+ }
+ if err := repoIO.WriteKustomization("kustomization.yaml", installer.NewKustomization()); err != nil {
+ return err
+ }
+ if err := repoIO.CommitAndPush("init"); err != nil {
return err
}
if err := st.ssClient.AddUser(st.fluxUserName, keys.AuthorizedKey()); err != nil {
diff --git a/core/installer/tasks/tasks.go b/core/installer/tasks/tasks.go
index 75e8a68..6d0ec01 100644
--- a/core/installer/tasks/tasks.go
+++ b/core/installer/tasks/tasks.go
@@ -86,25 +86,31 @@
type parentTask struct {
leafTask
- subtasks []Task
+ subtasks []Task
+ showChildren bool
}
-func newParentTask(title string, start func() error, subtasks ...Task) parentTask {
+func newParentTask(title string, showChildren bool, start func() error, subtasks ...Task) parentTask {
return parentTask{
- leafTask: newLeafTask(title, start),
- subtasks: subtasks,
+ leafTask: newLeafTask(title, start),
+ subtasks: subtasks,
+ showChildren: showChildren,
}
}
func (t *parentTask) Subtasks() []Task {
- return t.subtasks
+ if t.showChildren {
+ return t.subtasks
+ } else {
+ return make([]Task, 0)
+ }
}
type sequentialParentTask struct {
parentTask
}
-func newSequentialParentTask(title string, subtasks ...Task) *sequentialParentTask {
+func newSequentialParentTask(title string, showChildren bool, subtasks ...Task) *sequentialParentTask {
start := func() error {
errCh := make(chan error)
for i := range subtasks[:len(subtasks)-1] {
@@ -124,7 +130,7 @@
return <-errCh
}
return &sequentialParentTask{
- parentTask: newParentTask(title, start, subtasks...),
+ parentTask: newParentTask(title, showChildren, start, subtasks...),
}
}
@@ -132,7 +138,7 @@
parentTask
}
-func newConcurrentParentTask(title string, subtasks ...Task) *concurrentParentTask {
+func newConcurrentParentTask(title string, showChildren bool, subtasks ...Task) *concurrentParentTask {
start := func() error {
errCh := make(chan error)
for i := range subtasks {
@@ -151,6 +157,6 @@
return nil
}
return &concurrentParentTask{
- parentTask: newParentTask(title, start, subtasks...),
+ parentTask: newParentTask(title, showChildren, start, subtasks...),
}
}
diff --git a/core/installer/tasks/tasks_test.go b/core/installer/tasks/tasks_test.go
index 7aa78f3..194be44 100644
--- a/core/installer/tasks/tasks_test.go
+++ b/core/installer/tasks/tasks_test.go
@@ -27,7 +27,7 @@
two := newLeafTask("two", func() error {
return nil
})
- l := newSequentialParentTask("parent", &one, &two)
+ l := newSequentialParentTask("parent", true, &one, &two)
done := make(chan error)
l.OnDone(func(err error) {
done <- err
@@ -46,7 +46,7 @@
two := newLeafTask("two", func() error {
return nil
})
- l := newSequentialParentTask("parent", &one, &two)
+ l := newSequentialParentTask("parent", true, &one, &two)
done := make(chan error)
l.OnDone(func(err error) {
done <- err
@@ -67,7 +67,7 @@
fmt.Println("two")
return fmt.Errorf("two")
})
- l := newSequentialParentTask("parent", &one, &two)
+ l := newSequentialParentTask("parent", true, &one, &two)
done := make(chan error)
l.OnDone(func(err error) {
done <- err