feat: Added --chmod for ADD and COPY command. Fixes #2850 (#3119)

This commit is contained in:
Matthias Schneider 2024-04-22 18:28:37 +02:00 committed by GitHub
parent 87e646a0b3
commit a9062b97f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 227 additions and 95 deletions

View File

@ -18,6 +18,7 @@ package cmd
import (
"fmt"
"io/fs"
"os"
"os/exec"
"path/filepath"
@ -300,7 +301,7 @@ func checkKanikoDir(dir string) error {
if dir != constants.DefaultKanikoPath {
// The destination directory may be across a different partition, so we cannot simply rename/move the directory in this case.
if _, err := util.CopyDir(constants.DefaultKanikoPath, dir, util.FileContext{}, util.DoNotChangeUID, util.DoNotChangeGID); err != nil {
if _, err := util.CopyDir(constants.DefaultKanikoPath, dir, util.FileContext{}, util.DoNotChangeUID, util.DoNotChangeGID, fs.FileMode(0o600), true); err != nil {
return err
}
@ -321,7 +322,6 @@ func checkContained() bool {
// checkNoDeprecatedFlags return an error if deprecated flags are used.
func checkNoDeprecatedFlags() {
// In version >=2.0.0 make it fail (`Warn` -> `Fatal`)
if opts.CustomPlatformDeprecated != "" {
logrus.Warn("Flag --customPlatform is deprecated. Use: --custom-platform")
@ -391,12 +391,12 @@ func resolveEnvironmentBuildArgs(arguments []string, resolver func(string) strin
// copy Dockerfile to /kaniko/Dockerfile so that if it's specified in the .dockerignore
// it won't be copied into the image
func copyDockerfile() error {
if _, err := util.CopyFile(opts.DockerfilePath, config.DockerfilePath, util.FileContext{}, util.DoNotChangeUID, util.DoNotChangeGID); err != nil {
if _, err := util.CopyFile(opts.DockerfilePath, config.DockerfilePath, util.FileContext{}, util.DoNotChangeUID, util.DoNotChangeGID, fs.FileMode(0o600), true); err != nil {
return errors.Wrap(err, "copying dockerfile")
}
dockerignorePath := opts.DockerfilePath + ".dockerignore"
if util.FilepathExists(dockerignorePath) {
if _, err := util.CopyFile(dockerignorePath, config.DockerfilePath+".dockerignore", util.FileContext{}, util.DoNotChangeUID, util.DoNotChangeGID); err != nil {
if _, err := util.CopyFile(dockerignorePath, config.DockerfilePath+".dockerignore", util.FileContext{}, util.DoNotChangeUID, util.DoNotChangeGID, fs.FileMode(0o600), true); err != nil {
return errors.Wrap(err, "copying Dockerfile.dockerignore")
}
}

View File

@ -0,0 +1,22 @@
FROM alpine@sha256:5ce5f501c457015c4b91f91a15ac69157d9b06f1a75cf9107bf2b62e0843983a
ADD --chmod=0666 context/foo /file666
ADD --chmod=777 context/qux /dir777
# ADD tests
# simple file
RUN test "$(stat -c "%a" /file666)" = "666"
# recurive dir
RUN test "$(stat -c "%a" /dir777/qup)" = "777"
RUN test "$(stat -c "%a" /dir777/quw/que)" = "777"
# COPY tests
COPY --chmod=0755 context/foo /copyfile755
COPY --chmod=755 context/qux /copydir755
RUN test "$(stat -c "%a" /copyfile755)" = "755"
RUN test "$(stat -c "%a" /copydir755/qup)" = "755"
RUN test "$(stat -c "%a" /copydir755/quw/que)" = "755"

View File

@ -39,7 +39,7 @@ import (
const (
// ExecutorImage is the name of the kaniko executor image
ExecutorImage = "executor-image"
//WarmerImage is the name of the kaniko cache warmer image
// WarmerImage is the name of the kaniko cache warmer image
WarmerImage = "warmer-image"
dockerPrefix = "docker-"
@ -69,7 +69,8 @@ var argsMap = map[string][]string{
// Environment to build Dockerfiles with, used for both docker and kaniko builds
var envsMap = map[string][]string{
"Dockerfile_test_arg_secret": {"SSH_PRIVATE_KEY=ThEPriv4t3Key"},
"Dockerfile_test_arg_secret": {"SSH_PRIVATE_KEY=ThEPriv4t3Key"},
"Dockerfile_test_copyadd_chmod": {"DOCKER_BUILDKIT=1"},
}
// Arguments to build Dockerfiles with when building with docker
@ -138,8 +139,10 @@ func checkArgsNotPrinted(dockerfile string, out []byte) error {
return nil
}
var bucketContextTests = []string{"Dockerfile_test_copy_bucket"}
var reproducibleTests = []string{"Dockerfile_test_reproducible"}
var (
bucketContextTests = []string{"Dockerfile_test_copy_bucket"}
reproducibleTests = []string{"Dockerfile_test_reproducible"}
)
// GetDockerImage constructs the name of the docker image that would be built with
// dockerfile if it was tagged with imageRepo.
@ -347,13 +350,15 @@ func populateVolumeCache() error {
_, ex, _, _ := runtime.Caller(0)
cwd := filepath.Dir(ex)
warmerCmd := exec.Command("docker",
append([]string{"run", "--net=host",
append([]string{
"run", "--net=host",
"-d",
"-v", os.Getenv("HOME") + "/.config/gcloud:/root/.config/gcloud",
"-v", cwd + ":/workspace",
WarmerImage,
"-c", cacheDir,
"-i", baseImageToCache},
"-i", baseImageToCache,
},
)...,
)
@ -374,14 +379,16 @@ func (d *DockerFileBuilder) buildCachedImage(config *integrationTestConfig, cach
benchmarkEnv := "BENCHMARK_FILE=false"
if b, err := strconv.ParseBool(os.Getenv("BENCHMARK")); err == nil && b {
os.Mkdir("benchmarks", 0755)
os.Mkdir("benchmarks", 0o755)
benchmarkEnv = "BENCHMARK_FILE=/workspace/benchmarks/" + dockerfile
}
kanikoImage := GetVersionedKanikoImage(imageRepo, dockerfile, version)
dockerRunFlags := []string{"run", "--net=host",
dockerRunFlags := []string{
"run", "--net=host",
"-v", cwd + ":/workspace",
"-e", benchmarkEnv}
"-e", benchmarkEnv,
}
dockerRunFlags = addServiceAccountFlags(dockerRunFlags, serviceAccount)
dockerRunFlags = append(dockerRunFlags, ExecutorImage,
"-f", path.Join(buildContextPath, dockerfilesPath, dockerfile),
@ -411,10 +418,12 @@ func (d *DockerFileBuilder) buildRelativePathsImage(imageRepo, dockerfile, servi
kanikoImage := GetKanikoImage(imageRepo, "test_relative_"+dockerfile)
dockerCmd := exec.Command("docker",
append([]string{"build",
append([]string{
"build",
"-t", dockerImage,
"-f", dockerfile,
"./context"},
"./context",
},
)...,
)
@ -483,7 +492,8 @@ func buildKanikoImage(
additionalFlags := append(buildArgs, kanikoArgs...)
logf("Going to build image with kaniko: %s, flags: %s \n", kanikoImage, additionalFlags)
dockerRunFlags := []string{"run", "--net=host",
dockerRunFlags := []string{
"run", "--net=host",
"-e", benchmarkEnv,
"-v", contextDir + ":/workspace",
"-v", benchmarkDir + ":/kaniko/benchmarks",

View File

@ -46,9 +46,11 @@ import (
"github.com/GoogleContainerTools/kaniko/testutil"
)
var config *integrationTestConfig
var imageBuilder *DockerFileBuilder
var allDockerfiles []string
var (
config *integrationTestConfig
imageBuilder *DockerFileBuilder
allDockerfiles []string
)
const (
daemonPrefix = "daemon://"
@ -148,7 +150,6 @@ func TestMain(m *testing.M) {
fmt.Println(err)
}
os.Exit(exitCode)
}
func buildRequiredImages() error {
@ -207,7 +208,6 @@ func TestRun(t *testing.T) {
expected := fmt.Sprintf(emptyContainerDiff, dockerImage, kanikoImage, dockerImage, kanikoImage)
checkContainerDiffOutput(t, diff, expected)
})
}
@ -253,10 +253,12 @@ func testGitBuildcontextHelper(t *testing.T, repo string) {
// Build with docker
dockerImage := GetDockerImage(config.imageRepo, "Dockerfile_test_git")
dockerCmd := exec.Command("docker",
append([]string{"build",
append([]string{
"build",
"-t", dockerImage,
"-f", dockerfile,
repo})...)
repo,
})...)
out, err := RunCommandWithoutTest(dockerCmd)
if err != nil {
t.Errorf("Failed to build image %s with docker command %q: %s %s", dockerImage, dockerCmd.Args, err, string(out))
@ -363,10 +365,12 @@ func TestBuildViaRegistryMirrors(t *testing.T) {
// Build with docker
dockerImage := GetDockerImage(config.imageRepo, "Dockerfile_registry_mirror")
dockerCmd := exec.Command("docker",
append([]string{"build",
append([]string{
"build",
"-t", dockerImage,
"-f", dockerfile,
repo})...)
repo,
})...)
out, err := RunCommandWithoutTest(dockerCmd)
if err != nil {
t.Errorf("Failed to build image %s with docker command %q: %s %s", dockerImage, dockerCmd.Args, err, string(out))
@ -403,10 +407,12 @@ func TestBuildViaRegistryMap(t *testing.T) {
// Build with docker
dockerImage := GetDockerImage(config.imageRepo, "Dockerfile_registry_mirror")
dockerCmd := exec.Command("docker",
append([]string{"build",
append([]string{
"build",
"-t", dockerImage,
"-f", dockerfile,
repo})...)
repo,
})...)
out, err := RunCommandWithoutTest(dockerCmd)
if err != nil {
t.Errorf("Failed to build image %s with docker command %q: %s %s", dockerImage, dockerCmd.Args, err, string(out))
@ -467,10 +473,12 @@ func TestKanikoDir(t *testing.T) {
// Build with docker
dockerImage := GetDockerImage(config.imageRepo, "Dockerfile_registry_mirror")
dockerCmd := exec.Command("docker",
append([]string{"build",
append([]string{
"build",
"-t", dockerImage,
"-f", dockerfile,
repo})...)
repo,
})...)
out, err := RunCommandWithoutTest(dockerCmd)
if err != nil {
t.Errorf("Failed to build image %s with docker command %q: %s %s", dockerImage, dockerCmd.Args, err, string(out))
@ -508,11 +516,13 @@ func TestBuildWithLabels(t *testing.T) {
// Build with docker
dockerImage := GetDockerImage(config.imageRepo, "Dockerfile_test_label:mylabel")
dockerCmd := exec.Command("docker",
append([]string{"build",
append([]string{
"build",
"-t", dockerImage,
"-f", dockerfile,
"--label", testLabel,
repo})...)
repo,
})...)
out, err := RunCommandWithoutTest(dockerCmd)
if err != nil {
t.Errorf("Failed to build image %s with docker command %q: %s %s", dockerImage, dockerCmd.Args, err, string(out))
@ -549,10 +559,12 @@ func TestBuildWithHTTPError(t *testing.T) {
// Build with docker
dockerImage := GetDockerImage(config.imageRepo, "Dockerfile_test_add_404")
dockerCmd := exec.Command("docker",
append([]string{"build",
append([]string{
"build",
"-t", dockerImage,
"-f", dockerfile,
repo})...)
repo,
})...)
out, err := RunCommandWithoutTest(dockerCmd)
if err == nil {
t.Errorf("an error was expected, got %s", string(out))
@ -588,6 +600,7 @@ func TestLayers(t *testing.T) {
// produces a different amount of layers (?).
offset["Dockerfile_test_copy_same_file_many_times"] = 47
offset["Dockerfile_test_meta_arg"] = 1
offset["Dockerfile_test_copyadd_chmod"] = 6
}
for _, dockerfile := range allDockerfiles {
@ -732,7 +745,6 @@ func verifyBuildWith(t *testing.T, cache, dockerfile string) {
}
func TestRelativePaths(t *testing.T) {
dockerfile := "Dockerfile_relative_copy"
t.Run("test_relative_"+dockerfile, func(t *testing.T) {
@ -763,7 +775,6 @@ func TestRelativePaths(t *testing.T) {
}
func TestExitCodePropagation(t *testing.T) {
currentDir, err := os.Getwd()
if err != nil {
t.Fatal("Could not get working dir")
@ -778,7 +789,8 @@ func TestExitCodePropagation(t *testing.T) {
dockerFlags := []string{
"build",
"-t", dockerImage,
"-f", dockerfile}
"-f", dockerfile,
}
dockerCmd := exec.Command("docker", append(dockerFlags, context)...)
out, kanikoErr := RunCommandWithoutTest(dockerCmd)
@ -798,7 +810,7 @@ func TestExitCodePropagation(t *testing.T) {
t.Fatalf("did not produce the expected error:\n%s", out)
}
//try to build the same image with kaniko the error code should match with the one from the plain docker build
// try to build the same image with kaniko the error code should match with the one from the plain docker build
contextVolume := fmt.Sprintf("%s:/workspace", context)
dockerFlags = []string{

View File

@ -17,6 +17,7 @@ limitations under the License.
package commands
import (
"io/fs"
"path/filepath"
v1 "github.com/google/go-containerregistry/pkg/v1"
@ -47,6 +48,14 @@ type AddCommand struct {
func (a *AddCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.BuildArgs) error {
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
chmod, useDefaultChmod, err := util.GetChmod(a.cmd.Chmod, replacementEnvs)
if err != nil {
return errors.Wrap(err, "getting permissions from chmod")
}
if useDefaultChmod {
chmod = fs.FileMode(0o600)
}
uid, gid, err := util.GetUserGroup(a.cmd.Chown, replacementEnvs)
if err != nil {
return errors.Wrap(err, "getting user group from chown")
@ -71,7 +80,7 @@ func (a *AddCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
return err
}
logrus.Infof("Adding remote URL %s to %s", src, urlDest)
if err := util.DownloadFileToDest(src, urlDest, uid, gid); err != nil {
if err := util.DownloadFileToDest(src, urlDest, uid, gid, chmod); err != nil {
return errors.Wrap(err, "downloading remote source file")
}
a.snapshotFiles = append(a.snapshotFiles, urlDest)
@ -100,6 +109,7 @@ func (a *AddCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
cmd: &instructions.CopyCommand{
SourcesAndDest: instructions.SourcesAndDest{SourcePaths: unresolvedSrcs, DestPath: dest},
Chown: a.cmd.Chown,
Chmod: a.cmd.Chmod,
},
fileContext: a.fileContext,
}

View File

@ -64,6 +64,11 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
return errors.Wrap(err, "resolving src")
}
chmod, useDefaultChmod, err := util.GetChmod(c.cmd.Chmod, replacementEnvs)
if err != nil {
return errors.Wrap(err, "getting permissions from chmod")
}
// For each source, iterate through and copy it over
for _, src := range srcs {
fullPath := filepath.Join(c.fileContext.Root, src)
@ -93,7 +98,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
}
if fi.IsDir() {
copiedFiles, err := util.CopyDir(fullPath, destPath, c.fileContext, uid, gid)
copiedFiles, err := util.CopyDir(fullPath, destPath, c.fileContext, uid, gid, chmod, useDefaultChmod)
if err != nil {
return errors.Wrap(err, "copying dir")
}
@ -110,7 +115,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
c.snapshotFiles = append(c.snapshotFiles, destPath)
} else {
// ... Else, we want to copy over a file
exclude, err := util.CopyFile(fullPath, destPath, c.fileContext, uid, gid)
exclude, err := util.CopyFile(fullPath, destPath, c.fileContext, uid, gid, chmod, useDefaultChmod)
if err != nil {
return errors.Wrap(err, "copying file")
}

View File

@ -18,6 +18,7 @@ package util
import (
"fmt"
"io/fs"
"net/url"
"os"
"os/user"
@ -370,6 +371,24 @@ func GetUserGroup(chownStr string, env []string) (int64, int64, error) {
return int64(uid32), int64(gid32), nil
}
func GetChmod(chmodStr string, env []string) (chmod fs.FileMode, useDefault bool, err error) {
if chmodStr == "" {
return fs.FileMode(0o600), true, nil
}
chmodStr, err = ResolveEnvironmentReplacement(chmodStr, env, false)
if err != nil {
return 0, false, err
}
mode, err := strconv.ParseUint(chmodStr, 8, 32)
if err != nil {
return 0, false, errors.Wrap(err, "parsing value from chmod")
}
chmod = fs.FileMode(mode)
return
}
// Extract user and group id from a string formatted 'user:group'.
// UserID and GroupID don't need to be present on the system.
func getUIDAndGIDFromString(userGroupString string) (uint32, uint32, error) {

View File

@ -18,6 +18,7 @@ package util
import (
"fmt"
"io/fs"
"os/user"
"reflect"
"sort"
@ -308,7 +309,8 @@ var updateConfigEnvTests = []struct {
{
Key: "foo",
Value: "baz",
}},
},
},
config: &v1.Config{},
replacementEnvs: []string{},
expectedEnv: []string{"key=var", "foo=baz"},
@ -326,7 +328,8 @@ var updateConfigEnvTests = []struct {
{
Key: "foo",
Value: "$argarg",
}},
},
},
config: &v1.Config{},
replacementEnvs: []string{"var=/test/with'chars'/", "not=used", "argarg=\"a\"b\""},
expectedEnv: []string{"key=/var/run", "env=/test/with'chars'/", "foo=\"a\"b\""},
@ -340,7 +343,8 @@ var updateConfigEnvTests = []struct {
{
Key: "bob",
Value: "cool",
}},
},
},
config: &v1.Config{Env: []string{"bob=used", "more=test"}},
replacementEnvs: []string{},
expectedEnv: []string{"bob=cool", "more=test", "alice=nice"},
@ -585,6 +589,43 @@ func TestGetUserGroup(t *testing.T) {
}
}
func TestGetChmod(t *testing.T) {
tests := []struct {
description string
chmod string
env []string
expected fs.FileMode
shdErr bool
}{
{
description: "non empty chmod",
chmod: "0755",
env: []string{},
expected: fs.FileMode(0o755),
},
{
description: "non empty chmod with env replacement",
chmod: "$foo",
env: []string{"foo=0750"},
expected: fs.FileMode(0o750),
},
{
description: "empty chmod string",
expected: fs.FileMode(0o600),
},
}
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
defaultChmod := fs.FileMode(0o600)
chmod, useDefault, err := GetChmod(tc.chmod, tc.env)
if useDefault {
chmod = defaultChmod
}
testutil.CheckErrorAndDeepEqual(t, tc.shdErr, err, tc.expected, chmod)
})
}
}
func TestResolveEnvironmentReplacementList(t *testing.T) {
type args struct {
values []string
@ -806,7 +847,6 @@ func TestLookupUser(t *testing.T) {
testutil.CheckErrorAndDeepEqual(t, tt.wantErr, err, tt.expected, got)
})
}
}
func TestIsSrcRemoteFileURL(t *testing.T) {

View File

@ -22,6 +22,7 @@ import (
"bytes"
"fmt"
"io"
"io/fs"
"math"
"net/http"
"os"
@ -325,7 +326,7 @@ func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader)
if os.IsNotExist(err) || !fi.IsDir() {
logrus.Debugf("Base %s for file %s does not exist. Creating.", base, path)
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
}
@ -377,7 +378,7 @@ func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader)
return nil
}
// The base directory for a link may not exist before it is created.
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
// Check if something already exists at path
@ -395,7 +396,7 @@ func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader)
case tar.TypeSymlink:
logrus.Tracef("Symlink from %s to %s", hdr.Linkname, path)
// The base directory for a symlink may not exist before it is created.
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
// Check if something already exists at path
@ -621,9 +622,9 @@ func AddVolumePathToIgnoreList(path string) {
// DownloadFileToDest downloads the file at rawurl to the given dest for the ADD command
// From add command docs:
// 1. If <src> is a remote file URL:
// - destination will have permissions of 0600
// - destination will have permissions of 0600 by default if not specified with chmod
// - If remote file has HTTP Last-Modified header, we set the mtime of the file to that timestamp
func DownloadFileToDest(rawurl, dest string, uid, gid int64) error {
func DownloadFileToDest(rawurl, dest string, uid, gid int64, chmod fs.FileMode) error {
resp, err := http.Get(rawurl) //nolint:noctx
if err != nil {
return err
@ -634,7 +635,7 @@ func DownloadFileToDest(rawurl, dest string, uid, gid int64) error {
return fmt.Errorf("invalid response status %d", resp.StatusCode)
}
if err := CreateFile(dest, resp.Body, 0600, uint32(uid), uint32(gid)); err != nil {
if err := CreateFile(dest, resp.Body, chmod, uint32(uid), uint32(gid)); err != nil {
return err
}
mTime := time.Time{}
@ -661,7 +662,7 @@ func DetermineTargetFileOwnership(fi os.FileInfo, uid, gid int64) (int64, int64)
// CopyDir copies the file or directory at src to dest
// It returns a list of files it copied over
func CopyDir(src, dest string, context FileContext, uid, gid int64) ([]string, error) {
func CopyDir(src, dest string, context FileContext, uid, gid int64, chmod fs.FileMode, useDefaultChmod bool) ([]string, error) {
files, err := RelativeFiles("", src)
if err != nil {
return nil, errors.Wrap(err, "copying dir")
@ -681,7 +682,10 @@ func CopyDir(src, dest string, context FileContext, uid, gid int64) ([]string, e
if fi.IsDir() {
logrus.Tracef("Creating directory %s", destPath)
mode := fi.Mode()
mode := chmod
if useDefaultChmod {
mode = fi.Mode()
}
uid, gid := DetermineTargetFileOwnership(fi, uid, gid)
if err := MkdirAllWithPermissions(destPath, mode, uid, gid); err != nil {
return nil, err
@ -693,7 +697,12 @@ func CopyDir(src, dest string, context FileContext, uid, gid int64) ([]string, e
}
} else {
// ... Else, we want to copy over a file
if _, err := CopyFile(fullPath, destPath, context, uid, gid); err != nil {
mode := chmod
if useDefaultChmod {
mode = fs.FileMode(0o600)
}
if _, err := CopyFile(fullPath, destPath, context, uid, gid, mode, useDefaultChmod); err != nil {
return nil, err
}
}
@ -724,7 +733,7 @@ func CopySymlink(src, dest string, context FileContext) (bool, error) {
}
// CopyFile copies the file at src to dest
func CopyFile(src, dest string, context FileContext, uid, gid int64) (bool, error) {
func CopyFile(src, dest string, context FileContext, uid, gid int64, chmod fs.FileMode, useDefaultChmod bool) (bool, error) {
if context.ExcludesFile(src) {
logrus.Debugf("%s found in .dockerignore, ignoring", src)
return true, nil
@ -746,7 +755,12 @@ func CopyFile(src, dest string, context FileContext, uid, gid int64) (bool, erro
}
defer srcFile.Close()
uid, gid = DetermineTargetFileOwnership(fi, uid, gid)
return false, CreateFile(dest, srcFile, fi.Mode(), uint32(uid), uint32(gid))
mode := chmod
if useDefaultChmod {
mode = fi.Mode()
}
return false, CreateFile(dest, srcFile, mode, uint32(uid), uint32(gid))
}
func NewFileContextFromDockerfile(dockerfilePath, buildcontext string) (FileContext, error) {
@ -903,7 +917,7 @@ func CreateTargetTarfile(tarpath string) (*os.File, error) {
baseDir := filepath.Dir(tarpath)
if _, err := os.Lstat(baseDir); os.IsNotExist(err) {
logrus.Debugf("BaseDir %s for file %s does not exist. Creating.", baseDir, tarpath)
if err := os.MkdirAll(baseDir, 0755); err != nil {
if err := os.MkdirAll(baseDir, 0o755); err != nil {
return nil, err
}
}
@ -1040,7 +1054,7 @@ func createParentDirectory(path string, uid int, gid int) error {
dir := dirs[i]
if _, err := os.Lstat(dir); os.IsNotExist(err) {
os.Mkdir(dir, 0755)
os.Mkdir(dir, 0o755)
if uid != DoNotChangeUID {
if gid != DoNotChangeGID {
os.Chown(dir, uid, gid)

View File

@ -21,6 +21,7 @@ import (
"bytes"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"reflect"
@ -48,10 +49,10 @@ func Test_DetectFilesystemSkiplist(t *testing.T) {
232 228 0:101 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro`
path := filepath.Join(testDir, "mountinfo")
if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil {
if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil {
t.Fatalf("Error creating tempdir: %s", err)
}
if err := os.WriteFile(path, []byte(fileContents), 0644); err != nil {
if err := os.WriteFile(path, []byte(fileContents), 0o644); err != nil {
t.Fatalf("Error writing file contents to %s: %s", path, err)
}
@ -671,7 +672,6 @@ func Test_UnTar(t *testing.T) {
sort.Strings(tc.expectedFileList)
sort.Strings(fileList)
testutil.CheckErrorAndDeepEqual(t, tc.errorExpected, err, tc.expectedFileList, fileList)
})
}
}
@ -694,37 +694,37 @@ func TestExtractFile(t *testing.T) {
{
name: "normal file",
contents: []byte("helloworld"),
hdrs: []*tar.Header{fileHeader("./bar", "helloworld", 0644, defaultTestTime)},
hdrs: []*tar.Header{fileHeader("./bar", "helloworld", 0o644, defaultTestTime)},
checkers: []checker{
fileExists("/bar"),
fileMatches("/bar", []byte("helloworld")),
permissionsMatch("/bar", 0644),
permissionsMatch("/bar", 0o644),
timesMatch("/bar", defaultTestTime),
},
},
{
name: "normal file, directory does not exist",
contents: []byte("helloworld"),
hdrs: []*tar.Header{fileHeader("./foo/bar", "helloworld", 0644, defaultTestTime)},
hdrs: []*tar.Header{fileHeader("./foo/bar", "helloworld", 0o644, defaultTestTime)},
checkers: []checker{
fileExists("/foo/bar"),
fileMatches("/foo/bar", []byte("helloworld")),
permissionsMatch("/foo/bar", 0644),
permissionsMatch("/foo", 0755|os.ModeDir),
permissionsMatch("/foo/bar", 0o644),
permissionsMatch("/foo", 0o755|os.ModeDir),
},
},
{
name: "normal file, directory is created after",
contents: []byte("helloworld"),
hdrs: []*tar.Header{
fileHeader("./foo/bar", "helloworld", 0644, defaultTestTime),
dirHeader("./foo", 0722),
fileHeader("./foo/bar", "helloworld", 0o644, defaultTestTime),
dirHeader("./foo", 0o722),
},
checkers: []checker{
fileExists("/foo/bar"),
fileMatches("/foo/bar", []byte("helloworld")),
permissionsMatch("/foo/bar", 0644),
permissionsMatch("/foo", 0722|os.ModeDir),
permissionsMatch("/foo/bar", 0o644),
permissionsMatch("/foo", 0o722|os.ModeDir),
},
},
{
@ -753,15 +753,15 @@ func TestExtractFile(t *testing.T) {
hdrs: []*tar.Header{linkHeader("./foo/bar/baz", "../../bat")},
checkers: []checker{
linkPointsTo("/foo/bar/baz", "../../bat"),
permissionsMatch("/foo", 0755|os.ModeDir),
permissionsMatch("/foo/bar", 0755|os.ModeDir),
permissionsMatch("/foo", 0o755|os.ModeDir),
permissionsMatch("/foo/bar", 0o755|os.ModeDir),
},
},
{
name: "hardlink",
tmpdir: "/tmp/hardlink",
hdrs: []*tar.Header{
fileHeader("/bin/gzip", "gzip-binary", 0751, defaultTestTime),
fileHeader("/bin/gzip", "gzip-binary", 0o751, defaultTestTime),
hardlinkHeader("/bin/uncompress", "/bin/gzip"),
},
checkers: []checker{
@ -772,25 +772,25 @@ func TestExtractFile(t *testing.T) {
{
name: "file with setuid bit",
contents: []byte("helloworld"),
hdrs: []*tar.Header{fileHeader("./bar", "helloworld", 04644, defaultTestTime)},
hdrs: []*tar.Header{fileHeader("./bar", "helloworld", 0o4644, defaultTestTime)},
checkers: []checker{
fileExists("/bar"),
fileMatches("/bar", []byte("helloworld")),
permissionsMatch("/bar", 0644|os.ModeSetuid),
permissionsMatch("/bar", 0o644|os.ModeSetuid),
},
},
{
name: "dir with sticky bit",
contents: []byte("helloworld"),
hdrs: []*tar.Header{
dirHeader("./foo", 01755),
fileHeader("./foo/bar", "helloworld", 0644, defaultTestTime),
dirHeader("./foo", 0o1755),
fileHeader("./foo/bar", "helloworld", 0o644, defaultTestTime),
},
checkers: []checker{
fileExists("/foo/bar"),
fileMatches("/foo/bar", []byte("helloworld")),
permissionsMatch("/foo/bar", 0644),
permissionsMatch("/foo", 0755|os.ModeDir|os.ModeSticky),
permissionsMatch("/foo/bar", 0o644),
permissionsMatch("/foo", 0o755|os.ModeDir|os.ModeSticky),
},
},
}
@ -839,7 +839,7 @@ func TestCopySymlink(t *testing.T) {
linkTarget: "/abs/dest",
dest: "overwrite_me",
beforeLink: func(r string) error {
return os.WriteFile(filepath.Join(r, "overwrite_me"), nil, 0644)
return os.WriteFile(filepath.Join(r, "overwrite_me"), nil, 0o644)
},
}}
@ -848,9 +848,9 @@ func TestCopySymlink(t *testing.T) {
tc := tc
t.Parallel()
r := t.TempDir()
os.MkdirAll(filepath.Join(r, filepath.Dir(tc.linkTarget)), 0777)
os.MkdirAll(filepath.Join(r, filepath.Dir(tc.linkTarget)), 0o777)
tc.linkTarget = filepath.Join(r, tc.linkTarget)
os.WriteFile(tc.linkTarget, nil, 0644)
os.WriteFile(tc.linkTarget, nil, 0o644)
if tc.beforeLink != nil {
if err := tc.beforeLink(r); err != nil {
@ -982,12 +982,12 @@ func Test_CopyFile_skips_self(t *testing.T) {
if err := os.WriteFile(
tempFile,
[]byte(expected),
0755,
0o755,
); err != nil {
t.Fatal(err)
}
ignored, err := CopyFile(tempFile, tempFile, FileContext{}, DoNotChangeUID, DoNotChangeGID)
ignored, err := CopyFile(tempFile, tempFile, FileContext{}, DoNotChangeUID, DoNotChangeGID, fs.FileMode(0o600), true)
if err != nil {
t.Fatal(err)
}
@ -1012,7 +1012,7 @@ func fakeExtract(_ string, _ *tar.Header, _ string, _ io.Reader) error {
}
func Test_GetFSFromLayers_with_whiteouts_include_whiteout_enabled(t *testing.T) {
var resetMountInfoFile = provideEmptyMountinfoFile()
resetMountInfoFile := provideEmptyMountinfoFile()
defer resetMountInfoFile()
ctrl := gomock.NewController(t)
@ -1020,7 +1020,7 @@ func Test_GetFSFromLayers_with_whiteouts_include_whiteout_enabled(t *testing.T)
root := t.TempDir()
// Write a whiteout path
d1 := []byte("Hello World\n")
if err := os.WriteFile(filepath.Join(root, "foobar"), d1, 0644); err != nil {
if err := os.WriteFile(filepath.Join(root, "foobar"), d1, 0o644); err != nil {
t.Fatal(err)
}
@ -1039,7 +1039,7 @@ func Test_GetFSFromLayers_with_whiteouts_include_whiteout_enabled(t *testing.T)
hdr := &tar.Header{
Name: f,
Mode: 0644,
Mode: 0o644,
Size: int64(len("Hello World\n")),
}
@ -1121,7 +1121,7 @@ func provideEmptyMountinfoFile() func() {
}
func Test_GetFSFromLayers_with_whiteouts_include_whiteout_disabled(t *testing.T) {
var resetMountInfoFile = provideEmptyMountinfoFile()
resetMountInfoFile := provideEmptyMountinfoFile()
defer resetMountInfoFile()
ctrl := gomock.NewController(t)
@ -1129,7 +1129,7 @@ func Test_GetFSFromLayers_with_whiteouts_include_whiteout_disabled(t *testing.T)
root := t.TempDir()
// Write a whiteout path
d1 := []byte("Hello World\n")
if err := os.WriteFile(filepath.Join(root, "foobar"), d1, 0644); err != nil {
if err := os.WriteFile(filepath.Join(root, "foobar"), d1, 0o644); err != nil {
t.Fatal(err)
}
@ -1147,7 +1147,7 @@ func Test_GetFSFromLayers_with_whiteouts_include_whiteout_disabled(t *testing.T)
hdr := &tar.Header{
Name: f,
Mode: 0644,
Mode: 0o644,
Size: int64(len("Hello world\n")),
}
@ -1224,7 +1224,7 @@ func Test_GetFSFromLayers_with_whiteouts_include_whiteout_disabled(t *testing.T)
}
func Test_GetFSFromLayers_ignorelist(t *testing.T) {
var resetMountInfoFile = provideEmptyMountinfoFile()
resetMountInfoFile := provideEmptyMountinfoFile()
defer resetMountInfoFile()
ctrl := gomock.NewController(t)
@ -1232,7 +1232,7 @@ func Test_GetFSFromLayers_ignorelist(t *testing.T) {
root := t.TempDir()
// Write a whiteout path
fileContents := []byte("Hello World\n")
if err := os.Mkdir(filepath.Join(root, "testdir"), 0775); err != nil {
if err := os.Mkdir(filepath.Join(root, "testdir"), 0o775); err != nil {
t.Fatal(err)
}
@ -1249,7 +1249,7 @@ func Test_GetFSFromLayers_ignorelist(t *testing.T) {
hdr := &tar.Header{
Name: f,
Mode: 0644,
Mode: 0o644,
Size: int64(len(string(fileContents))),
}
@ -1321,7 +1321,7 @@ func Test_GetFSFromLayers_ignorelist(t *testing.T) {
defaultIgnoreList = append(defaultIgnoreList, IgnoreListEntry{
Path: filepath.Join(root, "testdir"),
})
if err := os.Mkdir(filepath.Join(root, "testdir"), 0775); err != nil {
if err := os.Mkdir(filepath.Join(root, "testdir"), 0o775); err != nil {
t.Fatal(err)
}
@ -1392,7 +1392,7 @@ func Test_GetFSFromLayers(t *testing.T) {
hdr := &tar.Header{
Name: f,
Mode: 0644,
Mode: 0o644,
Size: int64(len("Hello world\n")),
}
@ -1519,7 +1519,7 @@ func Test_setFileTimes(t *testing.T) {
p := filepath.Join(testDir, "foo.txt")
if err := os.WriteFile(p, []byte("meow"), 0777); err != nil {
if err := os.WriteFile(p, []byte("meow"), 0o777); err != nil {
t.Fatal(err)
}