From 44cae094e85057ed2b94e5112ef0b16b666479c1 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Mon, 12 Apr 2021 12:04:04 +0200 Subject: [PATCH] Allow multiple build values files Fixes #198 --- cmd/build.go | 4 ++-- pkg/compiler/compiler.go | 47 +++++++++++++++++++++++----------------- pkg/helpers/helm.go | 46 ++++++++++++++++++++++++++++----------- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/cmd/build.go b/cmd/build.go index 2551f37c..715ee341 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -100,7 +100,7 @@ Build packages specifying multiple definition trees: databaseType := viper.GetString("database") compressionType := viper.GetString("compression") imageRepository := viper.GetString("image-repository") - values := viper.GetString("values") + values := viper.GetStringSlice("values") wait := viper.GetBool("wait") push := viper.GetBool("push") pull := viper.GetBool("pull") @@ -311,7 +311,7 @@ func init() { buildCmd.Flags().Bool("revdeps", false, "Build with revdeps") buildCmd.Flags().Bool("all", false, "Build all specfiles in the tree") buildCmd.Flags().Bool("full", false, "Build all packages (optimized)") - buildCmd.Flags().String("values", "", "Build values file to interpolate with each package") + buildCmd.Flags().StringSlice("values", []string{}, "Build values file to interpolate with each package") buildCmd.Flags().StringSliceP("backend-args", "a", []string{}, "Backend args") buildCmd.Flags().String("destination", filepath.Join(path, "build"), "Destination folder") diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index 1db55844..a193f8c9 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -854,13 +854,7 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p Compila type templatedata map[string]interface{} -// FromPackage returns a compilation spec from a package definition -func (cs *LuetCompiler) FromPackage(p pkg.Package) (CompilationSpec, error) { - - pack, err := cs.Database.FindPackageCandidate(p) - if err != nil { - return nil, err - } +func (cs *LuetCompiler) templatePackage(pack pkg.Package) ([]byte, error) { var dataresult []byte @@ -877,36 +871,49 @@ func (cs *LuetCompiler) FromPackage(p pkg.Package) (CompilationSpec, error) { if err != nil { return nil, errors.Wrap(err, "rendering file "+val) } + packsRaw, err := pkg.GetRawPackages(data) + if err != nil { + return nil, errors.Wrap(err, "getting raw packages") + } raw := packsRaw.Find(pack.GetName(), pack.GetCategory(), pack.GetVersion()) - d := map[string]interface{}{} - if len(cs.Options.BuildValuesFile) > 0 { - defBuild, err := ioutil.ReadFile(cs.Options.BuildValuesFile) - if err != nil { - return nil, errors.Wrap(err, "rendering file "+val) - } - err = yaml.Unmarshal(defBuild, &d) - if err != nil { - return nil, errors.Wrap(err, "rendering file "+val) - } + dst, err := helpers.UnMarshalValues(cs.Options.BuildValuesFile) + if err != nil { + return nil, errors.Wrap(err, "unmarshalling values") } - dat, err := helpers.RenderHelm(string(dataBuild), raw, d) + dat, err := helpers.RenderHelm(string(dataBuild), raw, dst) if err != nil { return nil, errors.Wrap(err, "rendering file "+pack.Rel(BuildFile)) } dataresult = []byte(dat) } else { - out, err := helpers.RenderFiles(pack.Rel(BuildFile), val, cs.Options.BuildValuesFile) + out, err := helpers.RenderFiles(pack.Rel(BuildFile), val, cs.Options.BuildValuesFile...) if err != nil { return nil, errors.Wrap(err, "rendering file "+pack.Rel(BuildFile)) } dataresult = []byte(out) } + return dataresult, nil - return NewLuetCompilationSpec(dataresult, pack) +} + +// FromPackage returns a compilation spec from a package definition +func (cs *LuetCompiler) FromPackage(p pkg.Package) (CompilationSpec, error) { + + pack, err := cs.Database.FindPackageCandidate(p) + if err != nil { + return nil, err + } + + bytes, err := cs.templatePackage(pack) + if err != nil { + return nil, errors.Wrap(err, "while rendering package template") + } + + return NewLuetCompilationSpec(bytes, pack) } // GetBackend returns the current compilation backend diff --git a/pkg/helpers/helm.go b/pkg/helpers/helm.go index a3f21cb5..d708cece 100644 --- a/pkg/helpers/helm.go +++ b/pkg/helpers/helm.go @@ -2,7 +2,9 @@ package helpers import ( "io/ioutil" + "sort" + "github.com/imdario/mergo" "github.com/pkg/errors" "gopkg.in/yaml.v2" "helm.sh/helm/v3/pkg/chart" @@ -37,7 +39,31 @@ func RenderHelm(template string, values, d map[string]interface{}) (string, erro type templatedata map[string]interface{} -func RenderFiles(toTemplate, valuesFile string, defaultFile string) (string, error) { +func UnMarshalValues(values []string) (templatedata, error) { + dst := templatedata{} + if len(values) > 0 { + allbv := values + sort.Sort(sort.Reverse(sort.StringSlice(allbv))) + for _, bv := range allbv { + current := map[string]interface{}{} + + defBuild, err := ioutil.ReadFile(bv) + if err != nil { + return nil, errors.Wrap(err, "rendering file "+bv) + } + err = yaml.Unmarshal(defBuild, ¤t) + if err != nil { + return nil, errors.Wrap(err, "rendering file "+bv) + } + if err := mergo.Merge(&dst, current); err != nil { + return nil, errors.Wrap(err, "merging values file "+bv) + } + } + } + return dst, nil +} + +func RenderFiles(toTemplate, valuesFile string, defaultFile ...string) (string, error) { raw, err := ioutil.ReadFile(toTemplate) if err != nil { return "", errors.Wrap(err, "reading file "+toTemplate) @@ -52,20 +78,14 @@ func RenderFiles(toTemplate, valuesFile string, defaultFile string) (string, err } var values templatedata - d := templatedata{} - if len(defaultFile) > 0 { - def, err := ioutil.ReadFile(defaultFile) - if err != nil { - return "", errors.Wrap(err, "reading file "+valuesFile) - } - if err = yaml.Unmarshal(def, &d); err != nil { - return "", errors.Wrap(err, "unmarshalling file "+toTemplate) - } - } - if err = yaml.Unmarshal(val, &values); err != nil { return "", errors.Wrap(err, "unmarshalling file "+toTemplate) } - return RenderHelm(string(raw), values, d) + dst, err := UnMarshalValues(defaultFile) + if err != nil { + return "", errors.Wrap(err, "unmarshalling values") + } + + return RenderHelm(string(raw), values, dst) }