Skip to content

Commit 0cc8930

Browse files
author
Daniele Rondina
authored
Finalizer envs (#242)
* Allow to define envs for finalizer Fixes: #241 * tests: Add integration test for finalizer with envs
1 parent db78459 commit 0cc8930

File tree

9 files changed

+213
-2
lines changed

9 files changed

+213
-2
lines changed

cmd/install.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ To force install a package:
7272
concurrent, _ := cmd.Flags().GetBool("solver-concurrent")
7373
yes := LuetCfg.Viper.GetBool("yes")
7474
downloadOnly, _ := cmd.Flags().GetBool("download-only")
75+
finalizerEnvs, _ := cmd.Flags().GetStringArray("finalizer-env")
7576

7677
util.SetSystemConfig()
7778
util.SetSolverConfig()
@@ -88,6 +89,12 @@ To force install a package:
8889
// Load config protect configs
8990
installer.LoadConfigProtectConfs(LuetCfg)
9091

92+
// Load finalizer runtime environments
93+
err := util.SetCliFinalizerEnvs(finalizerEnvs)
94+
if err != nil {
95+
Fatal(err.Error())
96+
}
97+
9198
inst := installer.NewLuetInstaller(installer.LuetInstallerOptions{
9299
Concurrency: LuetCfg.GetGeneral().Concurrency,
93100
SolverOptions: *LuetCfg.GetSolverOptions(),
@@ -101,7 +108,7 @@ To force install a package:
101108
inst.Repositories(repos)
102109

103110
system := &installer.System{Database: LuetCfg.GetSystemDB(), Target: LuetCfg.GetSystem().Rootfs}
104-
err := inst.Install(toInstall, system)
111+
err = inst.Install(toInstall, system)
105112
if err != nil {
106113
Fatal("Error: " + err.Error())
107114
}
@@ -123,6 +130,8 @@ func init() {
123130
installCmd.Flags().Bool("solver-concurrent", false, "Use concurrent solver (experimental)")
124131
installCmd.Flags().BoolP("yes", "y", false, "Don't ask questions")
125132
installCmd.Flags().Bool("download-only", false, "Download only")
133+
installCmd.Flags().StringArray("finalizer-env", []string{},
134+
"Set finalizer environment in the format key=value.")
126135

127136
RootCmd.AddCommand(installCmd)
128137
}

cmd/util/cli.go

+19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
package util
1717

1818
import (
19+
"errors"
20+
"strings"
21+
1922
"github.com/spf13/cobra"
2023
"github.com/spf13/viper"
2124

@@ -72,3 +75,19 @@ func SetSolverConfig() (c *config.LuetSolverOptions) {
7275
MaxAttempts: attempts,
7376
}
7477
}
78+
79+
func SetCliFinalizerEnvs(finalizerEnvs []string) error {
80+
if len(finalizerEnvs) > 0 {
81+
for _, v := range finalizerEnvs {
82+
idx := strings.Index(v, "=")
83+
if idx < 0 {
84+
return errors.New("Found invalid runtime finalizer environment: " + v)
85+
}
86+
87+
LuetCfg.SetFinalizerEnv(v[0:idx], v[idx+1:])
88+
}
89+
90+
}
91+
92+
return nil
93+
}

contrib/config/luet.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@
9999
# If set to false rootfs path is used as prefix.
100100
# config_from_host: true
101101
#
102+
#
103+
# ------------------------------------------------
104+
# Finalizer Environment Variables
105+
# -----------------------------------------------
106+
# finalizer_envs:
107+
# - key: "BUILD_ISO"
108+
# value: "1"
109+
#
102110
# System repositories
103111
# ---------------------------------------------
104112
# In alternative to define repositories files

pkg/config/config.go

+60
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ func (r *LuetRepository) String() string {
221221
r.Name, r.Priority, r.Type, r.Enable, r.Cached)
222222
}
223223

224+
type LuetKV struct {
225+
Key string `json:"key" yaml:"key" mapstructure:"key"`
226+
Value string `json:"value" yaml:"value" mapstructure:"value"`
227+
}
228+
224229
type LuetConfig struct {
225230
Viper *v.Viper
226231

@@ -236,6 +241,8 @@ type LuetConfig struct {
236241
CacheRepositories []LuetRepository `mapstructure:"repetitors"`
237242
SystemRepositories []LuetRepository `mapstructure:"repositories"`
238243

244+
FinalizerEnvs []LuetKV `json:"finalizer_envs,omitempty" yaml:"finalizer_envs,omitempty" mapstructure:"finalizer_envs,omitempty"`
245+
239246
ConfigProtectConfFiles []ConfigProtectConfFile
240247
}
241248

@@ -284,6 +291,7 @@ func GenDefault(viper *v.Viper) {
284291
viper.SetDefault("config_from_host", true)
285292
viper.SetDefault("cache_repositories", []string{})
286293
viper.SetDefault("system_repositories", []string{})
294+
viper.SetDefault("finalizer_envs", make(map[string]string, 0))
287295

288296
viper.SetDefault("solver.type", "")
289297
viper.SetDefault("solver.rate", 0.7)
@@ -305,6 +313,58 @@ func (c *LuetConfig) AddSystemRepository(r LuetRepository) {
305313
c.SystemRepositories = append(c.SystemRepositories, r)
306314
}
307315

316+
func (c *LuetConfig) GetFinalizerEnvsMap() map[string]string {
317+
ans := make(map[string]string, 0)
318+
319+
for _, kv := range c.FinalizerEnvs {
320+
ans[kv.Key] = kv.Value
321+
}
322+
return ans
323+
}
324+
325+
func (c *LuetConfig) SetFinalizerEnv(k, v string) {
326+
keyPresent := false
327+
envs := []LuetKV{}
328+
329+
for _, kv := range c.FinalizerEnvs {
330+
if kv.Key == k {
331+
keyPresent = true
332+
envs = append(envs, LuetKV{Key: kv.Key, Value: v})
333+
} else {
334+
envs = append(envs, kv)
335+
}
336+
}
337+
if !keyPresent {
338+
envs = append(envs, LuetKV{Key: k, Value: v})
339+
}
340+
341+
c.FinalizerEnvs = envs
342+
}
343+
344+
func (c *LuetConfig) GetFinalizerEnvs() []string {
345+
ans := []string{}
346+
for _, kv := range c.FinalizerEnvs {
347+
ans = append(ans, fmt.Sprintf("%s=%s", kv.Key, kv.Value))
348+
}
349+
return ans
350+
}
351+
352+
func (c *LuetConfig) GetFinalizerEnv(k string) (string, error) {
353+
keyNotPresent := true
354+
ans := ""
355+
for _, kv := range c.FinalizerEnvs {
356+
if kv.Key == k {
357+
keyNotPresent = false
358+
ans = kv.Value
359+
}
360+
}
361+
362+
if keyNotPresent {
363+
return "", errors.New("Finalizer key " + k + " not found")
364+
}
365+
return ans, nil
366+
}
367+
308368
func (c *LuetConfig) GetLogging() *LuetLoggingConfig {
309369
return &c.Logging
310370
}

pkg/installer/finalizer.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/ghodss/yaml"
2323
box "github.com/mudler/luet/pkg/box"
24+
. "github.com/mudler/luet/pkg/config"
2425
. "github.com/mudler/luet/pkg/logger"
2526

2627
"github.com/pkg/errors"
@@ -51,13 +52,14 @@ func (f *LuetFinalizer) RunInstall(s *System) error {
5152
Info(":shell: Executing finalizer on ", s.Target, cmd, toRun)
5253
if s.Target == string(os.PathSeparator) {
5354
cmd := exec.Command(cmd, toRun...)
55+
cmd.Env = LuetCfg.GetFinalizerEnvs()
5456
stdoutStderr, err := cmd.CombinedOutput()
5557
if err != nil {
5658
return errors.Wrap(err, "Failed running command: "+string(stdoutStderr))
5759
}
5860
Info(string(stdoutStderr))
5961
} else {
60-
b := box.NewBox(cmd, toRun, []string{}, []string{}, s.Target, false, true, true)
62+
b := box.NewBox(cmd, toRun, []string{}, LuetCfg.GetFinalizerEnvs(), s.Target, false, true, true)
6163
err := b.Run()
6264
if err != nil {
6365
return errors.Wrap(err, "Failed running command ")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
image: "alpine"
2+
unpack: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
category: "seed"
2+
name: "alpine-finalizer-envs"
3+
version: "1.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
install:
2+
- env
3+
- echo "$@"
4+
- echo "$0" > /tmp/foo
5+
- if [ -z "$BUILD_ISO" ] ; then echo "test" > /tmp/foo2 ; fi
6+
- if [ -z "$CLI_ENV" ] ; then echo "test" > /tmp/foo3 ; fi
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/bin/bash
2+
3+
export LUET_NOLOCK=true
4+
export luetbin="$ROOT_DIR/tests/integration/bin/luet"
5+
6+
oneTimeSetUp() {
7+
export tmpdir="$(mktemp -d)"
8+
}
9+
10+
oneTimeTearDown() {
11+
rm -rf "$tmpdir"
12+
}
13+
14+
testBuild() {
15+
16+
# Ensure thet repos_confdir is empty to avoid reading
17+
# repositories availables on host.
18+
19+
mkdir $tmpdir/repos
20+
cat <<EOF > $tmpdir/luet-build.yaml
21+
general:
22+
debug: true
23+
database_path: "/"
24+
database_engine: "boltdb"
25+
config_from_host: true
26+
finalizer_envs:
27+
BUILD_ISO: "1"
28+
repos_confdir:
29+
- "$tmpdir/repos"
30+
EOF
31+
32+
mkdir $tmpdir/testbuild
33+
${luetbin} build --config $tmpdir/luet-build.yaml --tree "$ROOT_DIR/tests/fixtures/finalizers_envs" --destination $tmpdir/testbuild --compression gzip --all
34+
buildst=$?
35+
assertEquals 'builds successfully' "$buildst" "0"
36+
assertTrue 'create package' "[ -e '$tmpdir/testbuild/alpine-finalizer-envs-seed-1.0.package.tar.gz' ]"
37+
}
38+
39+
testRepo() {
40+
assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild/repository.yaml' ]"
41+
${luetbin} create-repo --tree "$ROOT_DIR/tests/fixtures/finalizers_envs" \
42+
--output $tmpdir/testbuild \
43+
--packages $tmpdir/testbuild \
44+
--name "test" \
45+
--descr "Test Repo" \
46+
--urls $tmpdir/testrootfs \
47+
--type disk > /dev/null
48+
49+
createst=$?
50+
assertEquals 'create repo successfully' "$createst" "0"
51+
assertTrue 'create repository' "[ -e '$tmpdir/testbuild/repository.yaml' ]"
52+
}
53+
54+
testConfig() {
55+
mkdir $tmpdir/testrootfs
56+
cat <<EOF > $tmpdir/luet.yaml
57+
general:
58+
debug: true
59+
system:
60+
rootfs: $tmpdir/testrootfs
61+
database_path: "/"
62+
database_engine: "boltdb"
63+
config_from_host: true
64+
finalizer_envs:
65+
- key: "BUILD_ISO"
66+
value: "1"
67+
68+
repos_confdir:
69+
- "$tmpdir/repos"
70+
71+
repositories:
72+
- name: "main"
73+
type: "disk"
74+
enable: true
75+
urls:
76+
- "$tmpdir/testbuild"
77+
EOF
78+
${luetbin} config --config $tmpdir/luet.yaml
79+
res=$?
80+
assertEquals 'config test successfully' "$res" "0"
81+
}
82+
83+
testInstall() {
84+
${luetbin} install -y --finalizer-env "CLI_ENV=1" --config $tmpdir/luet.yaml seed/[email protected]
85+
installst=$?
86+
assertEquals 'install test successfully' "$installst" "0"
87+
assertTrue 'package installed' "[ -e '$tmpdir/testrootfs/bin/busybox' ]"
88+
assertTrue 'finalizer does not run' "[ -e '$tmpdir/testrootfs/tmp/foo' ]"
89+
assertTrue 'finalizer env var is not present' "[ ! -e '$tmpdir/testrootfs/tmp/foo2' ]"
90+
assertTrue 'finalizer env var cli is not present' "[ ! -e '$tmpdir/testrootfs/tmp/foo3' ]"
91+
}
92+
93+
94+
testCleanup() {
95+
${luetbin} cleanup --config $tmpdir/luet.yaml
96+
installst=$?
97+
assertEquals 'install test successfully' "$installst" "0"
98+
}
99+
100+
# Load shUnit2.
101+
. "$ROOT_DIR/tests/integration/shunit2"/shunit2
102+

0 commit comments

Comments
 (0)