2023-07-20 09:26:25 +00:00
|
|
|
package release
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
2023-09-22 11:02:56 +00:00
|
|
|
"strings"
|
2023-07-20 09:26:25 +00:00
|
|
|
|
2023-08-02 15:00:34 +00:00
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/helmhelper"
|
2023-10-11 12:14:20 +00:00
|
|
|
"git.badhouseplants.net/allanger/shoebill/internal/utils/sopshelper"
|
2023-10-12 09:53:58 +00:00
|
|
|
"git.badhouseplants.net/allanger/shoebill/pkg/lockfile"
|
|
|
|
"git.badhouseplants.net/allanger/shoebill/pkg/repository"
|
2023-07-20 09:26:25 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Release struct {
|
|
|
|
// Public fields, that can be set with yaml
|
|
|
|
Repository string
|
|
|
|
// Release name
|
|
|
|
Release string `yaml:"name"`
|
|
|
|
// Chart name
|
|
|
|
Chart string
|
|
|
|
// Chart version
|
|
|
|
Version string
|
|
|
|
// Namespace to install release
|
|
|
|
Namespace string
|
2023-09-22 11:02:56 +00:00
|
|
|
// Value files
|
|
|
|
Values []string
|
2023-10-11 12:14:20 +00:00
|
|
|
// Secrets SOPS encrypted
|
|
|
|
Secrets []string
|
2023-07-20 09:26:25 +00:00
|
|
|
// Private fields that should be pupulated during the run-time
|
2023-10-11 12:14:20 +00:00
|
|
|
RepositoryObj *repository.Repository `yaml:"-"`
|
|
|
|
UnencryptedSecrets map[string][]byte `yaml:"-"`
|
2023-07-20 09:26:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Releases []*Release
|
|
|
|
|
2023-10-11 12:14:20 +00:00
|
|
|
// Preare the release object
|
|
|
|
func (r *Release) InitRelease() {
|
|
|
|
r.UnencryptedSecrets = map[string][]byte{}
|
|
|
|
}
|
|
|
|
|
2023-07-20 09:26:25 +00:00
|
|
|
// RepositoryObjFromName gather the whole repository object by its name
|
|
|
|
func (r *Release) RepositoryObjFromName(repos repository.Repositories) error {
|
|
|
|
for _, repo := range repos {
|
|
|
|
if repo.Name == r.Repository {
|
|
|
|
r.RepositoryObj = repo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if r.RepositoryObj == nil {
|
|
|
|
return fmt.Errorf("couldn't gather the RepositoryObj for %s", r.Repository)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Possible version placeholders
|
|
|
|
const (
|
|
|
|
VERSION_LATEST = "latest"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Replace the version placeholder with the fixed version
|
|
|
|
func (r *Release) VersionHandler(dir string, hh helmhelper.Helmhelper) error {
|
|
|
|
switch r.Version {
|
|
|
|
case VERSION_LATEST:
|
|
|
|
version, err := hh.FindLatestVersion(dir, r.Chart, *r.RepositoryObj)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r.Version = version
|
|
|
|
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-09-22 11:02:56 +00:00
|
|
|
func (r *Release) ValuesHandler(dir string) {
|
|
|
|
for i := range r.Values {
|
|
|
|
r.Values[i] = fmt.Sprintf("%s/%s", dir, strings.ReplaceAll(r.Values[i], "./", ""))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-11 12:14:20 +00:00
|
|
|
func (r *Release) SecretsHandler(dir string, sops sopshelper.SopsHelper) error {
|
|
|
|
for i := range r.Secrets {
|
|
|
|
path := fmt.Sprintf("%s/%s", dir, strings.ReplaceAll(r.Secrets[i], "./", ""))
|
|
|
|
res, err := sops.Decrypt(path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r.UnencryptedSecrets[path] = res
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-07-20 09:26:25 +00:00
|
|
|
func FindReleaseByNames(releases []string, releasesObj Releases) Releases {
|
|
|
|
result := Releases{}
|
|
|
|
for _, rObj := range releasesObj {
|
|
|
|
for _, r := range releases {
|
|
|
|
if rObj.Release == r {
|
|
|
|
result = append(result, rObj)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helpers
|
|
|
|
func ReleasesFromLockfile(lockfile lockfile.LockFile, repos repository.Repositories) (Releases, error) {
|
|
|
|
releases := Releases{}
|
|
|
|
for _, releaseLocked := range lockfile {
|
|
|
|
release := &Release{
|
2023-10-11 13:03:50 +00:00
|
|
|
Repository: releaseLocked.RepoName,
|
2023-07-20 09:26:25 +00:00
|
|
|
Release: releaseLocked.Release,
|
|
|
|
Chart: releaseLocked.Chart,
|
|
|
|
Version: releaseLocked.Version,
|
|
|
|
Namespace: releaseLocked.Namespace,
|
2023-10-11 13:03:50 +00:00
|
|
|
RepositoryObj: &repository.Repository{
|
|
|
|
Name: releaseLocked.RepoName,
|
|
|
|
URL: releaseLocked.RepoUrl,
|
|
|
|
},
|
2023-07-20 09:26:25 +00:00
|
|
|
}
|
2023-10-11 13:03:50 +00:00
|
|
|
if err := release.RepositoryObj.ValidateURL(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := release.RepositoryObj.KindFromUrl(); err != nil {
|
2023-07-20 09:26:25 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
releases = append(releases, release)
|
|
|
|
}
|
|
|
|
return releases, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Release) LockEntry() *lockfile.LockEntry {
|
|
|
|
return &lockfile.LockEntry{
|
|
|
|
Chart: r.Chart,
|
|
|
|
Release: r.Release,
|
|
|
|
Version: r.Version,
|
|
|
|
Namespace: r.Namespace,
|
|
|
|
RepoUrl: r.RepositoryObj.URL,
|
|
|
|
RepoName: r.RepositoryObj.Name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type Diff struct {
|
|
|
|
Added Releases
|
|
|
|
Deleted Releases
|
|
|
|
Updated Releases
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(@allanger): Naming should be better
|
|
|
|
func (src Releases) Diff(dest Releases) Diff {
|
|
|
|
diff := Diff{}
|
|
|
|
for _, rSrc := range src {
|
|
|
|
found := false
|
|
|
|
for _, rDest := range dest {
|
|
|
|
logrus.Infof("comparing %s to %s", rSrc.Release, rDest.Release)
|
|
|
|
if rSrc.Release == rDest.Release {
|
|
|
|
found = true
|
|
|
|
if reflect.DeepEqual(rSrc, rDest) {
|
|
|
|
continue
|
|
|
|
} else {
|
|
|
|
diff.Updated = append(diff.Updated, rDest)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
diff.Deleted = append(diff.Added, rSrc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, rDest := range dest {
|
|
|
|
found := false
|
|
|
|
for _, rSrc := range src {
|
|
|
|
if rSrc.Release == rDest.Release {
|
|
|
|
found = true
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
diff.Added = append(diff.Added, rDest)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return diff
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rs *Releases) PopulateRepositories(repos repository.Repositories) error {
|
|
|
|
for _, r := range *rs {
|
|
|
|
if err := r.RepositoryObjFromName(repos); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|