WIP: start adding values support

This commit is contained in:
Nikolai Rodionov 2023-09-22 13:02:56 +02:00
parent b2a43af042
commit beef71b128
No known key found for this signature in database
GPG Key ID: 19DB54039EBF8F10
7 changed files with 121 additions and 30 deletions

View File

@ -1,26 +1,16 @@
--- ---
repositories: repositories:
- name: jetstack
url: https://charts.jetstack.io
- name: bitnami-oci - name: bitnami-oci
url: oci://registry-1.docker.io/bitnamicharts url: oci://registry-1.docker.io/bitnamicharts
releases: 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 - name: postgresql-server
chart: postgresql chart: postgresql
repository: bitnami-oci repository: bitnami-oci
namespace: postgresql-server namespace: postgresql-server
version: latest version: latest
values:
- ./values/postgresql.yaml
clusters: clusters:
- name: cluster-shoebill-test - name: cluster-shoebill-test
@ -28,5 +18,3 @@ clusters:
provider: flux provider: flux
releases: releases:
- postgresql-server - postgresql-server
- cert-manager
# - cert-manager-2

View File

@ -0,0 +1,6 @@
---
global:
postgresql:
auth:
username: check
password: check

View File

@ -14,6 +14,7 @@ type Config struct {
Repositories repository.Repositories Repositories repository.Repositories
Releases release.Releases Releases release.Releases
Clusters cluster.Clusters Clusters cluster.Clusters
ConfigPath string `yaml:"-"`
} }
// NewConfigFromFile populates the config struct from a configuration yaml file // 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 { if err := yaml.Unmarshal(configFile, &config); err != nil {
return nil, err return nil, err
} }
config.ConfigPath = path
return &config, nil return &config, nil
} }

View File

@ -3,6 +3,7 @@ package release
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"strings"
"git.badhouseplants.net/allanger/shoebill/internal/config/repository" "git.badhouseplants.net/allanger/shoebill/internal/config/repository"
"git.badhouseplants.net/allanger/shoebill/internal/lockfile" "git.badhouseplants.net/allanger/shoebill/internal/lockfile"
@ -21,6 +22,8 @@ type Release struct {
Version string Version string
// Namespace to install release // Namespace to install release
Namespace string Namespace string
// Value files
Values []string
// Private fields that should be pupulated during the run-time // Private fields that should be pupulated during the run-time
RepositoryObj *repository.Repository `yaml:"-"` RepositoryObj *repository.Repository `yaml:"-"`
} }
@ -59,6 +62,12 @@ func (r *Release) VersionHandler(dir string, hh helmhelper.Helmhelper) error {
return nil 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 { func FindReleaseByNames(releases []string, releasesObj Releases) Releases {
result := Releases{} result := Releases{}
for _, rObj := range releasesObj { for _, rObj := range releasesObj {

View File

@ -2,6 +2,7 @@ package controller
import ( import (
"fmt" "fmt"
"path/filepath"
"git.badhouseplants.net/allanger/shoebill/internal/config" "git.badhouseplants.net/allanger/shoebill/internal/config"
"git.badhouseplants.net/allanger/shoebill/internal/config/release" "git.badhouseplants.net/allanger/shoebill/internal/config/release"
@ -22,15 +23,12 @@ func ReadTheConfig(path string) (*config.Config, error) {
return conf, nil 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 { func Reconcile(workdirPath, sshKeyPath string, conf *config.Config, dry bool) error {
dir, err := workdir.CreateWorkdir(workdirPath) dir, err := workdir.CreateWorkdir(workdirPath)
if err != nil { if err != nil {
return err return err
} }
// Prepare repositories
for _, repository := range conf.Repositories { for _, repository := range conf.Repositories {
if err := repository.ValidateURL(); err != nil { if err := repository.ValidateURL(); err != nil {
return err return err
@ -39,17 +37,10 @@ func Reconcile(workdirPath, sshKeyPath string, conf *config.Config, dry bool) er
return err return err
} }
} }
gh := githelper.NewGit(sshKeyPath) gh := githelper.NewGit(sshKeyPath)
for _, cluster := range conf.Clusters { 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) fullPath := fmt.Sprintf("%s/%s", dir, cluster.Name)
provider, err := providers.NewProvider(cluster.Provider, fullPath, gh) provider, err := providers.NewProvider(cluster.Provider, fullPath, gh)
if err != nil { 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 { if err := cluster.CloneRepo(gh, fullPath, dry); err != nil {
return err return err
} }
err = cluster.BootstrapRepo(gh, fullPath, dry) err = cluster.BootstrapRepo(gh, fullPath, dry)
if err != nil { if err != nil {
return err return err
} }
lockfileData, err := lockfile.NewFromFile(fullPath) lockfileData, err := lockfile.NewFromFile(fullPath)
if err != nil { if err != nil {
return err return err
@ -78,11 +71,13 @@ func Reconcile(workdirPath, sshKeyPath string, conf *config.Config, dry bool) er
} }
hh := helmhelper.NewHelm() hh := helmhelper.NewHelm()
for _, release := range conf.Releases { for _, release := range conf.Releases {
err := release.VersionHandler(workdirPath, hh) err := release.VersionHandler(workdirPath, hh)
if err != nil { if err != nil {
return err return err
} }
release.ValuesHandler(filepath.Dir(conf.ConfigPath))
} }
rsObj := release.FindReleaseByNames(cluster.Releases, conf.Releases) rsObj := release.FindReleaseByNames(cluster.Releases, conf.Releases)

View File

@ -1,8 +1,11 @@
package providers package providers
import ( import (
"errors"
"fmt" "fmt"
"io"
"os" "os"
"path/filepath"
"git.badhouseplants.net/allanger/shoebill/internal/config/release" "git.badhouseplants.net/allanger/shoebill/internal/config/release"
"git.badhouseplants.net/allanger/shoebill/internal/config/repository" "git.badhouseplants.net/allanger/shoebill/internal/config/repository"
@ -10,6 +13,7 @@ import (
"git.badhouseplants.net/allanger/shoebill/internal/utils/githelper" "git.badhouseplants.net/allanger/shoebill/internal/utils/githelper"
release_v2beta1 "github.com/fluxcd/helm-controller/api/v2beta1" release_v2beta1 "github.com/fluxcd/helm-controller/api/v2beta1"
helmrepo_v1beta2 "github.com/fluxcd/source-controller/api/v1beta2" helmrepo_v1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/sirupsen/logrus"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
) )
@ -30,6 +34,7 @@ func (f *Flux) SyncState(diff diff.Diff) error {
entity := "repository" entity := "repository"
srcPath := fmt.Sprintf("%s/src", f.path) srcPath := fmt.Sprintf("%s/src", f.path)
filePath := fmt.Sprintf("%s/%s-", srcPath, entity) filePath := fmt.Sprintf("%s/%s-", srcPath, entity)
for _, repo := range diff.DeletedRepositories { for _, repo := range diff.DeletedRepositories {
if err := os.Remove(filePath + repo.Name + ".yaml"); err != nil { if err := os.Remove(filePath + repo.Name + ".yaml"); err != nil {
return err return err
@ -44,6 +49,7 @@ func (f *Flux) SyncState(diff diff.Diff) error {
return err return err
} }
} }
for _, repo := range diff.UpdatedRepositories { for _, repo := range diff.UpdatedRepositories {
manifest, err := GenerateRepository(repo) manifest, err := GenerateRepository(repo)
if err != nil { if err != nil {
@ -85,9 +91,14 @@ func (f *Flux) SyncState(diff diff.Diff) error {
} }
} }
entity = "release" entity = "release"
filePath = fmt.Sprintf("%s/%s-", srcPath, entity) filePath = fmt.Sprintf("%s/%s-", srcPath, entity)
for _, release := range diff.AddedReleases { for _, release := range diff.AddedReleases {
if err := SyncValues(release, srcPath); err != nil {
return err
}
manifest, err := GenerateRelease(release) manifest, err := GenerateRelease(release)
if err != nil { if err != nil {
return err return err
@ -113,7 +124,9 @@ func (f *Flux) SyncState(diff diff.Diff) error {
} }
} }
for _, release := range diff.UpdatedReleases { for _, release := range diff.UpdatedReleases {
SyncValues(release, srcPath)
manifest, err := GenerateRelease(release) manifest, err := GenerateRelease(release)
if err != nil { if err != nil {
return err return err
@ -136,6 +149,7 @@ func (f *Flux) SyncState(diff diff.Diff) error {
} }
} }
for _, release := range diff.DeletedReleases { for _, release := range diff.DeletedReleases {
if err := os.Remove(filePath + release.Release + ".yaml"); err != nil { if err := os.Remove(filePath + release.Release + ".yaml"); err != nil {
return err return err
@ -210,3 +224,50 @@ func GenerateRelease(release *release.Release) ([]byte, error) {
} }
return yaml.Marshal(&fluxRelease) 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
}

View File

@ -3,6 +3,8 @@ package kustomize
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings"
"git.badhouseplants.net/allanger/shoebill/internal/utils/githelper" "git.badhouseplants.net/allanger/shoebill/internal/utils/githelper"
kustomize_types "sigs.k8s.io/kustomize/api/types" kustomize_types "sigs.k8s.io/kustomize/api/types"
@ -10,22 +12,47 @@ import (
) )
type Kusmtomize struct { type Kusmtomize struct {
Files []string Files []string
ConfigMaps []string
} }
func (k *Kusmtomize) PopulateResources(path string) error { func (k *Kusmtomize) PopulateResources(path string) error {
// Main sources
files, err := os.ReadDir(fmt.Sprintf("%s/src", path)) files, err := os.ReadDir(fmt.Sprintf("%s/src", path))
if err != nil { if err != nil {
return err return err
} }
for _, file := range files { 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())) 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 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 { func Generate(path string, gh githelper.Githelper) error {
kustomize := &Kusmtomize{} kustomize := &Kusmtomize{}
if err := kustomize.PopulateResources(path); err != nil { if err := kustomize.PopulateResources(path); err != nil {
@ -42,6 +69,10 @@ func Generate(path string, gh githelper.Githelper) error {
Namespace: "flux-system", Namespace: "flux-system",
}, },
Resources: kustomize.Files, Resources: kustomize.Files,
GeneratorOptions: &kustomize_types.GeneratorOptions{
DisableNameSuffixHash: true,
},
ConfigMapGenerator: []kustomize_types.ConfigMapArgs{},
} }
manifest, err := yaml.Marshal(kustomization) manifest, err := yaml.Marshal(kustomization)
if err != nil { if err != nil {
@ -60,5 +91,4 @@ func Generate(path string, gh githelper.Githelper) error {
} }
return nil return nil
} }