shoebill/pkg/release/release.go

275 lines
6.5 KiB
Go
Raw Permalink Normal View History

2023-07-20 09:26:25 +00:00
package release
import (
"fmt"
2023-10-12 16:02:14 +00:00
"os"
2023-10-12 11:23:50 +00:00
"path/filepath"
2023-07-20 09:26:25 +00:00
"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-12-20 16:36:14 +00:00
"git.badhouseplants.net/allanger/shoebill/pkg/chart"
2024-07-25 13:23:28 +00:00
"git.badhouseplants.net/allanger/shoebill/pkg/config"
"git.badhouseplants.net/allanger/shoebill/pkg/lockfile"
2023-12-20 16:36:14 +00:00
"git.badhouseplants.net/allanger/shoebill/pkg/mirror"
"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
2024-07-25 13:23:28 +00:00
Mirror string
2023-07-20 09:26:25 +00:00
// Private fields that should be pupulated during the run-time
2023-10-12 16:02:14 +00:00
RepositoryObj *repository.Repository `yaml:"-"`
2024-07-25 13:23:28 +00:00
ChartObj *chart.Chart `yaml:"-"`
2023-10-12 16:02:14 +00:00
DestValues ValuesHolders `yaml:"-"`
DestSecrets ValuesHolders `yaml:"-"`
2023-10-12 11:23:50 +00:00
}
2023-10-20 11:31:30 +00:00
func (r *Release) ToHelmReleaseData() *helmhelper.ReleaseData {
2024-07-25 13:23:28 +00:00
// valuesData =
2023-10-20 11:31:30 +00:00
// for _, data := range r.DestValues {
2024-07-25 13:23:28 +00:00
2023-10-20 11:31:30 +00:00
// }
return &helmhelper.ReleaseData{
Name: r.Release,
Chart: r.Chart,
Version: r.Version,
Namespace: r.Namespace,
RepositoryName: r.RepositoryObj.Name,
RepositoryURL: r.RepositoryObj.URL,
RepositoryKind: r.RepositoryObj.Kind,
}
}
2023-10-12 11:23:50 +00:00
type ValuesHolder struct {
SrcPath string
DestPath string
Data []byte
2023-07-20 09:26:25 +00:00
}
2023-10-12 16:02:14 +00:00
type ValuesHolders []ValuesHolder
2023-07-20 09:26:25 +00:00
2023-10-12 16:02:14 +00:00
func (vhs ValuesHolders) ToStrings() []string {
values := []string{}
for _, vh := range vhs {
values = append(values, vh.DestPath)
}
return values
2023-10-11 12:14:20 +00:00
}
2023-10-12 16:02:14 +00:00
type Releases []*Release
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
}
2023-12-20 16:36:14 +00:00
// RepositoryObjFromName gather the whole repository object by its name
func (r *Release) MirrorObjFromName(mirrors mirror.Mirrors) error {
for _, mir := range mirrors {
if mir.Name == r.Mirror {
r.RepositoryObj = &repository.Repository{
Name: mir.Name,
2024-07-25 13:23:28 +00:00
URL: fmt.Sprintf("%s/%s", mir.OCI.URL, mir.OCI.Prefix),
2023-12-20 16:36:14 +00:00
}
2023-07-20 09:26:25 +00:00
}
2023-12-20 16:36:14 +00:00
}
if r.RepositoryObj == nil {
2023-12-20 21:19:08 +00:00
return fmt.Errorf("couldn't gather the RepositoryObj from mirror for %s", r.Repository)
2023-12-20 16:36:14 +00:00
}
return nil
}
2023-07-20 09:26:25 +00:00
2023-12-20 16:36:14 +00:00
func (r *Release) ChartObjFromName(chs chart.Charts) error {
for _, ch := range chs {
if ch.Name == r.Chart {
r.ChartObj = ch
}
}
if r.ChartObj == nil {
return fmt.Errorf("couldn't gather the ChartObj for %s", r.Chart)
2023-07-20 09:26:25 +00:00
}
return nil
}
2023-12-20 16:36:14 +00:00
// Possible version placeholders
const (
VERSION_LATEST = "latest"
)
2023-10-12 16:02:14 +00:00
func (r *Release) ValuesHandler(dir string) error {
2023-09-22 11:02:56 +00:00
for i := range r.Values {
r.Values[i] = fmt.Sprintf("%s/%s", dir, strings.ReplaceAll(r.Values[i], "./", ""))
2023-10-12 11:23:50 +00:00
destValues := fmt.Sprintf("%s-%s-%s", r.Namespace, r.Release, filepath.Base(r.Values[i]))
2023-10-12 16:02:14 +00:00
valuesData, err := os.ReadFile(r.Values[i])
if err != nil {
return err
}
2023-10-12 11:23:50 +00:00
r.DestValues = append(r.DestValues, ValuesHolder{
SrcPath: r.Values[i],
DestPath: destValues,
2023-10-12 16:02:14 +00:00
Data: valuesData,
2023-10-12 11:23:50 +00:00
})
2023-09-22 11:02:56 +00:00
}
2023-10-12 16:02:14 +00:00
return nil
2023-09-22 11:02:56 +00:00
}
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
}
2023-10-12 11:23:50 +00:00
destSecrets := fmt.Sprintf("%s-%s-%s", r.Namespace, r.Release, filepath.Base(r.Secrets[i]))
2023-10-12 16:02:14 +00:00
r.DestSecrets = append(r.DestSecrets, ValuesHolder{
SrcPath: path,
DestPath: destSecrets,
Data: res,
})
2023-10-11 12:14:20 +00:00
}
return nil
}
2023-07-20 09:26:25 +00:00
func FindReleaseByNames(releases []string, releasesObj Releases) Releases {
result := Releases{}
2023-10-12 11:23:50 +00:00
for _, repoObj := range releasesObj {
for _, release := range releases {
if repoObj.Release == release {
result = append(result, repoObj)
2023-07-20 09:26:25 +00:00
}
}
}
2023-10-12 11:23:50 +00:00
2023-07-20 09:26:25 +00:00
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,
2023-10-12 16:02:14 +00:00
Values: r.DestValues.ToStrings(),
Secrets: r.DestSecrets.ToStrings(),
2023-07-20 09:26:25 +00:00
}
}
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
}
2024-07-25 13:23:28 +00:00
func (rs *Releases) PopulateRepositories(repos config.Repositories, mirrors mirror.Mirrors) error {
2023-07-20 09:26:25 +00:00
for _, r := range *rs {
2023-12-20 21:19:08 +00:00
if len(r.Mirror) > 0 {
if err := r.MirrorObjFromName(mirrors); err != nil {
return err
}
} else {
2024-07-25 13:23:28 +00:00
if err := r.RepositoryObjFromName(repos); err != nil {
return err
}
2023-12-20 21:19:08 +00:00
}
2023-07-20 09:26:25 +00:00
}
return nil
}
2023-12-20 16:36:14 +00:00
func (rs *Releases) PopulateCharts(chs chart.Charts) error {
for _, r := range *rs {
if err := r.ChartObjFromName(chs); err != nil {
return err
}
}
return nil
}