package release import ( "fmt" "reflect" "strings" "git.badhouseplants.net/allanger/shoebill/internal/utils/helmhelper" "git.badhouseplants.net/allanger/shoebill/internal/utils/sopshelper" "git.badhouseplants.net/allanger/shoebill/pkg/lockfile" "git.badhouseplants.net/allanger/shoebill/pkg/repository" "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 // Value files Values []string // Secrets SOPS encrypted Secrets []string // Private fields that should be pupulated during the run-time RepositoryObj *repository.Repository `yaml:"-"` UnencryptedSecrets map[string][]byte `yaml:"-"` } type Releases []*Release // Preare the release object func (r *Release) InitRelease() { r.UnencryptedSecrets = map[string][]byte{} } // 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 } 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 (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 } 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{ Repository: releaseLocked.RepoName, Release: releaseLocked.Release, Chart: releaseLocked.Chart, Version: releaseLocked.Version, Namespace: releaseLocked.Namespace, RepositoryObj: &repository.Repository{ Name: releaseLocked.RepoName, URL: releaseLocked.RepoUrl, }, } if err := release.RepositoryObj.ValidateURL(); err != nil { return nil, err } if err := release.RepositoryObj.KindFromUrl(); err != nil { 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 }