From 5a882ced67b3b2e0213233ff0d601b30bec29f3f Mon Sep 17 00:00:00 2001 From: Atanas Dinov Date: Tue, 21 Nov 2023 11:27:46 +0200 Subject: [PATCH] Configure combustion components Signed-off-by: Atanas Dinov --- cmd/eib/main.go | 5 +- pkg/build/build.go | 64 +----- pkg/build/build_test.go | 33 +-- pkg/build/grub_test.go | 16 +- pkg/build/iso_test.go | 49 +++-- pkg/build/message.go | 26 --- pkg/build/message_test.go | 33 --- pkg/build/raw_test.go | 37 ++-- pkg/build/rpm_test.go | 205 ------------------ pkg/build/users.go | 37 ---- pkg/combustion/combustion.go | 61 ++++-- pkg/combustion/combustion_test.go | 26 ++- .../scripts.go => combustion/custom.go} | 9 +- .../custom_test.go} | 30 +-- pkg/combustion/message.go | 28 +++ pkg/combustion/message_test.go | 28 +++ pkg/{build => combustion}/rpm.go | 33 +-- pkg/combustion/rpm_test.go | 188 ++++++++++++++++ pkg/combustion/script.go | 37 ++++ pkg/combustion/script_test.go | 16 ++ .../scripts}/10-rpm-install.sh.tpl | 0 .../scripts}/add-users.sh.tpl | 0 .../message => combustion/scripts}/message.sh | 0 pkg/combustion/users.go | 39 ++++ pkg/{build => combustion}/users_test.go | 40 +--- pkg/context/context.go | 7 +- pkg/context/context_test.go | 4 +- 27 files changed, 526 insertions(+), 525 deletions(-) delete mode 100644 pkg/build/message.go delete mode 100644 pkg/build/message_test.go delete mode 100644 pkg/build/rpm_test.go delete mode 100644 pkg/build/users.go rename pkg/{build/scripts.go => combustion/custom.go} (80%) rename pkg/{build/scripts_test.go => combustion/custom_test.go} (81%) create mode 100644 pkg/combustion/message.go create mode 100644 pkg/combustion/message_test.go rename pkg/{build => combustion}/rpm.go (69%) create mode 100644 pkg/combustion/rpm_test.go create mode 100644 pkg/combustion/script.go create mode 100644 pkg/combustion/script_test.go rename pkg/{build/scripts/rpms => combustion/scripts}/10-rpm-install.sh.tpl (100%) rename pkg/{build/scripts/users => combustion/scripts}/add-users.sh.tpl (100%) rename pkg/{build/scripts/message => combustion/scripts}/message.sh (100%) create mode 100644 pkg/combustion/users.go rename pkg/{build => combustion}/users_test.go (79%) diff --git a/cmd/eib/main.go b/cmd/eib/main.go index d3726de4..f6b273b9 100644 --- a/cmd/eib/main.go +++ b/cmd/eib/main.go @@ -7,6 +7,7 @@ import ( "path/filepath" "github.com/suse-edge/edge-image-builder/pkg/build" + "github.com/suse-edge/edge-image-builder/pkg/combustion" "github.com/suse-edge/edge-image-builder/pkg/config" "github.com/suse-edge/edge-image-builder/pkg/context" "go.uber.org/zap" @@ -50,7 +51,7 @@ func processArgs() (*config.ImageConfig, *context.Context, error) { return nil, nil, fmt.Errorf("validating the config dir %s: %w", configDir, err) } - ctx, err := context.NewContext(configDir, buildDir, deleteBuildDir) + ctx, err := context.NewContext(configDir, buildDir, deleteBuildDir, imageConfig) if err != nil { return nil, nil, fmt.Errorf("building dir structure: %w", err) } @@ -117,7 +118,7 @@ func main() { zap.L().Fatal("CLI arguments could not be parsed", zap.Error(err)) } - builder := build.New(imageConfig, ctx) + builder := build.New(imageConfig, ctx, combustion.Configure) if err = builder.Build(); err != nil { zap.L().Fatal("An error occurred building the image", zap.Error(err)) } diff --git a/pkg/build/build.go b/pkg/build/build.go index ed94e57d..43d1404c 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -2,69 +2,31 @@ package build import ( "fmt" - "os" "path/filepath" - "github.com/suse-edge/edge-image-builder/pkg/combustion" "github.com/suse-edge/edge-image-builder/pkg/config" "github.com/suse-edge/edge-image-builder/pkg/context" - "github.com/suse-edge/edge-image-builder/pkg/fileio" ) +type configureCombustion func(ctx *context.Context) error + type Builder struct { - imageConfig *config.ImageConfig - context *context.Context + imageConfig *config.ImageConfig + context *context.Context + configureCombustion configureCombustion } -func New(imageConfig *config.ImageConfig, context *context.Context) *Builder { +func New(imageConfig *config.ImageConfig, ctx *context.Context, configureCombustionFunc configureCombustion) *Builder { return &Builder{ - imageConfig: imageConfig, - context: context, + imageConfig: imageConfig, + context: ctx, + configureCombustion: configureCombustionFunc, } } func (b *Builder) Build() error { - var combustionScripts []string - - messageScript, err := b.configureMessage() - if err != nil { - return fmt.Errorf("configuring the welcome message: %w", err) - } - - combustionScripts = append(combustionScripts, messageScript) - - customScripts, err := b.configureCustomScripts() - if err != nil { - return fmt.Errorf("configuring custom scripts: %w", err) - } - - combustionScripts = append(combustionScripts, customScripts...) - - userScript, err := b.configureUsers() - if err != nil { - return fmt.Errorf("configuring users: %w", err) - } - - if userScript != "" { - combustionScripts = append(combustionScripts, userScript) - } - - rpmScript, err := b.processRPMs() - if err != nil { - return fmt.Errorf("processing RPMs: %w", err) - } - - if rpmScript != "" { - combustionScripts = append(combustionScripts, rpmScript) - } - - script, err := combustion.GenerateScript(combustionScripts) - if err != nil { - return fmt.Errorf("generating combustion script: %w", err) - } - - if err = os.WriteFile("script", []byte(script), fileio.ExecutablePerms); err != nil { - return fmt.Errorf("writing combustion script: %w", err) + if err := b.configureCombustion(b.context); err != nil { + return fmt.Errorf("configuring combustion: %w", err) } switch b.imageConfig.Image.ImageType { @@ -82,10 +44,6 @@ func (b *Builder) generateBuildDirFilename(filename string) string { return filepath.Join(b.context.BuildDir, filename) } -func (b *Builder) generateCombustionDirFilename(filename string) string { - return filepath.Join(b.context.CombustionDir, filename) -} - func (b *Builder) generateOutputImageFilename() string { filename := filepath.Join(b.context.ImageConfigDir, b.imageConfig.Image.OutputImageName) return filename diff --git a/pkg/build/build_test.go b/pkg/build/build_test.go index e1fdfff6..6d565a30 100644 --- a/pkg/build/build_test.go +++ b/pkg/build/build_test.go @@ -1,6 +1,7 @@ package build import ( + "os" "path/filepath" "testing" @@ -9,38 +10,18 @@ import ( "github.com/suse-edge/edge-image-builder/pkg/context" ) -func TestGenerateCombustionDirFilename(t *testing.T) { - // Setup - ctx, err := context.NewContext("", "", true) - require.NoError(t, err) - defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) - }() - - builder := Builder{ - context: ctx, - } - - testFilename := "combustion-file.sh" - - // Test - filename := builder.generateCombustionDirFilename(testFilename) - - // Verify - expectedFilename := filepath.Join(ctx.CombustionDir, testFilename) - assert.Equal(t, expectedFilename, filename) -} - func TestGenerateBuildDirFilename(t *testing.T) { // Setup - ctx, err := context.NewContext("", "", true) + tmpDir, err := os.MkdirTemp("", "eib-") require.NoError(t, err) defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) + assert.NoError(t, os.RemoveAll(tmpDir)) }() builder := Builder{ - context: ctx, + context: &context.Context{ + BuildDir: tmpDir, + }, } testFilename := "build-dir-file.sh" @@ -49,6 +30,6 @@ func TestGenerateBuildDirFilename(t *testing.T) { filename := builder.generateBuildDirFilename(testFilename) // Verify - expectedFilename := filepath.Join(ctx.BuildDir, testFilename) + expectedFilename := filepath.Join(builder.context.BuildDir, testFilename) require.Equal(t, expectedFilename, filename) } diff --git a/pkg/build/grub_test.go b/pkg/build/grub_test.go index 03a799c0..5aa4f080 100644 --- a/pkg/build/grub_test.go +++ b/pkg/build/grub_test.go @@ -10,12 +10,13 @@ import ( func TestGenerateGRUBGuestfishCommands(t *testing.T) { // Setup - imageConfig := config.ImageConfig{ - OperatingSystem: config.OperatingSystem{ - KernelArgs: []string{"alpha", "beta"}, + builder := Builder{ + imageConfig: &config.ImageConfig{ + OperatingSystem: config.OperatingSystem{ + KernelArgs: []string{"alpha", "beta"}, + }, }, } - builder := New(&imageConfig, nil) // Test commandString, err := builder.generateGRUBGuestfishCommands() @@ -33,10 +34,11 @@ func TestGenerateGRUBGuestfishCommands(t *testing.T) { func TestGenerateGRUBGuestfishCommandsNoArgs(t *testing.T) { // Setup - imageConfig := config.ImageConfig{ - OperatingSystem: config.OperatingSystem{}, + builder := Builder{ + imageConfig: &config.ImageConfig{ + OperatingSystem: config.OperatingSystem{}, + }, } - builder := New(&imageConfig, nil) // Test commandString, err := builder.generateGRUBGuestfishCommands() diff --git a/pkg/build/iso_test.go b/pkg/build/iso_test.go index e0707a04..a8236cf3 100644 --- a/pkg/build/iso_test.go +++ b/pkg/build/iso_test.go @@ -17,15 +17,16 @@ func TestDeleteNoExistingImage(t *testing.T) { require.NoError(t, err) defer os.RemoveAll(tmpDir) - imageConfig := config.ImageConfig{ - Image: config.Image{ - OutputImageName: "not-there", + builder := Builder{ + imageConfig: &config.ImageConfig{ + Image: config.Image{ + OutputImageName: "not-there", + }, + }, + context: &context.Context{ + ImageConfigDir: tmpDir, }, } - ctx := context.Context{ - ImageConfigDir: tmpDir, - } - builder := New(&imageConfig, &ctx) // Test err = builder.deleteExistingOutputIso() @@ -40,15 +41,16 @@ func TestDeleteExistingImage(t *testing.T) { require.NoError(t, err) defer os.RemoveAll(tmpDir) - imageConfig := config.ImageConfig{ - Image: config.Image{ - OutputImageName: "not-there", + builder := Builder{ + imageConfig: &config.ImageConfig{ + Image: config.Image{ + OutputImageName: "not-there", + }, + }, + context: &context.Context{ + ImageConfigDir: tmpDir, }, } - ctx := context.Context{ - ImageConfigDir: tmpDir, - } - builder := New(&imageConfig, &ctx) _, err = os.Create(builder.generateOutputImageFilename()) require.NoError(t, err) @@ -66,17 +68,18 @@ func TestDeleteExistingImage(t *testing.T) { func TestCreateXorrisoCommand(t *testing.T) { // Setup - imageConfig := config.ImageConfig{ - Image: config.Image{ - BaseImage: "base-image", - OutputImageName: "build-image", + builder := Builder{ + imageConfig: &config.ImageConfig{ + Image: config.Image{ + BaseImage: "base-image", + OutputImageName: "build-image", + }, + }, + context: &context.Context{ + ImageConfigDir: "config-dir", + CombustionDir: "combustion", }, } - ctx := context.Context{ - ImageConfigDir: "config-dir", - CombustionDir: "combustion", - } - builder := New(&imageConfig, &ctx) // Test cmd, logfile, err := builder.createXorrisoCommand() diff --git a/pkg/build/message.go b/pkg/build/message.go deleted file mode 100644 index a87f4474..00000000 --- a/pkg/build/message.go +++ /dev/null @@ -1,26 +0,0 @@ -package build - -import ( - _ "embed" - "fmt" - "os" - - "github.com/suse-edge/edge-image-builder/pkg/fileio" -) - -const ( - messageScriptName = "message.sh" -) - -//go:embed scripts/message/message.sh -var messageScript string - -func (b *Builder) configureMessage() (string, error) { - filename := b.generateCombustionDirFilename(messageScriptName) - - if err := os.WriteFile(filename, []byte(messageScript), fileio.ExecutablePerms); err != nil { - return "", fmt.Errorf("copying script %s: %w", messageScriptName, err) - } - - return messageScriptName, nil -} diff --git a/pkg/build/message_test.go b/pkg/build/message_test.go deleted file mode 100644 index f9e0bd14..00000000 --- a/pkg/build/message_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package build - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/suse-edge/edge-image-builder/pkg/context" -) - -func TestConfigureMessage(t *testing.T) { - // Setup - ctx, err := context.NewContext("", "", true) - require.NoError(t, err) - defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) - }() - - builder := Builder{context: ctx} - - // Test - script, err := builder.configureMessage() - - // Verify - require.NoError(t, err) - - _, err = os.Stat(filepath.Join(builder.context.CombustionDir, messageScriptName)) - require.NoError(t, err) - - assert.Equal(t, messageScriptName, script) -} diff --git a/pkg/build/raw_test.go b/pkg/build/raw_test.go index 45c98c5c..049edb82 100644 --- a/pkg/build/raw_test.go +++ b/pkg/build/raw_test.go @@ -14,16 +14,17 @@ import ( func TestCreateRawImageCopyCommand(t *testing.T) { // Setup - imageConfig := config.ImageConfig{ - Image: config.Image{ - BaseImage: "base-image", - OutputImageName: "build-image", + builder := Builder{ + imageConfig: &config.ImageConfig{ + Image: config.Image{ + BaseImage: "base-image", + OutputImageName: "build-image", + }, + }, + context: &context.Context{ + ImageConfigDir: "config-dir", }, } - ctx := context.Context{ - ImageConfigDir: "config-dir", - } - builder := New(&imageConfig, &ctx) // Test cmd := builder.createRawImageCopyCommand() @@ -46,18 +47,20 @@ func TestWriteModifyScript(t *testing.T) { require.NoError(t, err) defer os.RemoveAll(tmpDir) - imageConfig := config.ImageConfig{ - Image: config.Image{ - OutputImageName: "output-image", + builder := Builder{ + imageConfig: &config.ImageConfig{ + Image: config.Image{ + OutputImageName: "output-image", + }, + OperatingSystem: config.OperatingSystem{ + KernelArgs: []string{"alpha", "beta"}, + }, }, - OperatingSystem: config.OperatingSystem{ - KernelArgs: []string{"alpha", "beta"}, + context: &context.Context{ + ImageConfigDir: "config-dir", + BuildDir: tmpDir, }, } - ctx, err := context.NewContext("config-dir", tmpDir, false) - require.NoError(t, err) - - builder := New(&imageConfig, ctx) // Test err = builder.writeModifyScript() diff --git a/pkg/build/rpm_test.go b/pkg/build/rpm_test.go deleted file mode 100644 index 26fed255..00000000 --- a/pkg/build/rpm_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package build - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/suse-edge/edge-image-builder/pkg/context" - "github.com/suse-edge/edge-image-builder/pkg/fileio" -) - -func setupRPMSourceDir(t *testing.T, addFiles bool) (tmpDir string, rpmSourceDir string, teardown func()) { - tmpDir, err := os.MkdirTemp("", "eib-RPM-") - require.NoError(t, err) - - rpmSourceDir = filepath.Join(tmpDir, "rpms") - err = os.Mkdir(rpmSourceDir, 0o755) - require.NoError(t, err) - - var file1 *os.File - var file2 *os.File - if addFiles { - file1Path := filepath.Join(rpmSourceDir, "rpm1.rpm") - file1, err = os.Create(file1Path) - require.NoError(t, err) - - file2Path := filepath.Join(rpmSourceDir, "rpm2.rpm") - file2, err = os.Create(file2Path) - require.NoError(t, err) - } - - return tmpDir, rpmSourceDir, func() { - if addFiles { - assert.NoError(t, file1.Close()) - assert.NoError(t, file2.Close()) - } - assert.NoError(t, os.RemoveAll(tmpDir)) - } -} - -func TestGetRPMFileNames(t *testing.T) { - // Setup - _, rpmSourceDir, teardown := setupRPMSourceDir(t, true) - defer teardown() - - // Test - rpmFileNames, err := getRPMFileNames(rpmSourceDir) - - // Verify - require.NoError(t, err) - - assert.Contains(t, rpmFileNames, "rpm1.rpm") - assert.Contains(t, rpmFileNames, "rpm2.rpm") -} - -func TestCopyRPMs(t *testing.T) { - // Setup - tmpDir, rpmSourceDir, teardown := setupRPMSourceDir(t, true) - defer teardown() - - tmpDestDir := filepath.Join(tmpDir, "temp-dest-dir") - err := os.Mkdir(tmpDestDir, 0o755) - require.NoError(t, err) - - // Test - err = copyRPMs(rpmSourceDir, tmpDestDir, []string{"rpm1.rpm", "rpm2.rpm"}) - - // Verify - require.NoError(t, err) - - _, err = os.Stat(filepath.Join(tmpDestDir, "rpm1.rpm")) - require.NoError(t, err) - - _, err = os.Stat(filepath.Join(tmpDestDir, "rpm2.rpm")) - require.NoError(t, err) -} - -func TestGetRPMFileNamesNoRPMs(t *testing.T) { - // Setup - _, rpmSourceDir, teardown := setupRPMSourceDir(t, false) - defer teardown() - - // Test - rpmFileNames, err := getRPMFileNames(rpmSourceDir) - - // Verify - require.ErrorContains(t, err, "no RPMs found") - - assert.Empty(t, rpmFileNames) -} - -func TestCopyRPMsNoRPMDestDir(t *testing.T) { - // Setup - _, rpmSourceDir, teardown := setupRPMSourceDir(t, true) - defer teardown() - - // Test - err := copyRPMs(rpmSourceDir, "", []string{"rpm1.rpm", "rpm2.rpm"}) - - // Verify - require.ErrorContains(t, err, "RPM destination directory cannot be empty") -} - -func TestCopyRPMsNoRPMSrcDir(t *testing.T) { - // Setup - tmpDestDir, _, teardown := setupRPMSourceDir(t, true) - defer teardown() - - // Test - err := copyRPMs("", tmpDestDir, []string{"rpm1.rpm", "rpm2.rpm"}) - - // Verify - require.ErrorContains(t, err, "opening source file") -} - -func TestWriteRPMScript(t *testing.T) { - // Setup - ctx, err := context.NewContext("", "", true) - require.NoError(t, err) - defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) - }() - - builder := Builder{context: ctx} - - // Test - script, err := builder.writeRPMScript([]string{"rpm1.rpm", "rpm2.rpm"}) - - // Verify - require.NoError(t, err) - - assert.Equal(t, modifyRPMScriptName, script) - - expectedFilename := filepath.Join(builder.context.CombustionDir, modifyRPMScriptName) - foundBytes, err := os.ReadFile(expectedFilename) - require.NoError(t, err) - - stats, err := os.Stat(expectedFilename) - require.NoError(t, err) - assert.Equal(t, fileio.ExecutablePerms, stats.Mode()) - - foundContents := string(foundBytes) - assert.Contains(t, foundContents, "rpm1.rpm") - assert.Contains(t, foundContents, "rpm2.rpm") -} - -func TestProcessRPMs(t *testing.T) { - // Setup - tmpDir, _, teardown := setupRPMSourceDir(t, true) - defer teardown() - - ctx, err := context.NewContext(tmpDir, "", true) - require.NoError(t, err) - defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) - }() - - builder := Builder{context: ctx} - - // Test - script, err := builder.processRPMs() - - // Verify - require.NoError(t, err) - - assert.Equal(t, modifyRPMScriptName, script) - - _, err = os.Stat(filepath.Join(builder.context.CombustionDir, "rpm1.rpm")) - require.NoError(t, err) - - _, err = os.Stat(filepath.Join(builder.context.CombustionDir, "rpm2.rpm")) - require.NoError(t, err) - - expectedFilename := filepath.Join(builder.context.CombustionDir, modifyRPMScriptName) - foundBytes, err := os.ReadFile(expectedFilename) - require.NoError(t, err) - - foundContents := string(foundBytes) - assert.Contains(t, foundContents, "rpm1.rpm") - assert.Contains(t, foundContents, "rpm2.rpm") -} - -func TestGenerateRPMPath(t *testing.T) { - // Setup - tmpDir, expectedPath, teardown := setupRPMSourceDir(t, false) - defer teardown() - - ctx, err := context.NewContext(tmpDir, "", true) - require.NoError(t, err) - defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) - }() - - builder := Builder{context: ctx} - - // Test - generatedPath, err := builder.generateRPMPath() - - // Verify - require.NoError(t, err) - - assert.Equal(t, expectedPath, generatedPath) -} diff --git a/pkg/build/users.go b/pkg/build/users.go deleted file mode 100644 index 9a25137b..00000000 --- a/pkg/build/users.go +++ /dev/null @@ -1,37 +0,0 @@ -package build - -import ( - _ "embed" - "fmt" - "os" - - "github.com/suse-edge/edge-image-builder/pkg/fileio" - "github.com/suse-edge/edge-image-builder/pkg/template" -) - -const ( - usersScriptName = "add-users.sh" -) - -//go:embed scripts/users/add-users.sh.tpl -var usersScript string - -func (b *Builder) configureUsers() (string, error) { - // Punch out early if there are no users - if len(b.imageConfig.OperatingSystem.Users) == 0 { - return "", nil - } - - data, err := template.Parse(usersScriptName, usersScript, b.imageConfig.OperatingSystem.Users) - if err != nil { - return "", fmt.Errorf("parsing users script template: %w", err) - } - - filename := b.generateCombustionDirFilename(usersScriptName) - err = os.WriteFile(filename, []byte(data), fileio.ExecutablePerms) - if err != nil { - return "", fmt.Errorf("writing %s to the combustion directory: %w", usersScriptName, err) - } - - return usersScriptName, nil -} diff --git a/pkg/combustion/combustion.go b/pkg/combustion/combustion.go index fc6e1130..1e1c1350 100644 --- a/pkg/combustion/combustion.go +++ b/pkg/combustion/combustion.go @@ -1,37 +1,52 @@ package combustion import ( - _ "embed" "fmt" - "slices" - "strings" -) - -//go:embed scripts/script_base.sh -var combustionScriptBase string + "os" + "path/filepath" -func GenerateScript(scripts []string) (string, error) { - b := new(strings.Builder) + "github.com/suse-edge/edge-image-builder/pkg/context" + "github.com/suse-edge/edge-image-builder/pkg/fileio" +) - _, err := b.WriteString(combustionScriptBase) - if err != nil { - return "", fmt.Errorf("writing script base: %w", err) +// configureComponent defines the combustion component contract. +// Each component (e.g. "users") receives the necessary dir structure and +// additional values it should be operating with through a Context object. +// +// configureComponent returns a slice of scripts which should be executed as part of the Combustion script. +// Result can also be an empty slice or nil if this is not necessary. +type configureComponent func(context *context.Context) ([]string, error) + +// Configure iterates over all separate Combustion components and configures them independently. +// If all of those are successful, the Combustion script is assembled and written to the file system. +func Configure(ctx *context.Context) error { + var combustionScripts []string + + combustionComponents := map[string]configureComponent{ + "message": configureMessage, + "users": configureUsers, + "rpm": configureRPMs, + "custom": configureCustomScripts, } - // Use alphabetical ordering for determinism - slices.Sort(scripts) - - // Add a call to each script that was added to the combustion directory - for _, filename := range scripts { - _, err = b.WriteString(scriptExecutor(filename)) + for componentName, configureFunc := range combustionComponents { + scripts, err := configureFunc(ctx) if err != nil { - return "", fmt.Errorf("appending script %s: %w", filename, err) + return fmt.Errorf("configuring component %q: %w", componentName, err) } + + combustionScripts = append(combustionScripts, scripts...) } - return b.String(), nil -} + script, err := assembleScript(combustionScripts) + if err != nil { + return fmt.Errorf("assembling script: %w", err) + } + + filename := filepath.Join(ctx.CombustionDir, "script") + if err = os.WriteFile(filename, []byte(script), fileio.ExecutablePerms); err != nil { + return fmt.Errorf("writing script: %w", err) + } -func scriptExecutor(name string) string { - return fmt.Sprintf("./%s\n", name) + return nil } diff --git a/pkg/combustion/combustion_test.go b/pkg/combustion/combustion_test.go index e7c3610b..cb0c8c14 100644 --- a/pkg/combustion/combustion_test.go +++ b/pkg/combustion/combustion_test.go @@ -1,16 +1,34 @@ package combustion import ( + "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/suse-edge/edge-image-builder/pkg/config" + "github.com/suse-edge/edge-image-builder/pkg/context" ) -func TestGenerateScript(t *testing.T) { - script, err := GenerateScript([]string{"foo.sh", "bar.sh", "baz.sh"}) +func setupContext(t *testing.T) (ctx *context.Context, teardown func()) { + configDir, err := os.MkdirTemp("", "eib-config-") require.NoError(t, err) - // alphabetic ordering - assert.Contains(t, script, "./bar.sh\n./baz.sh\n./foo.sh") + buildDir, err := os.MkdirTemp("", "eib-build-") + require.NoError(t, err) + + combustionDir, err := os.MkdirTemp("", "eib-combustion-") + require.NoError(t, err) + + ctx = &context.Context{ + ImageConfigDir: configDir, + BuildDir: buildDir, + CombustionDir: combustionDir, + ImageConfig: &config.ImageConfig{}, + } + + return ctx, func() { + assert.NoError(t, os.RemoveAll(buildDir)) + assert.NoError(t, os.RemoveAll(combustionDir)) + } } diff --git a/pkg/build/scripts.go b/pkg/combustion/custom.go similarity index 80% rename from pkg/build/scripts.go rename to pkg/combustion/custom.go index 8e64481d..b02c802f 100644 --- a/pkg/build/scripts.go +++ b/pkg/combustion/custom.go @@ -1,10 +1,11 @@ -package build +package combustion import ( "fmt" "os" "path/filepath" + "github.com/suse-edge/edge-image-builder/pkg/context" "github.com/suse-edge/edge-image-builder/pkg/fileio" ) @@ -12,8 +13,8 @@ const ( scriptsDir = "scripts" ) -func (b *Builder) configureCustomScripts() ([]string, error) { - fullScriptsDir := filepath.Join(b.context.ImageConfigDir, scriptsDir) +func configureCustomScripts(ctx *context.Context) ([]string, error) { + fullScriptsDir := filepath.Join(ctx.ImageConfigDir, scriptsDir) // Nothing to do if the image config dir doesn't have the scripts directory _, err := os.Stat(fullScriptsDir) @@ -38,7 +39,7 @@ func (b *Builder) configureCustomScripts() ([]string, error) { for _, scriptEntry := range dirListing { copyMe := filepath.Join(fullScriptsDir, scriptEntry.Name()) - copyTo := filepath.Join(b.context.CombustionDir, scriptEntry.Name()) + copyTo := filepath.Join(ctx.CombustionDir, scriptEntry.Name()) err = fileio.CopyFile(copyMe, copyTo, fileio.ExecutablePerms) if err != nil { diff --git a/pkg/build/scripts_test.go b/pkg/combustion/custom_test.go similarity index 81% rename from pkg/build/scripts_test.go rename to pkg/combustion/custom_test.go index b7bc7fa8..fe482dba 100644 --- a/pkg/build/scripts_test.go +++ b/pkg/combustion/custom_test.go @@ -1,4 +1,4 @@ -package build +package combustion import ( "os" @@ -34,15 +34,13 @@ func TestConfigureScripts(t *testing.T) { require.NoError(t, err) defer os.RemoveAll(tmpDestDir) - builder := &Builder{ - context: &context.Context{ - ImageConfigDir: tmpSrcDir, - CombustionDir: tmpDestDir, - }, + ctx := &context.Context{ + ImageConfigDir: tmpSrcDir, + CombustionDir: tmpDestDir, } // Test - scripts, err := builder.configureCustomScripts() + scripts, err := configureCustomScripts(ctx) // Verify require.NoError(t, err) @@ -54,7 +52,7 @@ func TestConfigureScripts(t *testing.T) { // - make sure the copied files have the right permissions for _, entry := range foundDirListing { - fullEntryPath := filepath.Join(builder.context.CombustionDir, entry.Name()) + fullEntryPath := filepath.Join(ctx.CombustionDir, entry.Name()) stats, err := os.Stat(fullEntryPath) require.NoError(t, err) assert.Equal(t, fileio.ExecutablePerms, stats.Mode()) @@ -71,14 +69,12 @@ func TestConfigureScriptsNoScriptsDir(t *testing.T) { require.NoError(t, err) defer os.RemoveAll(tmpSrcDir) - builder := &Builder{ - context: &context.Context{ - ImageConfigDir: tmpSrcDir, - }, + ctx := &context.Context{ + ImageConfigDir: tmpSrcDir, } // Test - scripts, err := builder.configureCustomScripts() + scripts, err := configureCustomScripts(ctx) // Verify require.NoError(t, err) @@ -97,14 +93,12 @@ func TestConfigureScriptsEmptyScriptsDir(t *testing.T) { err = os.MkdirAll(fullScriptsDir, os.ModePerm) require.NoError(t, err) - builder := &Builder{ - context: &context.Context{ - ImageConfigDir: tmpSrcDir, - }, + ctx := &context.Context{ + ImageConfigDir: tmpSrcDir, } // Test - scripts, err := builder.configureCustomScripts() + scripts, err := configureCustomScripts(ctx) // Verify require.Error(t, err) diff --git a/pkg/combustion/message.go b/pkg/combustion/message.go new file mode 100644 index 00000000..3c6dcd39 --- /dev/null +++ b/pkg/combustion/message.go @@ -0,0 +1,28 @@ +package combustion + +import ( + _ "embed" + "fmt" + "os" + "path/filepath" + + "github.com/suse-edge/edge-image-builder/pkg/context" + "github.com/suse-edge/edge-image-builder/pkg/fileio" +) + +const ( + messageScriptName = "message.sh" +) + +//go:embed scripts/message.sh +var messageScript string + +func configureMessage(ctx *context.Context) ([]string, error) { + filename := filepath.Join(ctx.CombustionDir, messageScriptName) + + if err := os.WriteFile(filename, []byte(messageScript), fileio.ExecutablePerms); err != nil { + return nil, fmt.Errorf("copying script %s: %w", messageScriptName, err) + } + + return []string{messageScriptName}, nil +} diff --git a/pkg/combustion/message_test.go b/pkg/combustion/message_test.go new file mode 100644 index 00000000..1989be60 --- /dev/null +++ b/pkg/combustion/message_test.go @@ -0,0 +1,28 @@ +package combustion + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestConfigureMessage(t *testing.T) { + // Setup + ctx, teardown := setupContext(t) + defer teardown() + + // Test + scripts, err := configureMessage(ctx) + + // Verify + require.NoError(t, err) + + _, err = os.Stat(filepath.Join(ctx.CombustionDir, messageScriptName)) + require.NoError(t, err) + + require.Len(t, scripts, 1) + assert.Equal(t, messageScriptName, scripts[0]) +} diff --git a/pkg/build/rpm.go b/pkg/combustion/rpm.go similarity index 69% rename from pkg/build/rpm.go rename to pkg/combustion/rpm.go index 4f8e9397..bced7546 100644 --- a/pkg/build/rpm.go +++ b/pkg/combustion/rpm.go @@ -1,4 +1,4 @@ -package build +package combustion import ( _ "embed" @@ -7,6 +7,7 @@ import ( "path/filepath" "strings" + "github.com/suse-edge/edge-image-builder/pkg/context" "github.com/suse-edge/edge-image-builder/pkg/fileio" "github.com/suse-edge/edge-image-builder/pkg/template" ) @@ -15,35 +16,35 @@ const ( modifyRPMScriptName = "10-rpm-install.sh" ) -//go:embed scripts/rpms/10-rpm-install.sh.tpl +//go:embed scripts/10-rpm-install.sh.tpl var modifyRPMScript string -func (b *Builder) processRPMs() (string, error) { - rpmSourceDir, err := b.generateRPMPath() +func configureRPMs(ctx *context.Context) ([]string, error) { + rpmSourceDir, err := generateRPMPath(ctx) if err != nil { - return "", fmt.Errorf("generating RPM path: %w", err) + return nil, fmt.Errorf("generating RPM path: %w", err) } // Only proceed with processing the RPMs if the directory exists if rpmSourceDir == "" { - return "", nil + return nil, nil } rpmFileNames, err := getRPMFileNames(rpmSourceDir) if err != nil { - return "", fmt.Errorf("getting RPM file names: %w", err) + return nil, fmt.Errorf("getting RPM file names: %w", err) } - err = copyRPMs(rpmSourceDir, b.context.CombustionDir, rpmFileNames) + err = copyRPMs(rpmSourceDir, ctx.CombustionDir, rpmFileNames) if err != nil { - return "", fmt.Errorf("copying RPMs over: %w", err) + return nil, fmt.Errorf("copying RPMs over: %w", err) } - script, err := b.writeRPMScript(rpmFileNames) + script, err := writeRPMScript(ctx, rpmFileNames) if err != nil { - return "", fmt.Errorf("writing the RPM install script %s: %w", modifyRPMScriptName, err) + return nil, fmt.Errorf("writing the RPM install script %s: %w", modifyRPMScriptName, err) } - return script, nil + return []string{script}, nil } func getRPMFileNames(rpmSourceDir string) ([]string, error) { @@ -84,7 +85,7 @@ func copyRPMs(rpmSourceDir string, rpmDestDir string, rpmFileNames []string) err return nil } -func (b *Builder) writeRPMScript(rpmFileNames []string) (string, error) { +func writeRPMScript(ctx *context.Context, rpmFileNames []string) (string, error) { values := struct { RPMs string }{ @@ -96,7 +97,7 @@ func (b *Builder) writeRPMScript(rpmFileNames []string) (string, error) { return "", fmt.Errorf("parsing RPM script template: %w", err) } - filename := b.generateCombustionDirFilename(modifyRPMScriptName) + filename := filepath.Join(ctx.CombustionDir, modifyRPMScriptName) err = os.WriteFile(filename, []byte(data), fileio.ExecutablePerms) if err != nil { return "", fmt.Errorf("writing RPM script: %w", err) @@ -105,8 +106,8 @@ func (b *Builder) writeRPMScript(rpmFileNames []string) (string, error) { return modifyRPMScriptName, nil } -func (b *Builder) generateRPMPath() (string, error) { - rpmSourceDir := filepath.Join(b.context.ImageConfigDir, "rpms") +func generateRPMPath(ctx *context.Context) (string, error) { + rpmSourceDir := filepath.Join(ctx.ImageConfigDir, "rpms") _, err := os.Stat(rpmSourceDir) if err != nil { if os.IsNotExist(err) { diff --git a/pkg/combustion/rpm_test.go b/pkg/combustion/rpm_test.go new file mode 100644 index 00000000..39401a1c --- /dev/null +++ b/pkg/combustion/rpm_test.go @@ -0,0 +1,188 @@ +package combustion + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/suse-edge/edge-image-builder/pkg/context" + "github.com/suse-edge/edge-image-builder/pkg/fileio" +) + +func setupRPMSourceDir(t *testing.T) (ctx *context.Context, rpmSourceDir string, teardown func()) { + ctx, teardownCtx := setupContext(t) + + rpmSourceDir = filepath.Join(ctx.ImageConfigDir, "rpms") + require.NoError(t, os.Mkdir(rpmSourceDir, 0o755)) + + file1, err := os.Create(filepath.Join(rpmSourceDir, "rpm1.rpm")) + require.NoError(t, err) + + file2, err := os.Create(filepath.Join(rpmSourceDir, "rpm2.rpm")) + require.NoError(t, err) + + return ctx, rpmSourceDir, func() { + assert.NoError(t, file1.Close()) + assert.NoError(t, file2.Close()) + + teardownCtx() + } +} + +func TestGetRPMFileNames(t *testing.T) { + // Setup + _, rpmSourceDir, teardown := setupRPMSourceDir(t) + defer teardown() + + // Test + rpmFileNames, err := getRPMFileNames(rpmSourceDir) + + // Verify + require.NoError(t, err) + + assert.Contains(t, rpmFileNames, "rpm1.rpm") + assert.Contains(t, rpmFileNames, "rpm2.rpm") +} + +func TestCopyRPMs(t *testing.T) { + // Setup + ctx, rpmSourceDir, teardown := setupRPMSourceDir(t) + defer teardown() + + tmpDestDir := filepath.Join(ctx.BuildDir, "temp-dest-dir") + require.NoError(t, os.Mkdir(tmpDestDir, 0o755)) + + // Test + require.NoError(t, copyRPMs(rpmSourceDir, tmpDestDir, []string{"rpm1.rpm", "rpm2.rpm"})) + + // Verify + _, err := os.Stat(filepath.Join(tmpDestDir, "rpm1.rpm")) + require.NoError(t, err) + + _, err = os.Stat(filepath.Join(tmpDestDir, "rpm2.rpm")) + require.NoError(t, err) +} + +func TestGetRPMFileNamesNoRPMs(t *testing.T) { + // Setup + tmpDir, err := os.MkdirTemp("", "eib-rpm-") + require.NoError(t, err) + defer func() { + assert.NoError(t, os.RemoveAll(tmpDir)) + }() + + // Test + rpmFileNames, err := getRPMFileNames(tmpDir) + + // Verify + require.ErrorContains(t, err, "no RPMs found") + + assert.Empty(t, rpmFileNames) +} + +func TestCopyRPMsNoRPMDestDir(t *testing.T) { + // Setup + tmpDir, err := os.MkdirTemp("", "eib-rpm-") + require.NoError(t, err) + defer func() { + assert.NoError(t, os.RemoveAll(tmpDir)) + }() + + // Test + err = copyRPMs(tmpDir, "", []string{"rpm1.rpm", "rpm2.rpm"}) + + // Verify + require.ErrorContains(t, err, "RPM destination directory cannot be empty") +} + +func TestCopyRPMsNoRPMSrcDir(t *testing.T) { + // Setup + tmpDir, err := os.MkdirTemp("", "eib-rpm-") + require.NoError(t, err) + defer func() { + assert.NoError(t, os.RemoveAll(tmpDir)) + }() + + // Test + err = copyRPMs("", tmpDir, []string{"rpm1.rpm", "rpm2.rpm"}) + + // Verify + require.ErrorContains(t, err, "opening source file") +} + +func TestWriteRPMScript(t *testing.T) { + // Setup + ctx, teardown := setupContext(t) + defer teardown() + + // Test + script, err := writeRPMScript(ctx, []string{"rpm1.rpm", "rpm2.rpm"}) + + // Verify + require.NoError(t, err) + + assert.Equal(t, modifyRPMScriptName, script) + + expectedFilename := filepath.Join(ctx.CombustionDir, modifyRPMScriptName) + foundBytes, err := os.ReadFile(expectedFilename) + require.NoError(t, err) + + stats, err := os.Stat(expectedFilename) + require.NoError(t, err) + assert.Equal(t, fileio.ExecutablePerms, stats.Mode()) + + foundContents := string(foundBytes) + assert.Contains(t, foundContents, "rpm1.rpm") + assert.Contains(t, foundContents, "rpm2.rpm") +} + +func TestConfigureRPMs(t *testing.T) { + // Setup + ctx, _, teardown := setupRPMSourceDir(t) + defer teardown() + + // Test + scripts, err := configureRPMs(ctx) + + // Verify + require.NoError(t, err) + + require.Len(t, scripts, 1) + assert.Equal(t, modifyRPMScriptName, scripts[0]) + + _, err = os.Stat(filepath.Join(ctx.CombustionDir, "rpm1.rpm")) + require.NoError(t, err) + + _, err = os.Stat(filepath.Join(ctx.CombustionDir, "rpm2.rpm")) + require.NoError(t, err) + + expectedFilename := filepath.Join(ctx.CombustionDir, modifyRPMScriptName) + foundBytes, err := os.ReadFile(expectedFilename) + require.NoError(t, err) + + foundContents := string(foundBytes) + assert.Contains(t, foundContents, "rpm1.rpm") + assert.Contains(t, foundContents, "rpm2.rpm") +} + +func TestGenerateRPMPath(t *testing.T) { + // Setup + ctx, teardown := setupContext(t) + defer teardown() + + rpmDir := filepath.Join(ctx.ImageConfigDir, "rpms") + require.NoError(t, os.Mkdir(rpmDir, 0o755)) + defer func() { + assert.NoError(t, os.RemoveAll(rpmDir)) + }() + + // Test + generatedPath, err := generateRPMPath(ctx) + + // Verify + require.NoError(t, err) + + assert.Equal(t, rpmDir, generatedPath) +} diff --git a/pkg/combustion/script.go b/pkg/combustion/script.go new file mode 100644 index 00000000..3e082a1e --- /dev/null +++ b/pkg/combustion/script.go @@ -0,0 +1,37 @@ +package combustion + +import ( + _ "embed" + "fmt" + "slices" + "strings" +) + +//go:embed scripts/script_base.sh +var combustionScriptBase string + +func assembleScript(scripts []string) (string, error) { + b := new(strings.Builder) + + _, err := b.WriteString(combustionScriptBase) + if err != nil { + return "", fmt.Errorf("writing script base: %w", err) + } + + // Use alphabetical ordering for determinism + slices.Sort(scripts) + + // Add a call to each script that was added to the combustion directory + for _, filename := range scripts { + _, err = b.WriteString(scriptExecutor(filename)) + if err != nil { + return "", fmt.Errorf("appending script %s: %w", filename, err) + } + } + + return b.String(), nil +} + +func scriptExecutor(name string) string { + return fmt.Sprintf("./%s\n", name) +} diff --git a/pkg/combustion/script_test.go b/pkg/combustion/script_test.go new file mode 100644 index 00000000..ca1c7d54 --- /dev/null +++ b/pkg/combustion/script_test.go @@ -0,0 +1,16 @@ +package combustion + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAssembleScript(t *testing.T) { + script, err := assembleScript([]string{"foo.sh", "bar.sh", "baz.sh"}) + require.NoError(t, err) + + // alphabetic ordering + assert.Contains(t, script, "./bar.sh\n./baz.sh\n./foo.sh") +} diff --git a/pkg/build/scripts/rpms/10-rpm-install.sh.tpl b/pkg/combustion/scripts/10-rpm-install.sh.tpl similarity index 100% rename from pkg/build/scripts/rpms/10-rpm-install.sh.tpl rename to pkg/combustion/scripts/10-rpm-install.sh.tpl diff --git a/pkg/build/scripts/users/add-users.sh.tpl b/pkg/combustion/scripts/add-users.sh.tpl similarity index 100% rename from pkg/build/scripts/users/add-users.sh.tpl rename to pkg/combustion/scripts/add-users.sh.tpl diff --git a/pkg/build/scripts/message/message.sh b/pkg/combustion/scripts/message.sh similarity index 100% rename from pkg/build/scripts/message/message.sh rename to pkg/combustion/scripts/message.sh diff --git a/pkg/combustion/users.go b/pkg/combustion/users.go new file mode 100644 index 00000000..096538c1 --- /dev/null +++ b/pkg/combustion/users.go @@ -0,0 +1,39 @@ +package combustion + +import ( + _ "embed" + "fmt" + "os" + "path/filepath" + + "github.com/suse-edge/edge-image-builder/pkg/context" + "github.com/suse-edge/edge-image-builder/pkg/fileio" + "github.com/suse-edge/edge-image-builder/pkg/template" +) + +const ( + usersScriptName = "add-users.sh" +) + +//go:embed scripts/add-users.sh.tpl +var usersScript string + +func configureUsers(ctx *context.Context) ([]string, error) { + // Punch out early if there are no users + if len(ctx.OperatingSystem.Users) == 0 { + return nil, nil + } + + data, err := template.Parse(usersScriptName, usersScript, ctx.OperatingSystem.Users) + if err != nil { + return nil, fmt.Errorf("parsing users script template: %w", err) + } + + filename := filepath.Join(ctx.CombustionDir, usersScriptName) + err = os.WriteFile(filename, []byte(data), fileio.ExecutablePerms) + if err != nil { + return nil, fmt.Errorf("writing %s to the combustion directory: %w", usersScriptName, err) + } + + return []string{usersScriptName}, nil +} diff --git a/pkg/build/users_test.go b/pkg/combustion/users_test.go similarity index 79% rename from pkg/build/users_test.go rename to pkg/combustion/users_test.go index 43e36934..915e4edc 100644 --- a/pkg/build/users_test.go +++ b/pkg/combustion/users_test.go @@ -1,4 +1,4 @@ -package build +package combustion import ( "os" @@ -8,13 +8,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/suse-edge/edge-image-builder/pkg/config" - "github.com/suse-edge/edge-image-builder/pkg/context" "github.com/suse-edge/edge-image-builder/pkg/fileio" ) func TestConfigureUsers(t *testing.T) { // Setup - imageConfig := &config.ImageConfig{ + ctx, teardown := setupContext(t) + defer teardown() + + ctx.ImageConfig = &config.ImageConfig{ OperatingSystem: config.OperatingSystem{ Users: []config.OperatingSystemUser{ { @@ -39,24 +41,14 @@ func TestConfigureUsers(t *testing.T) { }, } - ctx, err := context.NewContext("", "", true) - require.NoError(t, err) - defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) - }() - - builder := &Builder{ - imageConfig: imageConfig, - context: ctx, - } - // Test - script, err := builder.configureUsers() + scripts, err := configureUsers(ctx) // Verify require.NoError(t, err) - assert.Equal(t, usersScriptName, script) + require.Len(t, scripts, 1) + assert.Equal(t, usersScriptName, scripts[0]) expectedFilename := filepath.Join(ctx.CombustionDir, usersScriptName) foundBytes, err := os.ReadFile(expectedFilename) @@ -99,24 +91,16 @@ func TestConfigureUsers(t *testing.T) { func TestConfigureUsers_NoUsers(t *testing.T) { // Setup - ctx, err := context.NewContext("", "", true) - require.NoError(t, err) - defer func() { - assert.NoError(t, context.CleanUpBuildDir(ctx)) - }() - - builder := &Builder{ - imageConfig: &config.ImageConfig{}, - context: ctx, - } + ctx, teardown := setupContext(t) + defer teardown() // Test - script, err := builder.configureUsers() + scripts, err := configureUsers(ctx) // Verify require.NoError(t, err) - assert.Equal(t, "", script) + assert.Len(t, scripts, 0) expectedFilename := filepath.Join(ctx.CombustionDir, usersScriptName) _, err = os.ReadFile(expectedFilename) diff --git a/pkg/context/context.go b/pkg/context/context.go index 6d618599..a92bba52 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -4,6 +4,8 @@ import ( "fmt" "os" "path/filepath" + + "github.com/suse-edge/edge-image-builder/pkg/config" ) type Context struct { @@ -15,9 +17,11 @@ type Context struct { CombustionDir string // DeleteBuildDir indicates whether the BuildDir should be cleaned up after the image is built. DeleteBuildDir bool + // ImageConfig contains the image definition properties. + *config.ImageConfig } -func NewContext(imageConfigDir, buildDir string, deleteBuildDir bool) (*Context, error) { +func NewContext(imageConfigDir, buildDir string, deleteBuildDir bool, imageConfig *config.ImageConfig) (*Context, error) { if buildDir == "" { tmpDir, err := os.MkdirTemp("", "eib-") if err != nil { @@ -36,6 +40,7 @@ func NewContext(imageConfigDir, buildDir string, deleteBuildDir bool) (*Context, BuildDir: buildDir, CombustionDir: combustionDir, DeleteBuildDir: deleteBuildDir, + ImageConfig: imageConfig, }, nil } diff --git a/pkg/context/context_test.go b/pkg/context/context_test.go index 9f47fb09..001472a2 100644 --- a/pkg/context/context_test.go +++ b/pkg/context/context_test.go @@ -10,7 +10,7 @@ import ( ) func TestContext_New(t *testing.T) { - context, err := NewContext("", "", false) + context, err := NewContext("", "", false, nil) require.NoError(t, err) defer os.RemoveAll(context.BuildDir) @@ -25,7 +25,7 @@ func TestContext_New_ExistingBuildDir(t *testing.T) { defer os.RemoveAll(tmpDir) // Test - context, err := NewContext("", tmpDir, false) + context, err := NewContext("", tmpDir, false, nil) require.NoError(t, err) // Verify