diff --git a/examples/one-config/giops.config.yaml b/examples/one-config/giops.config.yaml index b20da88..a083bed 100644 --- a/examples/one-config/giops.config.yaml +++ b/examples/one-config/giops.config.yaml @@ -1,26 +1,16 @@ --- repositories: - - name: jetstack - url: https://charts.jetstack.io - name: bitnami-oci url: oci://registry-1.docker.io/bitnamicharts releases: - - name: cert-manager - chart: cert-manager - repository: jetstack - version: latest - namespace: cert-manager - - name: cert-manager-2 - chart: cert-manager - repository: jetstack - version: latest - namespace: cert-manager - name: postgresql-server chart: postgresql repository: bitnami-oci namespace: postgresql-server version: latest + values: + - ./values/postgresql.yaml clusters: - name: cluster-shoebill-test @@ -28,5 +18,3 @@ clusters: provider: flux releases: - postgresql-server - - cert-manager - # - cert-manager-2 diff --git a/examples/one-config/values/postgresql.yaml b/examples/one-config/values/postgresql.yaml new file mode 100644 index 0000000..5822b22 --- /dev/null +++ b/examples/one-config/values/postgresql.yaml @@ -0,0 +1,6 @@ +--- +global: + postgresql: + auth: + username: check + password: check diff --git a/internal/config/config.go b/internal/config/config.go index 3b18262..c97b6a1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -14,6 +14,7 @@ type Config struct { Repositories repository.Repositories Releases release.Releases Clusters cluster.Clusters + ConfigPath string `yaml:"-"` } // NewConfigFromFile populates the config struct from a configuration yaml file @@ -27,5 +28,6 @@ func NewConfigFromFile(path string) (*Config, error) { if err := yaml.Unmarshal(configFile, &config); err != nil { return nil, err } + config.ConfigPath = path return &config, nil } diff --git a/internal/config/release/release.go b/internal/config/release/release.go index 41b3211..a6dc39c 100644 --- a/internal/config/release/release.go +++ b/internal/config/release/release.go @@ -3,6 +3,7 @@ package release import ( "fmt" "reflect" + "strings" "git.badhouseplants.net/allanger/shoebill/internal/config/repository" "git.badhouseplants.net/allanger/shoebill/internal/lockfile" @@ -21,6 +22,8 @@ type Release struct { Version string // Namespace to install release Namespace string + // Value files + Values []string // Private fields that should be pupulated during the run-time RepositoryObj *repository.Repository `yaml:"-"` } @@ -59,6 +62,12 @@ func (r *Release) VersionHandler(dir string, hh helmhelper.Helmhelper) error { return nil } +func (r *Release) ValuesHandler(dir string) { + for i := range r.Values { + r.Values[i] = fmt.Sprintf("%s/%s", dir, strings.ReplaceAll(r.Values[i], "./", "")) + } +} + func FindReleaseByNames(releases []string, releasesObj Releases) Releases { result := Releases{} for _, rObj := range releasesObj { diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 563f77f..2cb23b9 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -2,6 +2,7 @@ package controller import ( "fmt" + "path/filepath" "git.badhouseplants.net/allanger/shoebill/internal/config" "git.badhouseplants.net/allanger/shoebill/internal/config/release" @@ -22,15 +23,12 @@ func ReadTheConfig(path string) (*config.Config, error) { return conf, nil } -/* -* First it must prepare the workdir -* It must create a directorry and clone all the repos that are listed in the config - */ func Reconcile(workdirPath, sshKeyPath string, conf *config.Config, dry bool) error { dir, err := workdir.CreateWorkdir(workdirPath) if err != nil { return err } + // Prepare repositories for _, repository := range conf.Repositories { if err := repository.ValidateURL(); err != nil { return err @@ -39,17 +37,10 @@ func Reconcile(workdirPath, sshKeyPath string, conf *config.Config, dry bool) er return err } } + gh := githelper.NewGit(sshKeyPath) + for _, cluster := range conf.Clusters { - /* - * 1. Clone the cluster repo - * 2. Check if repo is already configured - * Yes -> Bootsrap the repo if it's not configured - * - Create the lockfile - * - ... - * No -> Get the current state - * 3. Turn the config file into the lockfile format and compare the actual to the desired - */ fullPath := fmt.Sprintf("%s/%s", dir, cluster.Name) provider, err := providers.NewProvider(cluster.Provider, fullPath, gh) if err != nil { @@ -59,10 +50,12 @@ func Reconcile(workdirPath, sshKeyPath string, conf *config.Config, dry bool) er if err := cluster.CloneRepo(gh, fullPath, dry); err != nil { return err } + err = cluster.BootstrapRepo(gh, fullPath, dry) if err != nil { return err } + lockfileData, err := lockfile.NewFromFile(fullPath) if err != nil { return err @@ -78,11 +71,13 @@ func Reconcile(workdirPath, sshKeyPath string, conf *config.Config, dry bool) er } hh := helmhelper.NewHelm() + for _, release := range conf.Releases { err := release.VersionHandler(workdirPath, hh) if err != nil { return err } + release.ValuesHandler(filepath.Dir(conf.ConfigPath)) } rsObj := release.FindReleaseByNames(cluster.Releases, conf.Releases) diff --git a/internal/providers/flux.go b/internal/providers/flux.go index 52ddcb7..ebc2c49 100644 --- a/internal/providers/flux.go +++ b/internal/providers/flux.go @@ -1,8 +1,11 @@ package providers import ( + "errors" "fmt" + "io" "os" + "path/filepath" "git.badhouseplants.net/allanger/shoebill/internal/config/release" "git.badhouseplants.net/allanger/shoebill/internal/config/repository" @@ -10,6 +13,7 @@ import ( "git.badhouseplants.net/allanger/shoebill/internal/utils/githelper" release_v2beta1 "github.com/fluxcd/helm-controller/api/v2beta1" helmrepo_v1beta2 "github.com/fluxcd/source-controller/api/v1beta2" + "github.com/sirupsen/logrus" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" ) @@ -30,6 +34,7 @@ func (f *Flux) SyncState(diff diff.Diff) error { entity := "repository" srcPath := fmt.Sprintf("%s/src", f.path) filePath := fmt.Sprintf("%s/%s-", srcPath, entity) + for _, repo := range diff.DeletedRepositories { if err := os.Remove(filePath + repo.Name + ".yaml"); err != nil { return err @@ -44,6 +49,7 @@ func (f *Flux) SyncState(diff diff.Diff) error { return err } } + for _, repo := range diff.UpdatedRepositories { manifest, err := GenerateRepository(repo) if err != nil { @@ -85,9 +91,14 @@ func (f *Flux) SyncState(diff diff.Diff) error { } } + entity = "release" filePath = fmt.Sprintf("%s/%s-", srcPath, entity) + for _, release := range diff.AddedReleases { + if err := SyncValues(release, srcPath); err != nil { + return err + } manifest, err := GenerateRelease(release) if err != nil { return err @@ -113,7 +124,9 @@ func (f *Flux) SyncState(diff diff.Diff) error { } } + for _, release := range diff.UpdatedReleases { + SyncValues(release, srcPath) manifest, err := GenerateRelease(release) if err != nil { return err @@ -136,6 +149,7 @@ func (f *Flux) SyncState(diff diff.Diff) error { } } + for _, release := range diff.DeletedReleases { if err := os.Remove(filePath + release.Release + ".yaml"); err != nil { return err @@ -210,3 +224,50 @@ func GenerateRelease(release *release.Release) ([]byte, error) { } return yaml.Marshal(&fluxRelease) } + +func SyncValues(release *release.Release, path string) error { + for _, valueFile := range release.Values { + // Prepare a dir for values + valuesPath := fmt.Sprintf("%s/%s", path, "values") + if _, err := os.Stat(valuesPath); errors.Is(err, os.ErrNotExist) { + err := os.Mkdir(valuesPath, os.ModePerm) + if err != nil { + return err + } + } else if err != nil { + return err + } + + destFileName := fmt.Sprintf("%s/%s-%s", valuesPath, release.Release, filepath.Base(valueFile)) + logrus.Info(destFileName) + logrus.Info(valueFile) + var dstValues *os.File + var srcValues *os.File + var err error + srcValues, err = os.Open(valueFile) + if err != nil { + return err + } + defer srcValues.Close() + if _, err = os.Stat(destFileName); err == nil { + dstValues, err = os.Open(destFileName) + if err != nil { + return err + } + defer dstValues.Close() + } else if errors.Is(err, os.ErrNotExist) { + dstValues, err = os.Create(destFileName) + if err != nil { + return nil + } + defer dstValues.Close() + } else { + return err + } + _, err = io.Copy(dstValues, srcValues) + if err != nil { + return err + } + } + return nil +} diff --git a/internal/utils/kustomize/kustomize.go b/internal/utils/kustomize/kustomize.go index b1fb203..96abc6b 100644 --- a/internal/utils/kustomize/kustomize.go +++ b/internal/utils/kustomize/kustomize.go @@ -3,6 +3,8 @@ package kustomize import ( "fmt" "os" + "path/filepath" + "strings" "git.badhouseplants.net/allanger/shoebill/internal/utils/githelper" kustomize_types "sigs.k8s.io/kustomize/api/types" @@ -10,22 +12,47 @@ import ( ) type Kusmtomize struct { - Files []string + Files []string + ConfigMaps []string } func (k *Kusmtomize) PopulateResources(path string) error { + // Main sources files, err := os.ReadDir(fmt.Sprintf("%s/src", path)) if err != nil { return err } for _, file := range files { - if file.Name() != ".gitkeep" { + if file.Name() != ".gitkeep" && !file.IsDir() { k.Files = append(k.Files, fmt.Sprintf("src/%s", file.Name())) } } + // Values + files, err = os.ReadDir(fmt.Sprintf("%s/src/values", path)) + if err != nil { + return err + } + + for _, file := range files { + k.ConfigMaps = append(k.ConfigMaps, fmt.Sprintf("src/values/%s", file.Name())) + } return nil } +func (k *Kusmtomize) CmGeneratorFromFiles() ([]kustomize_types.ConfigMapArgs, error) { + cmGens := []kustomize_types.ConfigMapArgs{} + for _, cm := range k.ConfigMaps { + cmName := + cmGen := &kustomize_types.ConfigMapArgs{ + GeneratorArgs: kustomize_types.GeneratorArgs{ + Namespace: "flux-system", + Name: "", + }, + } + } + +} + func Generate(path string, gh githelper.Githelper) error { kustomize := &Kusmtomize{} if err := kustomize.PopulateResources(path); err != nil { @@ -42,6 +69,10 @@ func Generate(path string, gh githelper.Githelper) error { Namespace: "flux-system", }, Resources: kustomize.Files, + GeneratorOptions: &kustomize_types.GeneratorOptions{ + DisableNameSuffixHash: true, + }, + ConfigMapGenerator: []kustomize_types.ConfigMapArgs{}, } manifest, err := yaml.Marshal(kustomization) if err != nil { @@ -60,5 +91,4 @@ func Generate(path string, gh githelper.Githelper) error { } return nil - }