2023-07-20 09:26:25 +00:00
|
|
|
package controller
|
|
|
|
|
|
|
|
import (
|
2024-07-25 16:44:58 +00:00
|
|
|
"context"
|
2023-07-20 09:26:25 +00:00
|
|
|
"fmt"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/providers"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/diff"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/githelper"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/helmhelper"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/kustomize"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/sopshelper"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/workdir"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/pkg/config"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/pkg/lockfile"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/pkg/release"
|
2024-07-26 07:04:03 +00:00
|
|
|
"github.com/go-logr/logr"
|
2023-07-20 09:26:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func ReadTheConfig(path string) (*config.Config, error) {
|
|
|
|
conf, err := config.NewConfigFromFile(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return conf, nil
|
|
|
|
}
|
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
type SyncOptions struct {
|
|
|
|
Workdir string
|
|
|
|
SSHKey string
|
|
|
|
Dry bool
|
|
|
|
Config *config.Config
|
|
|
|
SopsBin string
|
|
|
|
}
|
2023-07-20 09:26:25 +00:00
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
type SyncController struct{}
|
2023-07-20 09:26:25 +00:00
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
func Sync(ctx context.Context, opts *SyncOptions) error {
|
2024-07-26 07:04:03 +00:00
|
|
|
log, err := logr.FromContext(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
// Start by creating a directory where everything should be happening
|
|
|
|
configPath := filepath.Dir(opts.Config.ConfigPath)
|
2023-07-20 09:26:25 +00:00
|
|
|
// Prepare helm repositories
|
2024-07-25 16:44:58 +00:00
|
|
|
for _, repository := range opts.Config.Repositories {
|
2023-07-20 09:26:25 +00:00
|
|
|
if err := repository.KindFromUrl(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Configure a git client
|
2024-07-25 16:44:58 +00:00
|
|
|
gh := githelper.NewGit(opts.SSHKey)
|
2023-07-20 09:26:25 +00:00
|
|
|
// if len(diffArg) > 0 {
|
2024-07-25 16:44:58 +00:00
|
|
|
// snapshotDir := fmt.Sprint("%s/.snapshot", workdirPath)
|
|
|
|
// cloneSnapshoot(gh, snapshotDir, diffArg)
|
2023-07-20 09:26:25 +00:00
|
|
|
// }
|
|
|
|
|
|
|
|
// The main logic starts here
|
2024-07-25 16:44:58 +00:00
|
|
|
for _, cluster := range opts.Config.Clusters {
|
2023-07-20 09:26:25 +00:00
|
|
|
// Create a dir for the cluster git repo
|
2024-07-25 16:44:58 +00:00
|
|
|
clusterWorkdirPath := fmt.Sprintf("%s/%s", opts.Workdir, cluster.Name)
|
2023-07-20 09:26:25 +00:00
|
|
|
|
|
|
|
// Init a gitops provider (Currently onle flux is supported)
|
2024-07-25 16:44:58 +00:00
|
|
|
provider, err := providers.NewProvider(cluster.Provider, clusterWorkdirPath, opts.SopsBin, gh)
|
2023-07-20 09:26:25 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
if err := cluster.CloneRepo(gh, clusterWorkdirPath, opts.Dry); err != nil {
|
2023-07-20 09:26:25 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
if err := cluster.BootstrapRepo(gh, clusterWorkdirPath, opts.Dry); err != nil {
|
2023-07-20 09:26:25 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the lockfile generated by the shoebill
|
|
|
|
lockfileData, err := lockfile.NewFromFile(clusterWorkdirPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
currentRepositories, err := lockfileData.ReposFromLockfile()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
if err := opts.Config.Releases.PopulateRepositories(opts.Config.Repositories); err != nil {
|
2023-07-20 09:26:25 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init the helm client
|
|
|
|
hh := helmhelper.NewHelm()
|
|
|
|
|
|
|
|
// Init the sops client
|
|
|
|
sops := sopshelper.NewSops()
|
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
for _, release := range opts.Config.Releases {
|
|
|
|
err := release.VersionHandler(opts.Workdir, hh)
|
2023-07-20 09:26:25 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := release.ValuesHandler(configPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := release.SecretsHandler(configPath, sops); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-25 16:44:58 +00:00
|
|
|
releaseObj := release.FindReleaseByNames(cluster.Releases, opts.Config.Releases)
|
2023-07-20 09:26:25 +00:00
|
|
|
cluster.PopulateReleases(releaseObj)
|
2024-07-26 07:04:03 +00:00
|
|
|
for _, oneRelease := range releaseObj {
|
|
|
|
log.Info("Pullin a helm chart to the git repo", "chart", oneRelease.Chart)
|
|
|
|
if _, err := hh.PullChart(clusterWorkdirPath, oneRelease.ToHelmReleaseData()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2024-07-25 16:44:58 +00:00
|
|
|
releasesCurrent, err := release.ReleasesFromLockfile(lockfileData, opts.Config.Repositories)
|
2023-07-20 09:26:25 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare releases from the lockfile to ones from the current cluster config
|
|
|
|
diffReleases, err := diff.DiffReleases(releasesCurrent, cluster.ReleasesObj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
lockfile, diffRepos, err := diffReleases.Resolve(currentRepositories, clusterWorkdirPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
hashesPerRelease, err := provider.SyncState(diffReleases, diffRepos)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := kustomize.Generate(clusterWorkdirPath, gh); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
lockfile.AddHashes(hashesPerRelease)
|
|
|
|
|
|
|
|
if err := lockfile.WriteToFile(clusterWorkdirPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if _, err := gh.AddAllAndCommit(clusterWorkdirPath, "Update the lockfile"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2024-07-25 16:44:58 +00:00
|
|
|
if !opts.Dry {
|
2023-07-20 09:26:25 +00:00
|
|
|
if err := gh.Push(clusterWorkdirPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2024-07-25 16:44:58 +00:00
|
|
|
if !opts.Dry {
|
|
|
|
if err := workdir.RemoveWorkdir(opts.Workdir); err != nil {
|
2023-07-20 09:26:25 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|