Add templated finalizers

This commit is contained in:
Ettore Di Giacinto 2020-11-08 21:14:19 +01:00
parent 088adf6f3a
commit a765147c1d
8 changed files with 149 additions and 68 deletions

View File

@ -21,8 +21,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/ghodss/yaml"
"regexp" "regexp"
"strings" "strings"
"sync" "sync"
@ -456,7 +454,6 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage
} }
artifact.SetFiles(filelist) artifact.SetFiles(filelist)
artifact.GetCompileSpec().GetPackage().SetBuildTimestamp(time.Now().String()) artifact.GetCompileSpec().GetPackage().SetBuildTimestamp(time.Now().String())
err = artifact.WriteYaml(p.GetOutputPath()) err = artifact.WriteYaml(p.GetOutputPath())
@ -658,31 +655,11 @@ func (cs *LuetCompiler) FromPackage(p pkg.Package) (CompilationSpec, error) {
return nil, err return nil, err
} }
buildFile := pack.Rel(BuildFile) out, err := helpers.RenderFiles(pack.Rel(BuildFile), pack.Rel(DefinitionFile))
if !helpers.Exists(buildFile) {
return nil, errors.New("No build file present for " + p.GetFingerPrint())
}
defFile := pack.Rel(DefinitionFile)
if !helpers.Exists(defFile) {
return nil, errors.New("No build file present for " + p.GetFingerPrint())
}
def, err := ioutil.ReadFile(defFile)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "rendering file "+pack.Rel(BuildFile))
} }
build, err := ioutil.ReadFile(buildFile)
if err != nil {
return nil, err
}
var values templatedata
if err = yaml.Unmarshal(def, &values); err != nil {
return nil, err
}
out, err := helpers.RenderHelm(string(build), values)
if err != nil {
return nil, err
}
return NewLuetCompilationSpec([]byte(out), pack) return NewLuetCompilationSpec([]byte(out), pack)
} }

View File

@ -1,7 +1,10 @@
package helpers package helpers
import ( import (
"io/ioutil"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/yaml.v2"
"helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/engine" "helm.sh/helm/v3/pkg/engine"
@ -31,3 +34,26 @@ func RenderHelm(template string, values map[string]interface{}) (string, error)
return out["templates"], nil return out["templates"], nil
} }
type templatedata map[string]interface{}
func RenderFiles(toTemplate, valuesFile string) (string, error) {
raw, err := ioutil.ReadFile(toTemplate)
if err != nil {
return "", errors.Wrap(err, "reading file "+toTemplate)
}
if !Exists(valuesFile) {
return "", errors.Wrap(err, "file not existing "+valuesFile)
}
def, err := ioutil.ReadFile(valuesFile)
if err != nil {
return "", errors.Wrap(err, "reading file "+valuesFile)
}
var values templatedata
if err = yaml.Unmarshal(def, &values); err != nil {
return "", errors.Wrap(err, "unmarshalling file "+toTemplate)
}
return RenderHelm(string(raw), values)
}

View File

@ -30,7 +30,6 @@ import (
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
"github.com/mudler/luet/pkg/tree"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -453,8 +452,7 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
return errors.Wrap(err, "Failed creating package") return errors.Wrap(err, "Failed creating package")
} }
} }
executedFinalizer := map[string]bool{} var toFinalize []pkg.Package
if !l.Options.NoDeps { if !l.Options.NoDeps {
// TODO: Lower those errors as warning // TODO: Lower those errors as warning
for _, w := range p { for _, w := range p {
@ -466,36 +464,17 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
ORDER: ORDER:
for _, ass := range ordered { for _, ass := range ordered {
if ass.Value { if ass.Value {
installed, ok := toInstall[ass.Package.GetFingerPrint()] installed, ok := toInstall[ass.Package.GetFingerPrint()]
if !ok { if !ok {
// It was a dep already installed in the system, so we can skip it safely // It was a dep already installed in the system, so we can skip it safely
continue ORDER continue ORDER
} }
treePackage, err := installed.Repository.GetTree().GetDatabase().FindPackage(ass.Package) treePackage, err := installed.Repository.GetTree().GetDatabase().FindPackage(ass.Package)
if err != nil { if err != nil {
return errors.Wrap(err, "Error getting package "+ass.Package.HumanReadableString()) return errors.Wrap(err, "Error getting package "+ass.Package.HumanReadableString())
} }
if helpers.Exists(treePackage.Rel(tree.FinalizerFile)) {
finalizerRaw, err := ioutil.ReadFile(treePackage.Rel(tree.FinalizerFile))
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Error reading file "+treePackage.Rel(tree.FinalizerFile))
}
if _, exists := executedFinalizer[ass.Package.GetFingerPrint()]; !exists {
Info("Executing finalizer for " + ass.Package.HumanReadableString())
finalizer, err := NewLuetFinalizerFromYaml(finalizerRaw)
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Error reading finalizer "+treePackage.Rel(tree.FinalizerFile))
}
err = finalizer.RunInstall(s)
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Error executing install finalizer "+treePackage.Rel(tree.FinalizerFile))
}
executedFinalizer[ass.Package.GetFingerPrint()] = true
}
}
toFinalize = append(toFinalize, treePackage)
} }
} }
@ -506,29 +485,11 @@ func (l *LuetInstaller) install(syncedRepos Repositories, cp pkg.Packages, s *Sy
if err != nil { if err != nil {
return errors.Wrap(err, "Error getting package "+c.Package.HumanReadableString()) return errors.Wrap(err, "Error getting package "+c.Package.HumanReadableString())
} }
if helpers.Exists(treePackage.Rel(tree.FinalizerFile)) { toFinalize = append(toFinalize, treePackage)
finalizerRaw, err := ioutil.ReadFile(treePackage.Rel(tree.FinalizerFile))
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Error reading file "+treePackage.Rel(tree.FinalizerFile))
}
if _, exists := executedFinalizer[c.Package.GetFingerPrint()]; !exists {
Info(":shell: Executing finalizer for " + c.Package.HumanReadableString())
finalizer, err := NewLuetFinalizerFromYaml(finalizerRaw)
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Error reading finalizer "+treePackage.Rel(tree.FinalizerFile))
}
err = finalizer.RunInstall(s)
if err != nil && !l.Options.Force {
return errors.Wrap(err, "Error executing install finalizer "+treePackage.Rel(tree.FinalizerFile))
}
executedFinalizer[c.Package.GetFingerPrint()] = true
}
}
} }
} }
return nil return s.ExecuteFinalizers(toFinalize, l.Options.Force)
} }
func (l *LuetInstaller) downloadPackage(a ArtifactMatch) (compiler.Artifact, error) { func (l *LuetInstaller) downloadPackage(a ArtifactMatch) (compiler.Artifact, error) {

View File

@ -1,7 +1,12 @@
package installer package installer
import ( import (
. "github.com/mudler/luet/pkg/logger"
"github.com/mudler/luet/pkg/helpers"
pkg "github.com/mudler/luet/pkg/package" pkg "github.com/mudler/luet/pkg/package"
"github.com/mudler/luet/pkg/tree"
"github.com/pkg/errors"
) )
type System struct { type System struct {
@ -12,3 +17,31 @@ type System struct {
func (s *System) World() (pkg.Packages, error) { func (s *System) World() (pkg.Packages, error) {
return s.Database.World(), nil return s.Database.World(), nil
} }
type templatedata map[string]interface{}
func (s *System) ExecuteFinalizers(packs []pkg.Package, force bool) error {
executedFinalizer := map[string]bool{}
for _, p := range packs {
if helpers.Exists(p.Rel(tree.FinalizerFile)) {
out, err := helpers.RenderFiles(p.Rel(tree.FinalizerFile), p.Rel(tree.DefinitionFile))
if err != nil && !force {
return errors.Wrap(err, "reading file "+p.Rel(tree.FinalizerFile))
}
if _, exists := executedFinalizer[p.GetFingerPrint()]; !exists {
Info("Executing finalizer for " + p.HumanReadableString())
finalizer, err := NewLuetFinalizerFromYaml([]byte(out))
if err != nil && !force {
return errors.Wrap(err, "Error reading finalizer "+p.Rel(tree.FinalizerFile))
}
err = finalizer.RunInstall(s)
if err != nil && !force {
return errors.Wrap(err, "Error executing install finalizer "+p.Rel(tree.FinalizerFile))
}
executedFinalizer[p.GetFingerPrint()] = true
}
}
}
return nil
}

View File

@ -0,0 +1,2 @@
image: "alpine"
unpack: true

View File

@ -0,0 +1,3 @@
category: "seed"
name: "alpine"
version: "1.0"

View File

@ -0,0 +1,2 @@
install:
- echo "{{.Values.name}}" > /tmp/foo

View File

@ -0,0 +1,77 @@
#!/bin/bash
export LUET_NOLOCK=true
oneTimeSetUp() {
export tmpdir="$(mktemp -d)"
}
oneTimeTearDown() {
rm -rf "$tmpdir"
}
testBuild() {
mkdir $tmpdir/testbuild
luet build --tree "$ROOT_DIR/tests/fixtures/templatedfinalizers" --destination $tmpdir/testbuild --compression gzip --all > /dev/null
buildst=$?
assertEquals 'builds successfully' "$buildst" "0"
assertTrue 'create package' "[ -e '$tmpdir/testbuild/alpine-seed-1.0.package.tar.gz' ]"
}
testRepo() {
assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild/repository.yaml' ]"
luet create-repo --tree "$ROOT_DIR/tests/fixtures/templatedfinalizers" \
--output $tmpdir/testbuild \
--packages $tmpdir/testbuild \
--name "test" \
--descr "Test Repo" \
--urls $tmpdir/testrootfs \
--type disk > /dev/null
createst=$?
assertEquals 'create repo successfully' "$createst" "0"
assertTrue 'create repository' "[ -e '$tmpdir/testbuild/repository.yaml' ]"
}
testConfig() {
mkdir $tmpdir/testrootfs
cat <<EOF > $tmpdir/luet.yaml
general:
debug: true
system:
rootfs: $tmpdir/testrootfs
database_path: "/"
database_engine: "boltdb"
config_from_host: true
repositories:
- name: "main"
type: "disk"
enable: true
urls:
- "$tmpdir/testbuild"
EOF
luet config --config $tmpdir/luet.yaml
res=$?
assertEquals 'config test successfully' "$res" "0"
}
testInstall() {
luet install --config $tmpdir/luet.yaml seed/alpine
#luet install --config $tmpdir/luet.yaml test/c-1.0 > /dev/null
installst=$?
assertEquals 'install test successfully' "$installst" "0"
assertTrue 'package installed' "[ -e '$tmpdir/testrootfs/bin/busybox' ]"
assertTrue 'finalizer runs' "[ -e '$tmpdir/testrootfs/tmp/foo' ]"
assertEquals 'finalizer printed used shell' "$(cat $tmpdir/testrootfs/tmp/foo)" 'alpine'
}
testCleanup() {
luet cleanup --config $tmpdir/luet.yaml
installst=$?
assertEquals 'install test successfully' "$installst" "0"
}
# Load shUnit2.
. "$ROOT_DIR/tests/integration/shunit2"/shunit2