Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep custom files' permissions #305

Merged
merged 2 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
* [#242](https://github.com/suse-edge/edge-image-builder/issues/242) - Empty rpms directory triggers resolution
* [#283](https://github.com/suse-edge/edge-image-builder/issues/283) - Definition file argument to EIB is incorrect
* [#245](https://github.com/suse-edge/edge-image-builder/issues/245) - Pass additional arguments to Helm resolver
* [#272](https://github.com/suse-edge/edge-image-builder/issues/272) - Custom files should keep their permissions

---

Expand Down
26 changes: 15 additions & 11 deletions pkg/combustion/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,43 +41,47 @@ func configureCustomFiles(ctx *image.Context) ([]string, error) {

func handleCustomFiles(ctx *image.Context) error {
fullFilesDir := generateComponentPath(ctx, filepath.Join(customDir, customFilesDir))
_, err := copyCustomFiles(fullFilesDir, ctx.CombustionDir, fileio.NonExecutablePerms)
_, err := copyCustomFiles(fullFilesDir, ctx.CombustionDir)
return err
}

func handleCustomScripts(ctx *image.Context) ([]string, error) {
fullScriptsDir := generateComponentPath(ctx, filepath.Join(customDir, customScriptsDir))
scripts, err := copyCustomFiles(fullScriptsDir, ctx.CombustionDir, fileio.ExecutablePerms)
scripts, err := copyCustomFiles(fullScriptsDir, ctx.CombustionDir)
return scripts, err
}

func copyCustomFiles(fromDir, combustionDir string, params os.FileMode) ([]string, error) {
func copyCustomFiles(fromDir, toDir string) ([]string, error) {
if _, err := os.Stat(fromDir); os.IsNotExist(err) {
return nil, nil
}

dirListing, err := os.ReadDir(fromDir)
dirEntries, err := os.ReadDir(fromDir)
if err != nil {
return nil, fmt.Errorf("reading the custom directory at %s: %w", fromDir, err)
}

// If the directory exists but there's nothing in it, consider it an error case
if len(dirListing) == 0 {
if len(dirEntries) == 0 {
return nil, fmt.Errorf("no files found in directory %s", fromDir)
}

var copiedFiles []string

for _, scriptEntry := range dirListing {
copyMe := filepath.Join(fromDir, scriptEntry.Name())
copyTo := filepath.Join(combustionDir, scriptEntry.Name())
for _, entry := range dirEntries {
copyMe := filepath.Join(fromDir, entry.Name())
copyTo := filepath.Join(toDir, entry.Name())

err = fileio.CopyFile(copyMe, copyTo, params)
info, err := entry.Info()
if err != nil {
return nil, fmt.Errorf("copying script to %s: %w", copyTo, err)
return nil, fmt.Errorf("reading file info: %w", err)
}

copiedFiles = append(copiedFiles, scriptEntry.Name())
if err = fileio.CopyFile(copyMe, copyTo, info.Mode()); err != nil {
return nil, fmt.Errorf("copying file to %s: %w", copyTo, err)
}

copiedFiles = append(copiedFiles, entry.Name())
}

return copiedFiles, nil
Expand Down
78 changes: 49 additions & 29 deletions pkg/combustion/custom_test.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,59 @@
package combustion

import (
"io/fs"
"os"
"path/filepath"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/suse-edge/edge-image-builder/pkg/fileio"
)

func TestConfigureCustomFiles(t *testing.T) {
// Setup
ctx, teardown := setupContext(t)
defer teardown()

// - scripts
fullScriptsDir := filepath.Join(ctx.ImageConfigDir, customDir, customScriptsDir)
err := os.MkdirAll(fullScriptsDir, os.ModePerm)
require.NoError(t, err)
scriptsDir := filepath.Join(ctx.ImageConfigDir, customDir, customScriptsDir)
require.NoError(t, os.MkdirAll(scriptsDir, os.ModePerm))

filesDir := filepath.Join(ctx.ImageConfigDir, customDir, customFilesDir)
require.NoError(t, os.MkdirAll(filesDir, os.ModePerm))

files := map[string]struct {
isScript bool
perms fs.FileMode
}{
"foo.sh": {
isScript: true,
perms: 0o744,
},
"bar.sh": {
isScript: true,
perms: 0o755,
},
"baz": {
isScript: false,
perms: 0o744,
},
"qux": {
isScript: false,
perms: 0o644,
},
}

_, err = os.Create(filepath.Join(fullScriptsDir, "foo.sh"))
require.NoError(t, err)
_, err = os.Create(filepath.Join(fullScriptsDir, "bar.sh"))
require.NoError(t, err)
for filename, info := range files {
var path string

// - files
fullFilesDir := filepath.Join(ctx.ImageConfigDir, customDir, customFilesDir)
err = os.MkdirAll(fullFilesDir, os.ModePerm)
require.NoError(t, err)
if info.isScript {
path = filepath.Join(scriptsDir, filename)
} else {
path = filepath.Join(filesDir, filename)
}

_, err = os.Create(filepath.Join(fullFilesDir, "baz"))
require.NoError(t, err)
require.NoError(t, os.WriteFile(path, nil, info.perms))
}

// Test
scripts, err := configureCustomFiles(ctx)
Expand All @@ -41,25 +62,24 @@ func TestConfigureCustomFiles(t *testing.T) {
require.NoError(t, err)

// - make sure the files were added to the build directory
foundDirListing, err := os.ReadDir(ctx.CombustionDir)
dirEntries, err := os.ReadDir(ctx.CombustionDir)
require.NoError(t, err)
assert.Equal(t, 3, len(foundDirListing))
require.Len(t, dirEntries, 4)

// - make sure the copied files have the right permissions
for _, entry := range foundDirListing {
fullEntryPath := filepath.Join(ctx.CombustionDir, entry.Name())
stats, err := os.Stat(fullEntryPath)
for _, entry := range dirEntries {
file, ok := files[entry.Name()]
require.Truef(t, ok, "Unexpected file: %s", entry.Name())

entryPath := filepath.Join(ctx.CombustionDir, entry.Name())
stats, err := os.Stat(entryPath)
require.NoError(t, err)

if strings.HasSuffix(entry.Name(), ".sh") {
assert.Equal(t, fileio.ExecutablePerms, stats.Mode())
} else {
assert.Equal(t, fileio.NonExecutablePerms, stats.Mode())
}
assert.Equal(t, file.perms, stats.Mode())
}

// - make sure only script entries were added to the combustion scripts list
require.Equal(t, 2, len(scripts))
require.Len(t, scripts, 2)
assert.Contains(t, scripts, "foo.sh")
assert.Contains(t, scripts, "bar.sh")
}
Expand All @@ -83,7 +103,7 @@ func TestCopyCustomFiles_MissingFromDir(t *testing.T) {
defer teardown()

// Test
files, err := copyCustomFiles("missing", ctx.CombustionDir, fileio.NonExecutablePerms)
files, err := copyCustomFiles("missing", ctx.CombustionDir)

// Verify
assert.Nil(t, files)
Expand All @@ -101,7 +121,7 @@ func TestCopyCustomFiles_EmptyFromDir(t *testing.T) {
require.NoError(t, err)

// Test
scripts, err := copyCustomFiles(fullScriptsDir, ctx.CombustionDir, fileio.NonExecutablePerms)
scripts, err := copyCustomFiles(fullScriptsDir, ctx.CombustionDir)

// Verify
require.Error(t, err)
Expand Down
Loading