installer: configure pcloud repo during bootstrap
diff --git a/core/installer/app_manager.go b/core/installer/app_manager.go
index 53f1248..6bf0161 100644
--- a/core/installer/app_manager.go
+++ b/core/installer/app_manager.go
@@ -122,7 +122,7 @@
if err := t.Execute(out, all); err != nil {
return err
}
- appKust.Resources = append(appKust.Resources, t.Name())
+ appKust.AddResources(t.Name())
}
{
out, err := appRoot.Create(configFileName)
@@ -147,7 +147,7 @@
return err
}
if !slices.Contains(rootKust.Resources, app.Name) {
- rootKust.Resources = append(rootKust.Resources, app.Name)
+ rootKust.AddResources(app.Name)
rootKustFW, err := appsRoot.Create(kustomizationFileName)
if err != nil {
return err
diff --git a/core/installer/cmd/bootstrap.go b/core/installer/cmd/bootstrap.go
index 9d99e17..e5f3f2b 100644
--- a/core/installer/cmd/bootstrap.go
+++ b/core/installer/cmd/bootstrap.go
@@ -12,12 +12,13 @@
"path/filepath"
"time"
- "github.com/giolekva/pcloud/core/installer"
- "github.com/giolekva/pcloud/core/installer/soft"
"github.com/spf13/cobra"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/kube"
+
+ "github.com/giolekva/pcloud/core/installer"
+ "github.com/giolekva/pcloud/core/installer/soft"
)
var bootstrapFlags struct {
@@ -78,10 +79,6 @@
if err != nil {
return err
}
- fluxPub, fluxPriv, err := installer.GenerateSSHKeys()
- if err != nil {
- return err
- }
softServePub, softServePriv, err := installer.GenerateSSHKeys()
if err != nil {
return err
@@ -92,7 +89,7 @@
if err := installMetallb(); err != nil {
return err
}
- time.Sleep(3 * time.Minute)
+ time.Sleep(1 * time.Minute)
if err := installMetallbConfig(); err != nil {
return err
}
@@ -104,7 +101,11 @@
return err
}
time.Sleep(2 * time.Minute)
- ss, err := soft.NewClient(bootstrapFlags.softServeIP, 2222, adminPrivKey, log.Default())
+ ss, err := soft.NewClient(bootstrapFlags.softServeIP, 22, adminPrivKey, log.Default())
+ if err != nil {
+ return err
+ }
+ fluxPub, fluxPriv, err := installer.GenerateSSHKeys()
if err != nil {
return err
}
@@ -122,6 +123,13 @@
if err := installFlux("ssh://soft-serve.pcloud.svc.cluster.local:22/pcloud", "soft-serve.pcloud.svc.cluster.local", softServePub, fluxPriv); err != nil {
return err
}
+ pcloudRepo, err := ss.GetRepo("pcloud") // TODO(giolekva): configurable
+ if err != nil {
+ return err
+ }
+ if err := configurePCloudRepo(installer.NewRepoIO(pcloudRepo, ss.Signer)); err != nil {
+ return err
+ }
// TODO(giolekva): everything below must be installed using Flux
if err := installIngressPublic(); err != nil {
return err
@@ -132,6 +140,7 @@
if err := installCertManagerWebhookGandi(); err != nil {
return err
}
+ // TODO(giolekva): ideally should be installed automatically if any of the user installed apps requires it
if err := installSmbDriver(); err != nil {
return err
}
@@ -162,6 +171,7 @@
installer.Namespace = "pcloud"
installer.ReleaseName = "metallb-ns"
installer.Wait = true
+ installer.WaitForJobs = true
if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
return err
}
@@ -202,7 +212,8 @@
installer.CreateNamespace = true
installer.ReleaseName = "metallb"
installer.IncludeCRDs = true
- // installer.Wait = true
+ installer.Wait = true
+ installer.WaitForJobs = true
installer.Timeout = 20 * time.Minute
if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
return err
@@ -230,6 +241,7 @@
installer.CreateNamespace = true
installer.ReleaseName = "metallb-cfg"
installer.Wait = true
+ installer.WaitForJobs = true
installer.Timeout = 20 * time.Minute
if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
return err
@@ -268,6 +280,7 @@
installer.CreateNamespace = true
installer.ReleaseName = "longhorn"
installer.Wait = true
+ installer.WaitForJobs = true
installer.Timeout = 20 * time.Minute
if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
return err
@@ -296,6 +309,7 @@
installer.CreateNamespace = true
installer.ReleaseName = "soft-serve"
installer.Wait = true
+ installer.WaitForJobs = true
installer.Timeout = 20 * time.Minute
if _, err := installer.RunWithContext(context.TODO(), chart, values); err != nil {
return err
@@ -465,6 +479,18 @@
return nil
}
+func configurePCloudRepo(repo installer.RepoIO) error {
+ kust := installer.NewKustomization()
+ kust.AddResources("pcloud-flux", "environments")
+ if err := repo.WriteKustomization("kustomization.yaml", kust); err != nil {
+ return err
+ }
+ if err := repo.WriteKustomization("environments/kustomization.yaml", installer.NewKustomization()); err != nil {
+ return err
+ }
+ return repo.CommitAndPush("initialize pcloud directory structure, environments with kustomization.yaml-s")
+}
+
func createActionConfig(namespace string) (*action.Configuration, error) {
config := new(action.Configuration)
if err := config.Init(
diff --git a/core/installer/cmd/env.go b/core/installer/cmd/env.go
index 1ae0888..4b258b1 100644
--- a/core/installer/cmd/env.go
+++ b/core/installer/cmd/env.go
@@ -126,7 +126,7 @@
return err
}
}
- kust.Resources = append(kust.Resources, createEnvFlags.name)
+ kust.AddResources(createEnvFlags.name)
ff, err := wt.Filesystem.Create(envKust)
if err != nil {
return err
diff --git a/core/installer/kustomization.go b/core/installer/kustomization.go
index 8b96668..f5f42e5 100644
--- a/core/installer/kustomization.go
+++ b/core/installer/kustomization.go
@@ -44,3 +44,7 @@
}
return nil
}
+
+func (k *Kustomization) AddResources(names ...string) {
+ k.Resources = append(k.Resources, names...)
+}
diff --git a/core/installer/repoio.go b/core/installer/repoio.go
new file mode 100644
index 0000000..271a1c4
--- /dev/null
+++ b/core/installer/repoio.go
@@ -0,0 +1,80 @@
+package installer
+
+import (
+ "io/fs"
+ "path/filepath"
+ "time"
+
+ "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing/object"
+ "golang.org/x/crypto/ssh"
+)
+
+type RepoIO interface {
+ ReadKustomization(path string) (*Kustomization, error)
+ WriteKustomization(path string, kust Kustomization) error
+ CommitAndPush(message string) error
+}
+
+type repoIO struct {
+ repo *git.Repository
+ signer ssh.Signer
+}
+
+func NewRepoIO(repo *git.Repository, signer ssh.Signer) RepoIO {
+ return &repoIO{
+ repo,
+ signer,
+ }
+}
+
+func (r *repoIO) ReadKustomization(path string) (*Kustomization, error) {
+ wt, err := r.repo.Worktree()
+ if err != nil {
+ return nil, err
+ }
+ inp, err := wt.Filesystem.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer inp.Close()
+ return ReadKustomization(inp)
+}
+
+func (r *repoIO) WriteKustomization(path string, kust Kustomization) error {
+ wt, err := r.repo.Worktree()
+ if err != nil {
+ return err
+ }
+ if err := wt.Filesystem.MkdirAll(filepath.Dir(path), fs.ModePerm); err != nil {
+ return err
+ }
+ out, err := wt.Filesystem.Create(path)
+ if err != nil {
+ return err
+ }
+ defer out.Close()
+ return kust.Write(out)
+}
+
+func (r *repoIO) CommitAndPush(message string) error {
+ wt, err := r.repo.Worktree()
+ if err != nil {
+ return err
+ }
+ if err := wt.AddGlob("*"); err != nil {
+ return err
+ }
+ if _, err := wt.Commit(message, &git.CommitOptions{
+ Author: &object.Signature{
+ Name: "pcloud-installer",
+ When: time.Now(),
+ },
+ }); err != nil {
+ return err
+ }
+ return r.repo.Push(&git.PushOptions{
+ RemoteName: "soft", // TODO(giolekva): configurable
+ Auth: auth(r.signer),
+ })
+}
diff --git a/core/installer/soft/client.go b/core/installer/soft/client.go
index 01d79c7..68964d3 100644
--- a/core/installer/soft/client.go
+++ b/core/installer/soft/client.go
@@ -11,7 +11,6 @@
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
// "github.com/go-git/go-git/v5/config"
- "github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
gitssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
"github.com/go-git/go-git/v5/storage/memory"
@@ -22,7 +21,7 @@
type Client struct {
ip string
port int
- signer ssh.Signer
+ Signer ssh.Signer
log *log.Logger
}
@@ -87,18 +86,11 @@
if err != nil {
return err
}
- fmt.Println("aaaa")
- b, _ := configRepo.Branches()
- b.ForEach(func(r *plumbing.Reference) error {
- fmt.Println(r.Name())
- return nil
- })
if err = wt.Checkout(&git.CheckoutOptions{
Branch: "refs/heads/master",
}); err != nil {
return err
}
- fmt.Println("bbb")
f, err := wt.Filesystem.Open("config.yaml")
if err != nil {
return err
@@ -145,6 +137,18 @@
})
}
+func (ss *Client) GetRepo(name string) (*git.Repository, error) {
+ return git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
+ URL: fmt.Sprintf("%s/%s", ss.addressGit(), name),
+ Auth: ss.authGit(),
+ RemoteName: "soft",
+ ReferenceName: "refs/heads/master",
+ Depth: 1,
+ InsecureSkipTLS: true,
+ Progress: os.Stdout,
+ })
+}
+
func (ss *Client) repoPathByName(name string) string {
return fmt.Sprintf("%s/%s", ss.addressGit(), name)
}
@@ -191,7 +195,7 @@
func (ss *Client) authGit() *gitssh.PublicKeys {
return &gitssh.PublicKeys{
- Signer: ss.signer,
+ Signer: ss.Signer,
HostKeyCallbackHelper: gitssh.HostKeyCallbackHelper{
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
// TODO(giolekva): verify server public key
@@ -206,7 +210,7 @@
var ret []byte
config := &ssh.ClientConfig{
Auth: []ssh.AuthMethod{
- ssh.PublicKeys(ss.signer),
+ ssh.PublicKeys(ss.Signer),
},
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
ret = ssh.MarshalAuthorizedKey(key)
@@ -223,7 +227,7 @@
func (ss *Client) sshClientConfig() *ssh.ClientConfig {
return &ssh.ClientConfig{
Auth: []ssh.AuthMethod{
- ssh.PublicKeys(ss.signer),
+ ssh.PublicKeys(ss.Signer),
},
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
// TODO(giolekva): verify server public key