diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index 7f0339c5df..2c7c622220 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -31,6 +31,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/executor" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/logging" "github.com/GoogleContainerTools/kaniko/pkg/timing" "github.com/GoogleContainerTools/kaniko/pkg/util" @@ -210,7 +211,7 @@ var RootCmd = &cobra.Command{ } logrus.Infof("Benchmark file written at %s", benchmarkFile) } else { - f, err := os.Create(benchmarkFile) + f, err := filesystem.FS.Create(benchmarkFile) if err != nil { logrus.Warnf("Unable to create benchmarking file %s: %s", benchmarkFile, err) return @@ -305,7 +306,7 @@ func checkKanikoDir(dir string) error { return err } - if err := os.RemoveAll(constants.DefaultKanikoPath); err != nil { + if err := filesystem.FS.RemoveAll(constants.DefaultKanikoPath); err != nil { return err } // After remove DefaultKankoPath, the DOKCER_CONFIG env will point to a non-exist dir, so we should update DOCKER_CONFIG env to new dir @@ -437,7 +438,7 @@ func resolveSourceContext() error { } if ctxSubPath != "" { opts.SrcContext = filepath.Join(opts.SrcContext, ctxSubPath) - if _, err := os.Stat(opts.SrcContext); os.IsNotExist(err) { + if _, err := filesystem.FS.Stat(opts.SrcContext); os.IsNotExist(err) { return err } } diff --git a/cmd/warmer/cmd/root.go b/cmd/warmer/cmd/root.go index 6ac7f7d184..ba3c46dbb1 100644 --- a/cmd/warmer/cmd/root.go +++ b/cmd/warmer/cmd/root.go @@ -25,6 +25,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/cache" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/logging" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/containerd/containerd/platforms" @@ -70,8 +71,8 @@ var RootCmd = &cobra.Command{ return nil }, Run: func(cmd *cobra.Command, args []string) { - if _, err := os.Stat(opts.CacheDir); os.IsNotExist(err) { - err = os.MkdirAll(opts.CacheDir, 0755) + if _, err := filesystem.FS.Stat(opts.CacheDir); os.IsNotExist(err) { + err = filesystem.MkdirAll(opts.CacheDir, 0o755) if err != nil { exit(errors.Wrap(err, "Failed to create cache directory")) } @@ -79,7 +80,6 @@ var RootCmd = &cobra.Command{ if err := cache.WarmCache(opts); err != nil { exit(errors.Wrap(err, "Failed warming cache")) } - }, } diff --git a/go.mod b/go.mod index baa9be8865..ca7da83c42 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( require ( github.com/GoogleCloudPlatform/docker-credential-gcr/v2 v2.1.22 github.com/containerd/containerd v1.7.19 + github.com/twpayne/go-vfs/v5 v5.0.4 ) require github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect diff --git a/go.sum b/go.sum index cf523f4f27..e4ca359b0f 100644 --- a/go.sum +++ b/go.sum @@ -483,6 +483,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= +github.com/twpayne/go-vfs/v5 v5.0.4 h1:/ne3h+rW7f5YOyOFguz+3ztfUwzOLR0Vts3y0mMAitg= +github.com/twpayne/go-vfs/v5 v5.0.4/go.mod h1:zTPFJUbgsEMFNSWnWQlLq9wh4AN83edZzx3VXbxrS1w= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= diff --git a/integration/benchmark_test.go b/integration/benchmark_test.go index c6a31430f0..55c6f56aa1 100644 --- a/integration/benchmark_test.go +++ b/integration/benchmark_test.go @@ -27,6 +27,8 @@ import ( "sync" "testing" "time" + + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) type result struct { @@ -68,7 +70,7 @@ func TestSnapshotBenchmark(t *testing.T) { r := newResult(t, filepath.Join(benchmarkDir, dockerfile)) timeMap.Store(num, r) wg.Done() - defer os.Remove(benchmarkDir) + defer filesystem.FS.Remove(benchmarkDir) }(num, &err) if err != nil { t.Errorf("could not run benchmark results for num %d due to %s", num, err) @@ -84,12 +86,11 @@ func TestSnapshotBenchmark(t *testing.T) { t.Logf("%d,%f,%f,%f", d, v.totalBuildTime, v.walkingFiles, v.resolvingFiles) return true }) - } func newResult(t *testing.T, f string) result { var current map[string]time.Duration - jsonFile, err := os.Open(f) + jsonFile, err := filesystem.FS.Open(f) defer jsonFile.Close() if err != nil { t.Errorf("could not read benchmark file %s", f) @@ -141,7 +142,7 @@ func TestSnapshotBenchmarkGcloud(t *testing.T) { r := newResult(t, filepath.Join(dir, "results")) t.Log(fmt.Sprintf("%d,%f,%f,%f, %f", num, r.totalBuildTime, r.walkingFiles, r.resolvingFiles, r.hashingFiles)) wg.Done() - defer os.Remove(dir) + defer filesystem.FS.Remove(dir) defer os.Chdir(cwd) }(num) }) @@ -160,7 +161,7 @@ func runInGcloud(dir string, num int) (string, error) { } // grab gcs and to temp dir and return - tmpDir, err := os.MkdirTemp("", fmt.Sprintf("%d", num)) + tmpDir, err := filesystem.MkdirTemp("", fmt.Sprintf("%d", num)) if err != nil { return "", err } diff --git a/integration/images.go b/integration/images.go index ccf675c616..b3bb836ad3 100644 --- a/integration/images.go +++ b/integration/images.go @@ -31,6 +31,7 @@ import ( "time" "cloud.google.com/go/storage" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/timing" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/pkg/util/bucket" @@ -379,7 +380,7 @@ 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", 0o755) + filesystem.FS.Mkdir("benchmarks", 0o755) benchmarkEnv = "BENCHMARK_FILE=/workspace/benchmarks/" + dockerfile } kanikoImage := GetVersionedKanikoImage(imageRepo, dockerfile, version) @@ -470,7 +471,7 @@ func buildKanikoImage( shdUpload bool, ) (string, error) { benchmarkEnv := "BENCHMARK_FILE=false" - benchmarkDir, err := os.MkdirTemp("", "") + benchmarkDir, err := filesystem.MkdirTemp("", "") if err != nil { return "", err } @@ -480,7 +481,7 @@ func buildKanikoImage( benchmarkFile := path.Join(benchmarkDir, dockerfile) fileName := fmt.Sprintf("run_%s_%s", time.Now().Format("2006-01-02-15:04"), dockerfile) dst := path.Join("benchmarks", fileName) - file, err := os.Open(benchmarkFile) + file, err := filesystem.FS.Open(benchmarkFile) if err != nil { return "", err } diff --git a/integration/integration_test.go b/integration/integration_test.go index f52489fada..cc400f0045 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -40,6 +40,7 @@ import ( "github.com/pkg/errors" "google.golang.org/api/option" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/timing" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/pkg/util/bucket" @@ -104,7 +105,7 @@ func launchTests(m *testing.M) (int, error) { if err != nil { return 1, errors.Wrap(err, "failed to get bucket name from uri") } - contextFile, err := os.Open(contextFilePath) + contextFile, err := filesystem.FS.Open(contextFilePath) if err != nil { return 1, fmt.Errorf("failed to read file at path %v: %w", contextFilePath, err) } @@ -113,7 +114,7 @@ func launchTests(m *testing.M) (int, error) { return 1, errors.Wrap(err, "Failed to upload build context") } - if err = os.Remove(contextFilePath); err != nil { + if err = filesystem.FS.Remove(contextFilePath); err != nil { return 1, errors.Wrap(err, fmt.Sprintf("Failed to remove tarball at %s", contextFilePath)) } @@ -1035,7 +1036,7 @@ func getLastLayerFiles(image string) ([]string, error) { func logBenchmarks(benchmark string) error { if b, err := strconv.ParseBool(os.Getenv("BENCHMARK")); err == nil && b { - f, err := os.Create(benchmark) + f, err := filesystem.FS.Create(benchmark) if err != nil { return err } @@ -1074,7 +1075,7 @@ func initIntegrationTestConfig() *integrationTestConfig { if err != nil { log.Fatalf("Error getting absolute path for service account: %s\n", c.serviceAccount) } - if _, err := os.Stat(absPath); os.IsNotExist(err) { + if _, err := filesystem.FS.Stat(absPath); os.IsNotExist(err) { log.Fatalf("Service account does not exist: %s\n", absPath) } c.serviceAccount = absPath diff --git a/integration/integration_with_context_test.go b/integration/integration_with_context_test.go index 412bf212ea..3dc9fede1d 100644 --- a/integration/integration_with_context_test.go +++ b/integration/integration_with_context_test.go @@ -22,6 +22,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) func TestWithContext(t *testing.T) { @@ -31,7 +33,7 @@ func TestWithContext(t *testing.T) { } dir := filepath.Join(cwd, "dockerfiles-with-context") - entries, err := os.ReadDir(dir) + entries, err := filesystem.ReadDir(dir) if err != nil { t.Fatal(err) } @@ -68,7 +70,6 @@ func TestWithContext(t *testing.T) { expected := fmt.Sprintf(emptyContainerDiff, dockerImage, kanikoImage, dockerImage, kanikoImage) checkContainerDiffOutput(t, diff, expected) - }) } diff --git a/integration/integration_with_stdin_test.go b/integration/integration_with_stdin_test.go index 4a75b4c0cc..06c5cf32c4 100644 --- a/integration/integration_with_stdin_test.go +++ b/integration/integration_with_stdin_test.go @@ -26,6 +26,7 @@ import ( "sync" "testing" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/testutil" ) @@ -37,7 +38,7 @@ func TestBuildWithStdin(t *testing.T) { testDir := "test_dir" testDirLongPath := filepath.Join(cwd, testDir) - if err := os.MkdirAll(testDirLongPath, 0750); err != nil { + if err := filesystem.MkdirAll(testDirLongPath, 0o750); err != nil { t.Errorf("Failed to create dir_where_to_extract: %v", err) } @@ -62,7 +63,7 @@ func TestBuildWithStdin(t *testing.T) { // Create Tar Gz File with dockerfile inside go func(wg *sync.WaitGroup) { defer wg.Done() - tarFile, err := os.Create(tarPath) + tarFile, err := filesystem.FS.Create(tarPath) if err != nil { t.Errorf("Failed to create %s: %v", tarPath, err) } @@ -86,10 +87,12 @@ func TestBuildWithStdin(t *testing.T) { dockerImage := GetDockerImage(config.imageRepo, dockerfile) dockerCmd := exec.Command("docker", - append([]string{"build", + append([]string{ + "build", "-t", dockerImage, "-f", dockerfile, - "."})...) + ".", + })...) _, err := RunCommandWithoutTest(dockerCmd) if err != nil { @@ -145,7 +148,7 @@ func TestBuildWithStdin(t *testing.T) { expected := fmt.Sprintf(emptyContainerDiff, dockerImage, kanikoImageStdin, dockerImage, kanikoImageStdin) checkContainerDiffOutput(t, diff, expected) - if err := os.RemoveAll(testDirLongPath); err != nil { + if err := filesystem.FS.RemoveAll(testDirLongPath); err != nil { t.Errorf("Failed to remove %s: %v", testDirLongPath, err) } } diff --git a/integration/k8s_test.go b/integration/k8s_test.go index f05917a320..ef48e34477 100644 --- a/integration/k8s_test.go +++ b/integration/k8s_test.go @@ -25,6 +25,8 @@ import ( "path/filepath" "testing" "text/template" + + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) type K8sConfig struct { @@ -41,7 +43,7 @@ func TestK8s(t *testing.T) { dir := filepath.Join(cwd, "dockerfiles-with-context") - entries, err := os.ReadDir(dir) + entries, err := filesystem.ReadDir(dir) if err != nil { t.Fatal(err) } @@ -73,11 +75,11 @@ func TestK8s(t *testing.T) { dockerImage := GetDockerImage(config.imageRepo, name) kanikoImage := GetKanikoImage(config.imageRepo, name) - tmpfile, err := os.CreateTemp("", "k8s-job-*.yaml") + tmpfile, err := filesystem.CreateTemp("", "k8s-job-*.yaml") if err != nil { log.Fatal(err) } - defer os.Remove(tmpfile.Name()) // clean up + defer filesystem.FS.Remove(tmpfile.Name()) // clean up tmpl := template.Must(template.ParseFiles("k8s-job.yaml")) job := K8sConfig{KanikoImage: kanikoImage, Context: testDir, Name: name} if err := tmpl.Execute(tmpfile, job); err != nil { @@ -86,7 +88,7 @@ func TestK8s(t *testing.T) { t.Logf("Testing K8s based Kaniko building of dockerfile %s and push to %s \n", testDir, kanikoImage) - content, err := os.ReadFile(tmpfile.Name()) + content, err := filesystem.ReadFile(tmpfile.Name()) if err != nil { log.Fatal(err) } diff --git a/integration/tar.go b/integration/tar.go index 9e36c55c2a..73a7a8abac 100644 --- a/integration/tar.go +++ b/integration/tar.go @@ -23,6 +23,7 @@ import ( "os" "time" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" ) @@ -34,13 +35,13 @@ func CreateIntegrationTarball() (string, error) { if err != nil { return "nil", fmt.Errorf("Failed find path to integration dir: %w", err) } - tempDir, err := os.MkdirTemp("", "") + tempDir, err := filesystem.MkdirTemp("", "") if err != nil { return "", fmt.Errorf("Failed to create temporary directory to hold tarball: %w", err) } contextFilePath := fmt.Sprintf("%s/context_%d.tar.gz", tempDir, time.Now().UnixNano()) - file, err := os.OpenFile(contextFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + file, err := filesystem.FS.OpenFile(contextFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644) if err != nil { return "", err } diff --git a/pkg/buildcontext/azureblob.go b/pkg/buildcontext/azureblob.go index ec9af72ff6..ca6481fb6e 100644 --- a/pkg/buildcontext/azureblob.go +++ b/pkg/buildcontext/azureblob.go @@ -26,6 +26,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" kConfig "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" ) @@ -36,7 +37,6 @@ type AzureBlob struct { // Download context file from given azure blob storage url and unpack it to BuildContextDir func (b *AzureBlob) UnpackTarFromBuildContext() (string, error) { - // Get Azure_STORAGE_ACCESS_KEY from environment variables accountKey := os.Getenv("AZURE_STORAGE_ACCESS_KEY") if len(accountKey) == 0 { @@ -79,5 +79,5 @@ func (b *AzureBlob) UnpackTarFromBuildContext() (string, error) { return tarPath, err } // Remove the tar so it doesn't interfere with subsequent commands - return directory, os.Remove(tarPath) + return directory, filesystem.FS.Remove(tarPath) } diff --git a/pkg/buildcontext/gcs.go b/pkg/buildcontext/gcs.go index 6af45d5c65..47041be76d 100644 --- a/pkg/buildcontext/gcs.go +++ b/pkg/buildcontext/gcs.go @@ -19,11 +19,11 @@ package buildcontext import ( "fmt" "io" - "os" "path/filepath" kConfig "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/pkg/util/bucket" "github.com/sirupsen/logrus" @@ -69,7 +69,7 @@ func unpackTarFromGCSBucket(bucketName, item, directory string) error { } // Remove the tar so it doesn't interfere with subsequent commands logrus.Debugf("Deleting %s", tarPath) - return os.Remove(tarPath) + return filesystem.FS.Remove(tarPath) } // getTarFromBucket gets context.tar.gz from the GCS bucket and saves it to the filesystem @@ -87,7 +87,7 @@ func getTarFromBucket(bucketName, filepathInBucket, directory string) (string, e } defer reader.Close() tarPath := filepath.Join(directory, constants.ContextTar) - if err := util.CreateFile(tarPath, reader, 0600, 0, 0); err != nil { + if err := util.CreateFile(tarPath, reader, 0o600, 0, 0); err != nil { return "", err } logrus.Debugf("Copied tarball %s from GCS bucket %s to %s", constants.ContextTar, bucketName, tarPath) diff --git a/pkg/buildcontext/https.go b/pkg/buildcontext/https.go index c32afa7bc1..2b391dabbe 100644 --- a/pkg/buildcontext/https.go +++ b/pkg/buildcontext/https.go @@ -20,11 +20,11 @@ import ( "fmt" "io" "net/http" - "os" "path/filepath" kConfig "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/sirupsen/logrus" ) @@ -36,7 +36,6 @@ type HTTPSTar struct { // UnpackTarFromBuildContext downloads context file from https server func (h *HTTPSTar) UnpackTarFromBuildContext() (directory string, err error) { - logrus.Info("Retrieving https tar file") // Create directory and target file for downloading the context file @@ -76,5 +75,5 @@ func (h *HTTPSTar) UnpackTarFromBuildContext() (directory string, err error) { logrus.Info("Extracted https tar file") // Remove the tar so it doesn't interfere with subsequent commands - return directory, os.Remove(tarPath) + return directory, filesystem.FS.Remove(tarPath) } diff --git a/pkg/buildcontext/s3.go b/pkg/buildcontext/s3.go index d654149419..99d66321de 100644 --- a/pkg/buildcontext/s3.go +++ b/pkg/buildcontext/s3.go @@ -25,6 +25,7 @@ import ( kConfig "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/pkg/util/bucket" "github.com/aws/aws-sdk-go-v2/aws" @@ -72,10 +73,10 @@ func (s *S3) UnpackTarFromBuildContext() (string, error) { downloader := s3manager.NewDownloader(client) directory := kConfig.BuildContextDir tarPath := filepath.Join(directory, constants.ContextTar) - if err := os.MkdirAll(directory, 0750); err != nil { + if err := filesystem.MkdirAll(directory, 0o750); err != nil { return directory, err } - file, err := os.Create(tarPath) + file, err := filesystem.FS.Create(tarPath) if err != nil { return directory, err } diff --git a/pkg/buildcontext/tar.go b/pkg/buildcontext/tar.go index 8a6bc2dba5..0033836fc3 100644 --- a/pkg/buildcontext/tar.go +++ b/pkg/buildcontext/tar.go @@ -22,6 +22,7 @@ import ( "os" kConfig "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -35,7 +36,7 @@ type Tar struct { // UnpackTarFromBuildContext unpack the compressed tar file func (t *Tar) UnpackTarFromBuildContext() (string, error) { directory := kConfig.BuildContextDir - if err := os.MkdirAll(directory, 0750); err != nil { + if err := filesystem.MkdirAll(directory, 0o750); err != nil { return "", errors.Wrap(err, "unpacking tar from build context") } if t.context == "stdin" { diff --git a/pkg/buildcontext/tar_test.go b/pkg/buildcontext/tar_test.go index 0f881daa70..4dca8d1e7d 100644 --- a/pkg/buildcontext/tar_test.go +++ b/pkg/buildcontext/tar_test.go @@ -26,6 +26,7 @@ import ( "sync" "testing" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/testutil" ) @@ -38,7 +39,7 @@ func TestBuildWithLocalTar(t *testing.T) { testDirLongPath := filepath.Join(cwd, testDir) dirUnpack := filepath.Join(testDirLongPath, "dir_where_to_unpack") - if err := os.MkdirAll(dirUnpack, 0750); err != nil { + if err := filesystem.MkdirAll(dirUnpack, 0o750); err != nil { t.Errorf("Failed to create dir_where_to_extract: %v", err) } @@ -68,13 +69,13 @@ func TestBuildWithLocalTar(t *testing.T) { // Create Tar Gz File with dockerfile inside go func(wg *sync.WaitGroup) { defer wg.Done() - validTarFile, err := os.Create(validTarPath) + validTarFile, err := filesystem.FS.Create(validTarPath) if err != nil { t.Errorf("Failed to create %s: %v", validTarPath, err) } defer validTarFile.Close() - invalidTarFile, err := os.Create(invalidTarPath) + invalidTarFile, err := filesystem.FS.Create(invalidTarPath) if err != nil { t.Errorf("Failed to create %s: %v", invalidTarPath, err) } @@ -138,13 +139,13 @@ func TestBuildWithLocalTar(t *testing.T) { }) } - if err := os.RemoveAll(testDirLongPath); err != nil { + if err := filesystem.FS.RemoveAll(testDirLongPath); err != nil { t.Errorf("Failed to remove %s: %v", testDirLongPath, err) } } func getSHAFromFilePath(f string) (string, error) { - data, err := os.ReadFile(f) + data, err := filesystem.ReadFile(f) if err != nil { return "", err } diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index b861866eaf..700df0ffee 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -18,7 +18,6 @@ package cache import ( "fmt" - "os" "path" "path/filepath" "strings" @@ -26,6 +25,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/creds" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -178,7 +178,7 @@ func LocalSource(opts *config.CacheOptions, cacheKey string) (v1.Image, error) { path := path.Join(cache, cacheKey) - fi, err := os.Stat(path) + fi, err := filesystem.FS.Stat(path) if err != nil { msg := fmt.Sprintf("No file found for cache key %v %v", cacheKey, err) logrus.Debug(msg) @@ -219,7 +219,7 @@ func (c *cachedImage) Manifest() (*v1.Manifest, error) { } func mfstFromPath(p string) (*v1.Manifest, error) { - f, err := os.Open(p) + f, err := filesystem.FS.Open(p) if err != nil { return nil, err } @@ -237,7 +237,7 @@ func cachedImageFromPath(p string) (v1.Image, error) { mfstPath := p + ".json" var mfst *v1.Manifest - if _, err := os.Stat(mfstPath); err != nil { + if _, err := filesystem.FS.Stat(mfstPath); err != nil { logrus.Debugf("Manifest does not exist at file: %s", mfstPath) } else { mfst, err = mfstFromPath(mfstPath) diff --git a/pkg/cache/warm.go b/pkg/cache/warm.go index 589edcafa7..1e0d895229 100644 --- a/pkg/cache/warm.go +++ b/pkg/cache/warm.go @@ -20,12 +20,12 @@ import ( "fmt" "io" "net/http" - "os" "path" "regexp" "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/image/remote" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/google/go-containerregistry/pkg/name" @@ -73,19 +73,19 @@ func WarmCache(opts *config.WarmerOptions) error { // Download image in temporary files then move files to final destination func warmToFile(cacheDir, img string, opts *config.WarmerOptions) error { - f, err := os.CreateTemp(cacheDir, "warmingImage.*") + f, err := filesystem.CreateTemp(cacheDir, "warmingImage.*") if err != nil { return err } // defer called in reverse order - defer os.Remove(f.Name()) + defer filesystem.FS.Remove(f.Name()) defer f.Close() - mtfsFile, err := os.CreateTemp(cacheDir, "warmingManifest.*") + mtfsFile, err := filesystem.CreateTemp(cacheDir, "warmingManifest.*") if err != nil { return err } - defer os.Remove(mtfsFile.Name()) + defer filesystem.FS.Remove(mtfsFile.Name()) defer mtfsFile.Close() cw := &Warmer{ @@ -108,12 +108,12 @@ func warmToFile(cacheDir, img string, opts *config.WarmerOptions) error { finalCachePath := path.Join(cacheDir, digest.String()) finalMfstPath := finalCachePath + ".json" - err = os.Rename(f.Name(), finalCachePath) + err = filesystem.FS.Rename(f.Name(), finalCachePath) if err != nil { return err } - err = os.Rename(mtfsFile.Name(), finalMfstPath) + err = filesystem.FS.Rename(mtfsFile.Name(), finalMfstPath) if err != nil { return errors.Wrap(err, "Failed to rename manifest file") } @@ -194,7 +194,7 @@ func ParseDockerfile(opts *config.WarmerOptions) ([]string, error) { } d, err = io.ReadAll(response.Body) } else { - d, err = os.ReadFile(opts.DockerfilePath) + d, err = filesystem.ReadFile(opts.DockerfilePath) } if err != nil { @@ -217,5 +217,4 @@ func ParseDockerfile(opts *config.WarmerOptions) ([]string, error) { baseNames = append(baseNames, resolvedBaseName) } return baseNames, nil - } diff --git a/pkg/cache/warm_test.go b/pkg/cache/warm_test.go index 6dd926f8f9..7075cbbfe5 100644 --- a/pkg/cache/warm_test.go +++ b/pkg/cache/warm_test.go @@ -18,11 +18,11 @@ package cache import ( "bytes" - "os" "testing" "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/fakes" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" v1 "github.com/google/go-containerregistry/pkg/v1" ) @@ -118,11 +118,11 @@ func TestParseDockerfile_SingleStageDockerfile(t *testing.T) { dockerfile := `FROM alpine:latest LABEL maintainer="alexezio" ` - tmpfile, err := os.CreateTemp("", "example") + tmpfile, err := filesystem.CreateTemp("", "example") if err != nil { t.Fatal(err) } - defer os.Remove(tmpfile.Name()) + defer filesystem.FS.Remove(tmpfile.Name()) if _, err := tmpfile.Write([]byte(dockerfile)); err != nil { t.Fatal(err) @@ -151,11 +151,11 @@ LABEL maintainer="alexezio" FROM alpine:latest as RUNNER LABEL maintainer="alexezio" ` - tmpfile, err := os.CreateTemp("", "example") + tmpfile, err := filesystem.CreateTemp("", "example") if err != nil { t.Fatal(err) } - defer os.Remove(tmpfile.Name()) + defer filesystem.FS.Remove(tmpfile.Name()) if _, err := tmpfile.Write([]byte(dockerfile)); err != nil { t.Fatal(err) @@ -185,11 +185,11 @@ func TestParseDockerfile_ArgsDockerfile(t *testing.T) { dockerfile := `ARG version=latest FROM golang:${version} ` - tmpfile, err := os.CreateTemp("", "example") + tmpfile, err := filesystem.CreateTemp("", "example") if err != nil { t.Fatal(err) } - defer os.Remove(tmpfile.Name()) + defer filesystem.FS.Remove(tmpfile.Name()) if _, err := tmpfile.Write([]byte(dockerfile)); err != nil { t.Fatal(err) @@ -224,11 +224,11 @@ func TestParseDockerfile_MissingsDockerfile(t *testing.T) { func TestParseDockerfile_InvalidsDockerfile(t *testing.T) { dockerfile := "This is a invalid dockerfile" - tmpfile, err := os.CreateTemp("", "example") + tmpfile, err := filesystem.CreateTemp("", "example") if err != nil { t.Fatal(err) } - defer os.Remove(tmpfile.Name()) + defer filesystem.FS.Remove(tmpfile.Name()) if _, err := tmpfile.Write([]byte(dockerfile)); err != nil { t.Fatal(err) diff --git a/pkg/commands/add_test.go b/pkg/commands/add_test.go index 22f4ef9498..86eadb14cc 100644 --- a/pkg/commands/add_test.go +++ b/pkg/commands/add_test.go @@ -24,6 +24,7 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/testutil" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -38,13 +39,12 @@ type TarList struct { func createFile(tempDir string) error { fileName := filepath.Join(tempDir, "text.txt") - file, err := os.Create(fileName) + file, err := filesystem.FS.Create(fileName) if err != nil { return err } defer file.Close() - - err = os.WriteFile(fileName, []byte("This is a test!\n"), 0644) + err = filesystem.WriteFile(fileName, []byte("This is a test!\n"), 0o644) if err != nil { return err } @@ -53,7 +53,7 @@ func createFile(tempDir string) error { func createTar(tempDir string, toCreate TarList) error { if toCreate.compressed { - file, err := os.OpenFile(filepath.Join(tempDir, toCreate.tarName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + file, err := filesystem.FS.OpenFile(filepath.Join(tempDir, toCreate.tarName), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644) if err != nil { return err } @@ -68,7 +68,7 @@ func createTar(tempDir string, toCreate TarList) error { return nil } - tarFile, err := os.Create(filepath.Join(tempDir, toCreate.tarName)) + tarFile, err := filesystem.FS.Create(filepath.Join(tempDir, toCreate.tarName)) if err != nil { return err } @@ -88,7 +88,7 @@ func setupAddTest(t *testing.T) string { t.Errorf("couldn't create the file %v", err) } - var tarFiles = []TarList{ + tarFiles := []TarList{ { tarName: "a.tar", directory: "a", @@ -104,7 +104,7 @@ func setupAddTest(t *testing.T) string { // Create directories with files and then create tar for _, toCreate := range tarFiles { - err = os.Mkdir(filepath.Join(tempDir, toCreate.directory), 0755) + err = filesystem.FS.Mkdir(filepath.Join(tempDir, toCreate.directory), 0o755) if err != nil { t.Errorf("couldn't create directory %v", err) } @@ -114,7 +114,6 @@ func setupAddTest(t *testing.T) string { t.Errorf("couldn't create file inside directory %v", err) } err = createTar(tempDir, toCreate) - if err != nil { t.Errorf("couldn't create the tar %v", err) } @@ -134,7 +133,7 @@ func Test_AddCommand(t *testing.T) { } buildArgs := dockerfile.NewBuildArgs([]string{}) - var addTests = []struct { + addTests := []struct { name string sourcesAndDest []string expectedDest []string @@ -156,8 +155,10 @@ func Test_AddCommand(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { c := AddCommand{ cmd: &instructions.AddCommand{ - SourcesAndDest: instructions.SourcesAndDest{SourcePaths: testCase.sourcesAndDest[0 : len(testCase.sourcesAndDest)-1], - DestPath: testCase.sourcesAndDest[len(testCase.sourcesAndDest)-1]}, + SourcesAndDest: instructions.SourcesAndDest{ + SourcePaths: testCase.sourcesAndDest[0 : len(testCase.sourcesAndDest)-1], + DestPath: testCase.sourcesAndDest[len(testCase.sourcesAndDest)-1], + }, }, fileContext: fileContext, } diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 45f76eb69a..2d5fefd1ec 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -23,6 +23,7 @@ import ( "strings" kConfig "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/moby/buildkit/frontend/dockerfile/instructions" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -73,7 +74,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu for _, src := range srcs { fullPath := filepath.Join(c.fileContext.Root, src) - fi, err := os.Lstat(fullPath) + fi, err := filesystem.FS.Lstat(fullPath) if err != nil { return errors.Wrap(err, "could not copy source") } @@ -265,7 +266,7 @@ func resolveIfSymlink(destPath string) (string, error) { newPath := destPath for newPath != "/" { - _, err := os.Lstat(newPath) + _, err := filesystem.FS.Lstat(newPath) if err != nil { if os.IsNotExist(err) { dir, file := filepath.Split(newPath) diff --git a/pkg/commands/copy_test.go b/pkg/commands/copy_test.go index 5f967622b7..3f979ee4b0 100755 --- a/pkg/commands/copy_test.go +++ b/pkg/commands/copy_test.go @@ -28,6 +28,7 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/testutil" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -81,7 +82,7 @@ func setupTestTemp(t *testing.T) string { if err != nil { logrus.Fatalf("Error getting abs path %s", srcPath) } - cperr := filepath.Walk(srcPath, + cperr := filesystem.Walk(srcPath, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -91,20 +92,20 @@ func setupTestTemp(t *testing.T) string { return err } tempPath := strings.TrimPrefix(path, srcPath) - fileInfo, err := os.Stat(path) + fileInfo, err := filesystem.FS.Stat(path) if err != nil { return err } if fileInfo.IsDir() { - os.MkdirAll(tempDir+"/"+tempPath, 0777) + filesystem.MkdirAll(tempDir+"/"+tempPath, 0o777) } else { - out, err := os.Create(tempDir + "/" + tempPath) + out, err := filesystem.FS.Create(tempDir + "/" + tempPath) if err != nil { return err } defer out.Close() - in, err := os.Open(path) + in, err := filesystem.FS.Open(path) if err != nil { return err } @@ -126,7 +127,7 @@ func setupTestTemp(t *testing.T) string { } func readDirectory(dirName string) ([]fs.FileInfo, error) { - entries, err := os.ReadDir(dirName) + entries, err := filesystem.ReadDir(dirName) if err != nil { return nil, err } @@ -166,7 +167,7 @@ func Test_CachingCopyCommand_ExecuteCommand(t *testing.T) { } testCases := []testCase{ func() testCase { - err = os.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("meow"), 0644) + err = filesystem.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("meow"), 0o644) if err != nil { t.Errorf("couldn't write tempfile %v", err) t.FailNow() @@ -180,7 +181,8 @@ func Test_CachingCopyCommand_ExecuteCommand(t *testing.T) { }, fileContext: util.FileContext{Root: tempDir}, cmd: &instructions.CopyCommand{ - SourcesAndDest: instructions.SourcesAndDest{SourcePaths: []string{"foo.txt"}, DestPath: ""}}, + SourcesAndDest: instructions.SourcesAndDest{SourcePaths: []string{"foo.txt"}, DestPath: ""}, + }, } count := 0 tc := testCase{ @@ -309,8 +311,10 @@ func TestCopyExecuteCmd(t *testing.T) { cmd := CopyCommand{ cmd: &instructions.CopyCommand{ - SourcesAndDest: instructions.SourcesAndDest{SourcePaths: test.sourcesAndDest[0 : len(test.sourcesAndDest)-1], - DestPath: test.sourcesAndDest[len(test.sourcesAndDest)-1]}, + SourcesAndDest: instructions.SourcesAndDest{ + SourcePaths: test.sourcesAndDest[0 : len(test.sourcesAndDest)-1], + DestPath: test.sourcesAndDest[len(test.sourcesAndDest)-1], + }, }, fileContext: fileContext, } @@ -323,7 +327,7 @@ func TestCopyExecuteCmd(t *testing.T) { t.Error() } - fi, err := os.Open(dest) + fi, err := filesystem.FS.Open(dest) if err != nil { t.Error() } @@ -350,7 +354,7 @@ func TestCopyExecuteCmd(t *testing.T) { } testutil.CheckErrorAndDeepEqual(t, false, err, test.expectedDest, dirList) - os.RemoveAll(dest) + filesystem.FS.RemoveAll(dest) }) } } @@ -375,12 +379,12 @@ func Test_resolveIfSymlink(t *testing.T) { tmpDir := t.TempDir() - baseDir, err := os.MkdirTemp(tmpDir, "not-linked") + baseDir, err := filesystem.MkdirTemp(tmpDir, "not-linked") if err != nil { t.Error(err) } - path, err := os.CreateTemp(baseDir, "foo.txt") + path, err := filesystem.CreateTemp(baseDir, "foo.txt") if err != nil { t.Error(err) } @@ -395,7 +399,7 @@ func Test_resolveIfSymlink(t *testing.T) { } baseDir = tmpDir symLink := filepath.Join(baseDir, "symlink") - if err := os.Symlink(filepath.Base(thepath), symLink); err != nil { + if err := filesystem.FS.Symlink(filepath.Base(thepath), symLink); err != nil { t.Error(err) } cases = append(cases, @@ -404,7 +408,7 @@ func Test_resolveIfSymlink(t *testing.T) { ) absSymlink := filepath.Join(tmpDir, "abs-symlink") - if err := os.Symlink(thepath, absSymlink); err != nil { + if err := filesystem.FS.Symlink(thepath, absSymlink); err != nil { t.Error(err) } cases = append(cases, @@ -432,19 +436,19 @@ func Test_CopyEnvAndWildcards(t *testing.T) { dir := filepath.Join(testDir, "bar") - if err := os.MkdirAll(dir, 0777); err != nil { + if err := filesystem.MkdirAll(dir, 0o777); err != nil { t.Fatal(err) } file := filepath.Join(dir, "bam.txt") - if err := os.WriteFile(file, []byte("meow"), 0777); err != nil { + if err := filesystem.WriteFile(file, []byte("meow"), 0o777); err != nil { t.Fatal(err) } targetPath := filepath.Join(dir, "dam.txt") - if err := os.WriteFile(targetPath, []byte("woof"), 0777); err != nil { + if err := filesystem.WriteFile(targetPath, []byte("woof"), 0o777); err != nil { t.Fatal(err) } - if err := os.Symlink("dam.txt", filepath.Join(dir, "sym.link")); err != nil { + if err := filesystem.FS.Symlink("dam.txt", filepath.Join(dir, "sym.link")); err != nil { t.Fatal(err) } @@ -452,7 +456,7 @@ func Test_CopyEnvAndWildcards(t *testing.T) { } testDir, srcDir := setupDirs(t) t.Run("copy sources into a dir defined in env variable", func(t *testing.T) { - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) expected, err := readDirectory(filepath.Join(testDir, srcDir)) if err != nil { t.Fatal(err) @@ -496,19 +500,19 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { dir := filepath.Join(testDir, "bar") - if err := os.MkdirAll(dir, 0777); err != nil { + if err := filesystem.MkdirAll(dir, 0o777); err != nil { t.Fatal(err) } file := filepath.Join(dir, "bam.txt") - if err := os.WriteFile(file, []byte("meow"), 0777); err != nil { + if err := filesystem.WriteFile(file, []byte("meow"), 0o777); err != nil { t.Fatal(err) } targetPath := filepath.Join(dir, "dam.txt") - if err := os.WriteFile(targetPath, []byte("woof"), 0777); err != nil { + if err := filesystem.WriteFile(targetPath, []byte("woof"), 0o777); err != nil { t.Fatal(err) } - if err := os.Symlink("dam.txt", filepath.Join(dir, "sym.link")); err != nil { + if err := filesystem.FS.Symlink("dam.txt", filepath.Join(dir, "sym.link")); err != nil { t.Fatal(err) } @@ -517,7 +521,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy dir to another dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) expected, err := readDirectory(filepath.Join(testDir, srcDir)) if err != nil { t.Fatal(err) @@ -554,7 +558,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy dir to another dir - with ignored files", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) ignoredFile := "bam.txt" srcFiles, err := readDirectory(filepath.Join(testDir, srcDir)) if err != nil { @@ -574,7 +578,8 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { }, fileContext: util.FileContext{ Root: testDir, - ExcludedFiles: []string{filepath.Join(srcDir, ignoredFile)}}, + ExcludedFiles: []string{filepath.Join(srcDir, ignoredFile)}, + }, } cfg := &v1.Config{ @@ -608,7 +613,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy file to a dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) cmd := CopyCommand{ cmd: &instructions.CopyCommand{ SourcesAndDest: instructions.SourcesAndDest{SourcePaths: []string{filepath.Join(srcDir, "bam.txt")}, DestPath: "dest/"}, @@ -635,7 +640,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy file to a filepath", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) cmd := CopyCommand{ cmd: &instructions.CopyCommand{ SourcesAndDest: instructions.SourcesAndDest{SourcePaths: []string{filepath.Join(srcDir, "bam.txt")}, DestPath: "dest"}, @@ -652,16 +657,16 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { err := cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{})) testutil.CheckNoError(t, err) // Check if bam.txt is copied to dest file - if _, err := os.Lstat(filepath.Join(testDir, "dest")); err != nil { + if _, err := filesystem.FS.Lstat(filepath.Join(testDir, "dest")); err != nil { t.Fatal(err) } }) t.Run("copy file to a dir without trailing /", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) destDir := filepath.Join(testDir, "dest") - if err := os.MkdirAll(destDir, 0777); err != nil { + if err := filesystem.MkdirAll(destDir, 0o777); err != nil { t.Fatal(err) } @@ -687,12 +692,11 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { } testutil.CheckDeepEqual(t, 1, len(files)) testutil.CheckDeepEqual(t, files[0].Name(), "bam.txt") - }) t.Run("copy symlink file to a dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) cmd := CopyCommand{ cmd: &instructions.CopyCommand{ @@ -718,7 +722,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { testutil.CheckDeepEqual(t, 1, len(files)) testutil.CheckDeepEqual(t, files[0].Name(), "sym.link") testutil.CheckDeepEqual(t, true, files[0].Mode()&os.ModeSymlink != 0) - linkName, err := os.Readlink(filepath.Join(testDir, "dest", "sym.link")) + linkName, err := filesystem.FS.Readlink(filepath.Join(testDir, "dest", "sym.link")) if err != nil { t.Fatal(err) } @@ -727,15 +731,15 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy deadlink symlink file to a dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) doesNotExists := filepath.Join(testDir, "dead.txt") - if err := os.WriteFile(doesNotExists, []byte("remove me"), 0777); err != nil { + if err := filesystem.WriteFile(doesNotExists, []byte("remove me"), 0o777); err != nil { t.Fatal(err) } - if err := os.Symlink("../dead.txt", filepath.Join(testDir, srcDir, "dead.link")); err != nil { + if err := filesystem.FS.Symlink("../dead.txt", filepath.Join(testDir, srcDir, "dead.link")); err != nil { t.Fatal(err) } - if err := os.Remove(doesNotExists); err != nil { + if err := filesystem.FS.Remove(doesNotExists); err != nil { t.Fatal(err) } @@ -762,7 +766,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { testutil.CheckDeepEqual(t, 1, len(files)) testutil.CheckDeepEqual(t, files[0].Name(), "dead.link") testutil.CheckDeepEqual(t, true, files[0].Mode()&os.ModeSymlink != 0) - linkName, err := os.Readlink(filepath.Join(testDir, "dest", "dead.link")) + linkName, err := filesystem.FS.Readlink(filepath.Join(testDir, "dest", "dead.link")) if err != nil { t.Fatal(err) } @@ -771,14 +775,14 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy src symlink dir to a dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) expected, err := os.ReadDir(filepath.Join(testDir, srcDir)) if err != nil { t.Fatal(err) } another := filepath.Join(testDir, "another") - os.Symlink(filepath.Join(testDir, srcDir), another) + filesystem.FS.Symlink(filepath.Join(testDir, srcDir), another) cmd := CopyCommand{ cmd: &instructions.CopyCommand{ @@ -808,21 +812,21 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy dir with a symlink to a file outside of current src dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) expected, err := readDirectory(filepath.Join(testDir, srcDir)) if err != nil { t.Fatal(err) } anotherSrc := filepath.Join(testDir, "anotherSrc") - if err := os.MkdirAll(anotherSrc, 0777); err != nil { + if err := filesystem.MkdirAll(anotherSrc, 0o777); err != nil { t.Fatal(err) } targetPath := filepath.Join(anotherSrc, "target.txt") - if err := os.WriteFile(targetPath, []byte("woof"), 0777); err != nil { + if err := filesystem.WriteFile(targetPath, []byte("woof"), 0o777); err != nil { t.Fatal(err) } - if err := os.Symlink(targetPath, filepath.Join(testDir, srcDir, "zSym.link")); err != nil { + if err := filesystem.FS.Symlink(targetPath, filepath.Join(testDir, srcDir, "zSym.link")); err != nil { t.Fatal(err) } @@ -852,7 +856,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { testutil.CheckDeepEqual(t, f.Name(), actual[i].Name()) testutil.CheckDeepEqual(t, f.Mode(), actual[i].Mode()) } - linkName, err := os.Readlink(filepath.Join(testDir, "dest", "zSym.link")) + linkName, err := filesystem.FS.Readlink(filepath.Join(testDir, "dest", "zSym.link")) if err != nil { t.Fatal(err) } @@ -861,14 +865,14 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy src symlink dir to a dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) expected, err := os.ReadDir(filepath.Join(testDir, srcDir)) if err != nil { t.Fatal(err) } another := filepath.Join(testDir, "another") - os.Symlink(filepath.Join(testDir, srcDir), another) + filesystem.FS.Symlink(filepath.Join(testDir, srcDir), another) cmd := CopyCommand{ cmd: &instructions.CopyCommand{ @@ -898,18 +902,18 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy src dir to a dest dir which is a symlink", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) expected, err := readDirectory(filepath.Join(testDir, srcDir)) if err != nil { t.Fatal(err) } dest := filepath.Join(testDir, "dest") - if err := os.MkdirAll(dest, 0777); err != nil { + if err := filesystem.MkdirAll(dest, 0o777); err != nil { t.Fatal(err) } linkedDest := filepath.Join(testDir, "linkDest") - if err := os.Symlink(dest, linkedDest); err != nil { + if err := filesystem.FS.Symlink(dest, linkedDest); err != nil { t.Fatal(err) } @@ -938,7 +942,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { testutil.CheckDeepEqual(t, f.Mode(), actual[i].Mode()) } // Check if linkDest -> dest - linkName, err := os.Readlink(filepath.Join(testDir, "linkDest")) + linkName, err := filesystem.FS.Readlink(filepath.Join(testDir, "linkDest")) if err != nil { t.Fatal(err) } @@ -947,14 +951,14 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy src file to a dest dir which is a symlink", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) dest := filepath.Join(testDir, "dest") - if err := os.MkdirAll(dest, 0777); err != nil { + if err := filesystem.MkdirAll(dest, 0o777); err != nil { t.Fatal(err) } linkedDest := filepath.Join(testDir, "linkDest") - if err := os.Symlink(dest, linkedDest); err != nil { + if err := filesystem.FS.Symlink(dest, linkedDest); err != nil { t.Fatal(err) } @@ -979,13 +983,13 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Fatal(err) } testutil.CheckDeepEqual(t, "bam.txt", actual[0].Name()) - c, err := os.ReadFile(filepath.Join(testDir, "dest", "bam.txt")) + c, err := filesystem.ReadFile(filepath.Join(testDir, "dest", "bam.txt")) if err != nil { t.Fatal(err) } testutil.CheckDeepEqual(t, "meow", string(c)) // Check if linkDest -> dest - linkName, err := os.Readlink(filepath.Join(testDir, "linkDest")) + linkName, err := filesystem.FS.Readlink(filepath.Join(testDir, "linkDest")) if err != nil { t.Fatal(err) } @@ -994,7 +998,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy src file to a dest dir with chown", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) original := getUserGroup defer func() { getUserGroup = original }() @@ -1042,7 +1046,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy src file to a dest dir with chown and random user", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) original := getUserGroup defer func() { getUserGroup = original }() @@ -1073,14 +1077,14 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Run("copy src dir with relative symlinks in a dir", func(t *testing.T) { testDir, srcDir := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) // Make another dir inside bar with a relative symlink dir := filepath.Join(testDir, srcDir, "another") - if err := os.MkdirAll(dir, 0777); err != nil { + if err := filesystem.MkdirAll(dir, 0o777); err != nil { t.Fatal(err) } - os.Symlink("../bam.txt", filepath.Join(dir, "bam_relative.txt")) + filesystem.FS.Symlink("../bam.txt", filepath.Join(dir, "bam_relative.txt")) dest := filepath.Join(testDir, "copy") cmd := CopyCommand{ @@ -1102,7 +1106,7 @@ func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) { t.Fatal(err) } testutil.CheckDeepEqual(t, "bam_relative.txt", actual[0].Name()) - linkName, err := os.Readlink(filepath.Join(dest, "another", "bam_relative.txt")) + linkName, err := filesystem.FS.Readlink(filepath.Join(dest, "another", "bam_relative.txt")) if err != nil { t.Fatal(err) } diff --git a/pkg/commands/run.go b/pkg/commands/run.go index ed2d5a5bc1..10bc5599ce 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -27,6 +27,7 @@ import ( kConfig "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/moby/buildkit/frontend/dockerfile/instructions" @@ -145,7 +146,7 @@ func runCommandInExec(config *v1.Config, buildArgs *dockerfile.BuildArgs, cmdRun return errors.Wrap(err, "waiting for process to exit") } - //it's not an error if there are no grandchildren + // it's not an error if there are no grandchildren if err := syscall.Kill(-pgid, syscall.SIGKILL); err != nil && err.Error() != "no such process" { return err } @@ -191,7 +192,6 @@ func (r *RunCommand) ProvidesFilesToSnapshot() bool { // CacheCommand returns true since this command should be cached func (r *RunCommand) CacheCommand(img v1.Image) DockerCommand { - return &CachingRunCommand{ img: img, cmd: r.cmd, @@ -300,7 +300,7 @@ func (cr *CachingRunCommand) MetadataOnly() bool { // todo: this should create the workdir if it doesn't exist, atleast this is what docker does func setWorkDirIfExists(workdir string) string { - if _, err := os.Lstat(workdir); err == nil { + if _, err := filesystem.FS.Lstat(workdir); err == nil { return workdir } return "" diff --git a/pkg/commands/run_test.go b/pkg/commands/run_test.go index 135d7e2a78..1000b720bf 100644 --- a/pkg/commands/run_test.go +++ b/pkg/commands/run_test.go @@ -27,6 +27,7 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/testutil" v1 "github.com/google/go-containerregistry/pkg/v1" ) @@ -129,14 +130,14 @@ Meow meow meow meow meow meow meow meow ` for _, name := range fileNames { - if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0777); err != nil { + if err := filesystem.WriteFile(filepath.Join(dir, name), []byte(content), 0o777); err != nil { return nil, err } } writer := bytes.NewBuffer([]byte{}) tw := tar.NewWriter(writer) defer tw.Close() - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + filesystem.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -152,7 +153,7 @@ meow meow meow meow if err := tw.WriteHeader(hdr); err != nil { log.Fatal(err) } - body, err := os.ReadFile(path) + body, err := filesystem.ReadFile(path) if err != nil { return err } diff --git a/pkg/commands/volume.go b/pkg/commands/volume.go index d4ae3dd17c..f122fe13f1 100644 --- a/pkg/commands/volume.go +++ b/pkg/commands/volume.go @@ -21,6 +21,7 @@ import ( "os" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -51,9 +52,9 @@ func (v *VolumeCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile. util.AddVolumePathToIgnoreList(volume) // Only create and snapshot the dir if it didn't exist already - if _, err := os.Stat(volume); os.IsNotExist(err) { + if _, err := filesystem.FS.Stat(volume); os.IsNotExist(err) { logrus.Infof("Creating directory %s", volume) - if err := os.MkdirAll(volume, 0755); err != nil { + if err := filesystem.MkdirAll(volume, 0o755); err != nil { return fmt.Errorf("could not create directory for volume %s: %w", volume, err) } } diff --git a/pkg/commands/workdir.go b/pkg/commands/workdir.go index b97c4da841..393cd7e914 100644 --- a/pkg/commands/workdir.go +++ b/pkg/commands/workdir.go @@ -21,6 +21,7 @@ import ( "path/filepath" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/pkg/errors" "github.com/GoogleContainerTools/kaniko/pkg/util" @@ -59,7 +60,7 @@ func (w *WorkdirCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile // Only create and snapshot the dir if it didn't exist already w.snapshotFiles = []string{} - if _, err := os.Stat(config.WorkingDir); os.IsNotExist(err) { + if _, err := filesystem.FS.Stat(config.WorkingDir); os.IsNotExist(err) { uid, gid := int64(-1), int64(-1) if config.User != "" { @@ -72,7 +73,7 @@ func (w *WorkdirCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile logrus.Infof("Creating directory %s with uid %d and gid %d", config.WorkingDir, uid, gid) w.snapshotFiles = append(w.snapshotFiles, config.WorkingDir) - if err := mkdirAllWithPermissions(config.WorkingDir, 0755, uid, gid); err != nil { + if err := mkdirAllWithPermissions(config.WorkingDir, 0o755, uid, gid); err != nil { return errors.Wrapf(err, "creating workdir %s", config.WorkingDir) } } diff --git a/pkg/dockerfile/dockerfile.go b/pkg/dockerfile/dockerfile.go index 4de07680b1..2093b8bd17 100644 --- a/pkg/dockerfile/dockerfile.go +++ b/pkg/dockerfile/dockerfile.go @@ -21,7 +21,6 @@ import ( "fmt" "io" "net/http" - "os" "regexp" "strconv" "strings" @@ -30,6 +29,7 @@ import ( "github.com/sirupsen/logrus" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/moby/buildkit/frontend/dockerfile/instructions" "github.com/moby/buildkit/frontend/dockerfile/parser" @@ -50,7 +50,7 @@ func ParseStages(opts *config.KanikoOptions) ([]instructions.Stage, []instructio } d, err = io.ReadAll(response.Body) } else { - d, err = os.ReadFile(opts.DockerfilePath) + d, err = filesystem.ReadFile(opts.DockerfilePath) } } diff --git a/pkg/dockerfile/dockerfile_test.go b/pkg/dockerfile/dockerfile_test.go index b38fb81ef7..80b821a29c 100644 --- a/pkg/dockerfile/dockerfile_test.go +++ b/pkg/dockerfile/dockerfile_test.go @@ -18,11 +18,11 @@ package dockerfile import ( "fmt" - "os" "reflect" "testing" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/testutil" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/moby/buildkit/frontend/dockerfile/instructions" @@ -44,12 +44,12 @@ func Test_ParseStages_ArgValueWithQuotes(t *testing.T) { FROM scratch COPY --from=second /hi2 /hi3 ` - tmpfile, err := os.CreateTemp("", "Dockerfile.test") + tmpfile, err := filesystem.CreateTemp("", "Dockerfile.test") if err != nil { t.Fatal(err) } - defer os.Remove(tmpfile.Name()) + defer filesystem.FS.Remove(tmpfile.Name()) if _, err := tmpfile.Write([]byte(dockerfile)); err != nil { t.Fatal(err) @@ -201,17 +201,20 @@ func Test_GetOnBuildInstructions(t *testing.T) { } tests := []testCase{ - {name: "no on-build on config", + { + name: "no on-build on config", cfg: &v1.Config{}, stageToIdx: map[string]string{"builder": "0"}, expCommands: nil, }, - {name: "onBuild on config, nothing to resolve", + { + name: "onBuild on config, nothing to resolve", cfg: &v1.Config{OnBuild: []string{"WORKDIR /app"}}, stageToIdx: map[string]string{"builder": "0", "temp": "1"}, expCommands: []instructions.Command{&instructions.WorkdirCommand{Path: "/app"}}, }, - {name: "onBuild on config, resolve multiple stages", + { + name: "onBuild on config, resolve multiple stages", cfg: &v1.Config{OnBuild: []string{"COPY --from=builder a.txt b.txt", "COPY --from=temp /app /app"}}, stageToIdx: map[string]string{"builder": "0", "temp": "1"}, expCommands: []instructions.Command{ @@ -223,7 +226,8 @@ func Test_GetOnBuildInstructions(t *testing.T) { SourcesAndDest: instructions.SourcesAndDest{SourcePaths: []string{"/app"}, DestPath: "/app"}, From: "1", }, - }}, + }, + }, } for _, test := range tests { diff --git a/pkg/executor/build.go b/pkg/executor/build.go index 164c54fe76..889da2a5b1 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -18,7 +18,6 @@ package executor import ( "fmt" - "os" "path/filepath" "runtime" "sort" @@ -42,6 +41,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" image_util "github.com/GoogleContainerTools/kaniko/pkg/image" "github.com/GoogleContainerTools/kaniko/pkg/image/remote" "github.com/GoogleContainerTools/kaniko/pkg/snapshot" @@ -59,12 +59,14 @@ var ( getFSFromImage = util.GetFSFromImage ) -type cachePusher func(*config.KanikoOptions, string, string, string) error -type snapShotter interface { - Init() error - TakeSnapshotFS() (string, error) - TakeSnapshot([]string, bool, bool) (string, error) -} +type ( + cachePusher func(*config.KanikoOptions, string, string, string) error + snapShotter interface { + Init() error + TakeSnapshotFS() (string, error) + TakeSnapshot([]string, bool, bool) (string, error) + } +) // stageBuilder contains all fields necessary to build one stage of a Dockerfile type stageBuilder struct { @@ -239,7 +241,7 @@ func (s *stageBuilder) optimize(compositeKey CompositeCache, cfg v1.Config) erro if !s.opts.Cache { return nil } - var buildArgs = s.args.Clone() + buildArgs := s.args.Clone() // Restore build args back to their original values defer func() { s.args = buildArgs @@ -275,7 +277,6 @@ func (s *stageBuilder) optimize(compositeKey CompositeCache, cfg v1.Config) erro if command.ShouldCacheOutput() && !stopCache { img, err := s.layerCache.RetrieveLayer(ck) - if err != nil { logrus.Debugf("Failed to retrieve layer: %s", err) logrus.Infof("No cached layer found for cmd %s", command.String()) @@ -593,7 +594,7 @@ func (s *stageBuilder) saveSnapshotToLayer(tarPath string) (v1.Layer, error) { if tarPath == "" { return nil, nil } - fi, err := os.Stat(tarPath) + fi, err := filesystem.FS.Stat(tarPath) if err != nil { return nil, errors.Wrap(err, "tar file path does not exist") } @@ -913,7 +914,7 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { return nil, err } dstDir := filepath.Join(config.KanikoDir, strconv.Itoa(index)) - if err := os.MkdirAll(dstDir, 0644); err != nil { + if err := filesystem.MkdirAll(dstDir, 0o644); err != nil { return nil, errors.Wrap(err, fmt.Sprintf("to create workspace for stage %s", stageIdxToDigest[strconv.Itoa(index)], @@ -1201,7 +1202,7 @@ func extractImageToDependencyDir(name string, image v1.Image) error { t := timing.Start("Extracting Image to Dependency Dir") defer timing.DefaultRun.Stop(t) dependencyDir := filepath.Join(config.KanikoDir, name) - if err := os.MkdirAll(dependencyDir, 0755); err != nil { + if err := filesystem.MkdirAll(dependencyDir, 0o755); err != nil { return err } logrus.Debugf("Trying to extract to %s", dependencyDir) @@ -1218,7 +1219,7 @@ func saveStageAsTarball(path string, image v1.Image) error { } tarPath := filepath.Join(config.KanikoIntermediateStagesDir, path) logrus.Infof("Storing source image from stage %s at path %s", path, tarPath) - if err := os.MkdirAll(filepath.Dir(tarPath), 0750); err != nil { + if err := filesystem.MkdirAll(filepath.Dir(tarPath), 0o750); err != nil { return err } return tarball.WriteToFile(tarPath, destRef, image) diff --git a/pkg/executor/build_test.go b/pkg/executor/build_test.go index 4191b13f5d..fadf66ad7c 100644 --- a/pkg/executor/build_test.go +++ b/pkg/executor/build_test.go @@ -20,7 +20,6 @@ import ( "archive/tar" "bytes" "fmt" - "os" "path/filepath" "reflect" "sort" @@ -31,6 +30,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/commands" "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/testutil" "github.com/containerd/containerd/platforms" @@ -195,7 +195,6 @@ func Test_stageBuilder_shouldTakeSnapshot(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if tt.fields.opts == nil { tt.fields.opts = &config.KanikoOptions{} } @@ -369,8 +368,8 @@ COPY --from=second /bar /bat initializeConfig = tt.args.mockInitConfig } - f, _ := os.CreateTemp("", "") - os.WriteFile(f.Name(), []byte(tt.args.dockerfile), 0755) + f, _ := filesystem.CreateTemp("", "") + filesystem.WriteFile(f.Name(), []byte(tt.args.dockerfile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: f.Name(), CustomPlatform: platforms.Format(platforms.Normalize(platforms.DefaultSpec())), @@ -444,11 +443,11 @@ func Test_filesToSave(t *testing.T) { p := filepath.Join(tmpDir, f) dir := filepath.Dir(p) if dir != "." { - if err := os.MkdirAll(dir, 0755); err != nil { + if err := filesystem.MkdirAll(dir, 0o755); err != nil { t.Errorf("error making dir: %s", err) } } - fp, err := os.Create(p) + fp, err := filesystem.FS.Create(p) if err != nil { t.Errorf("error making file: %s", err) } @@ -618,10 +617,12 @@ func Test_stageBuilder_optimize(t *testing.T) { cf := &v1.ConfigFile{} snap := &fakeSnapShotter{} lc := &fakeLayerCache{retrieve: tc.retrieve} - sb := &stageBuilder{opts: tc.opts, cf: cf, snapshotter: snap, layerCache: lc, - args: dockerfile.NewBuildArgs([]string{})} + sb := &stageBuilder{ + opts: tc.opts, cf: cf, snapshotter: snap, layerCache: lc, + args: dockerfile.NewBuildArgs([]string{}), + } ck := CompositeCache{} - file, err := os.CreateTemp("", "foo") + file, err := filesystem.CreateTemp("", "foo") if err != nil { t.Error(err) } @@ -634,7 +635,6 @@ func Test_stageBuilder_optimize(t *testing.T) { if err != nil { t.Errorf("Expected error to be nil but was %v", err) } - }) } } @@ -1063,8 +1063,8 @@ func Test_stageBuilder_build(t *testing.T) { FROM ubuntu:16.04 COPY %s foo.txt `, filename) - f, _ := os.CreateTemp("", "") - os.WriteFile(f.Name(), []byte(dockerFile), 0755) + f, _ := filesystem.CreateTemp("", "") + filesystem.WriteFile(f.Name(), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: f.Name(), Cache: true, @@ -1129,8 +1129,8 @@ func Test_stageBuilder_build(t *testing.T) { FROM ubuntu:16.04 COPY %s foo.txt `, filename) - f, _ := os.CreateTemp("", "") - os.WriteFile(f.Name(), []byte(dockerFile), 0755) + f, _ := filesystem.CreateTemp("", "") + filesystem.WriteFile(f.Name(), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: f.Name(), Cache: true, @@ -1208,8 +1208,8 @@ FROM ubuntu:16.04 RUN foobar COPY %s bar.txt `, filename) - f, _ := os.CreateTemp("", "") - os.WriteFile(f.Name(), []byte(dockerFile), 0755) + f, _ := filesystem.CreateTemp("", "") + filesystem.WriteFile(f.Name(), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: f.Name(), } @@ -1282,8 +1282,8 @@ FROM ubuntu:16.04 COPY %s bar.txt RUN foobar `, filename) - f, _ := os.CreateTemp("", "") - os.WriteFile(f.Name(), []byte(dockerFile), 0755) + f, _ := filesystem.CreateTemp("", "") + filesystem.WriteFile(f.Name(), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: f.Name(), } @@ -1450,7 +1450,7 @@ RUN foobar t.Run(tc.description, func(t *testing.T) { var fileName string if tc.commands == nil { - file, err := os.CreateTemp("", "foo") + file, err := filesystem.CreateTemp("", "foo") if err != nil { t.Error(err) } @@ -1482,7 +1482,7 @@ RUN foobar } keys := []string{} sb := &stageBuilder{ - args: dockerfile.NewBuildArgs([]string{}), //required or code will panic + args: dockerfile.NewBuildArgs([]string{}), // required or code will panic image: tc.image, opts: tc.opts, cf: cf, @@ -1521,7 +1521,6 @@ RUN foobar assertCacheKeys(t, tc.pushedCacheKeys, keys, "push") config.RootDir = tmp - }) } } @@ -1574,7 +1573,7 @@ func tempDirAndFile(t *testing.T) (string, []string) { dir := t.TempDir() for _, filename := range filenames { filepath := filepath.Join(dir, filename) - err := os.WriteFile(filepath, []byte(`meow`), 0777) + err := filesystem.WriteFile(filepath, []byte(`meow`), 0o777) if err != nil { t.Errorf("could not create temp file %v", err) } @@ -1590,7 +1589,7 @@ func generateTar(t *testing.T, dir string, fileNames ...string) []byte { for _, filename := range fileNames { filePath := filepath.Join(dir, filename) - info, err := os.Stat(filePath) + info, err := filesystem.FS.Stat(filePath) if err != nil { t.Errorf("could not get file info for temp file %v", err) } @@ -1603,7 +1602,7 @@ func generateTar(t *testing.T, dir string, fileNames ...string) []byte { t.Errorf("could not write tar header %v", err) } - content, err := os.ReadFile(filePath) + content, err := filesystem.ReadFile(filePath) if err != nil { t.Errorf("could not read tempfile %v", err) } @@ -1696,7 +1695,6 @@ func Test_stageBuild_populateCompositeKeyForCopyCommand(t *testing.T) { actualCacheKey, ) } - }) } }) diff --git a/pkg/executor/cache_probe_test.go b/pkg/executor/cache_probe_test.go index 53e04db260..ce13a16c71 100644 --- a/pkg/executor/cache_probe_test.go +++ b/pkg/executor/cache_probe_test.go @@ -20,7 +20,6 @@ import ( "fmt" "net/http/httptest" "net/url" - "os" "path/filepath" "strings" "testing" @@ -30,6 +29,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/testutil" ) @@ -40,7 +40,7 @@ func TestDoCacheProbe(t *testing.T) { dockerFile := `FROM scratch COPY foo/bar.txt copied/ ` - err := os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) + err := filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) testutil.CheckNoError(t, err) regCache := setupCacheRegistry(t) opts := &config.KanikoOptions{ @@ -67,7 +67,7 @@ COPY foo/bar.txt copied/ dockerFile := `FROM scratch COPY foo/bar.txt copied/ ` - err := os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) + err := filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) testutil.CheckNoError(t, err) regCache := setupCacheRegistry(t) opts := &config.KanikoOptions{ @@ -99,7 +99,7 @@ COPY foo/bar.txt copied/ ARG foo=bar ENV baz=qux ` - err := os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) + err := filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) testutil.CheckNoError(t, err) regCache := setupCacheRegistry(t) opts := &config.KanikoOptions{ @@ -130,7 +130,7 @@ ENV baz=qux dockerFile := `FROM scratch COPY foo/bar.txt copied/ ` - err := os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) + err := filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) testutil.CheckNoError(t, err) regCache := setupCacheRegistry(t) opts := &config.KanikoOptions{ @@ -156,7 +156,7 @@ COPY foo/bar.txt copied/ COPY foo/bar.txt copied/ COPY foo/baz.txt copied/ ` - err = os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) + err = filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) testutil.CheckNoError(t, err) _, err = DoCacheProbe(opts) if err == nil || !strings.Contains(err.Error(), "uncached COPY command") { @@ -179,7 +179,7 @@ COPY foo/baz.txt copied/ From scratch as second COPY --from=first copied/bam.txt output/bam.txt` - err := os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) + err := filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) testutil.CheckNoError(t, err) opts := &config.KanikoOptions{ DockerfilePath: filepath.Join(testDir, "workspace", "Dockerfile"), @@ -250,20 +250,20 @@ func setupCacheProbeTests(t *testing.T) (string, func()) { // - /foo // - bar.txt // - baz.txt - if err := os.MkdirAll(filepath.Join(testDir, "kaniko/0"), 0755); err != nil { + if err := filesystem.MkdirAll(filepath.Join(testDir, "kaniko/0"), 0o755); err != nil { t.Fatal(err) } workspace := filepath.Join(testDir, "workspace") // Make foo - if err := os.MkdirAll(filepath.Join(workspace, "foo"), 0755); err != nil { + if err := filesystem.MkdirAll(filepath.Join(workspace, "foo"), 0o755); err != nil { t.Fatal(err) } file := filepath.Join(workspace, "foo", "bar.txt") - if err := os.WriteFile(file, []byte("hello"), 0755); err != nil { + if err := filesystem.WriteFile(file, []byte("hello"), 0o755); err != nil { t.Fatal(err) } file2 := filepath.Join(workspace, "foo", "baz.txt") - if err := os.WriteFile(file2, []byte("world"), 0755); err != nil { + if err := filesystem.WriteFile(file2, []byte("world"), 0o755); err != nil { t.Fatal(err) } @@ -271,7 +271,7 @@ func setupCacheProbeTests(t *testing.T) (string, func()) { config.RootDir = testDir config.KanikoDir = fmt.Sprintf("%s/%s", testDir, "kaniko") // Write path to ignore list - if err := os.MkdirAll(filepath.Join(testDir, "proc"), 0755); err != nil { + if err := filesystem.MkdirAll(filepath.Join(testDir, "proc"), 0o755); err != nil { t.Fatal(err) } mFile := filepath.Join(testDir, "proc/mountinfo") @@ -279,7 +279,7 @@ func setupCacheProbeTests(t *testing.T) (string, func()) { `36 35 98:0 /kaniko %s/kaniko rw,noatime master:1 - ext3 /dev/root rw,errors=continue 36 35 98:0 /proc %s/proc rw,noatime master:1 - ext3 /dev/root rw,errors=continue `, testDir, testDir) - if err := os.WriteFile(mFile, []byte(mountInfo), 0644); err != nil { + if err := filesystem.WriteFile(mFile, []byte(mountInfo), 0o644); err != nil { t.Fatal(err) } config.MountInfoPath = mFile diff --git a/pkg/executor/composite_cache.go b/pkg/executor/composite_cache.go index 2c1e00d25e..40bf7f3d60 100644 --- a/pkg/executor/composite_cache.go +++ b/pkg/executor/composite_cache.go @@ -20,9 +20,9 @@ import ( "crypto/sha256" "fmt" "os" - "path/filepath" "strings" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/pkg/errors" ) @@ -57,7 +57,7 @@ func (s *CompositeCache) Hash() (string, error) { func (s *CompositeCache) AddPath(p string, context util.FileContext) error { sha := sha256.New() - fi, err := os.Lstat(p) + fi, err := filesystem.FS.Lstat(p) if err != nil { return errors.Wrap(err, "could not add path") } @@ -95,7 +95,7 @@ func (s *CompositeCache) AddPath(p string, context util.FileContext) error { func hashDir(p string, context util.FileContext) (bool, string, error) { sha := sha256.New() empty := true - if err := filepath.Walk(p, func(path string, fi os.FileInfo, err error) error { + if err := filesystem.Walk(p, func(path string, fi os.FileInfo, err error) error { if err != nil { return err } diff --git a/pkg/executor/composite_cache_test.go b/pkg/executor/composite_cache_test.go index 86dc73f14c..0688cc1eaf 100644 --- a/pkg/executor/composite_cache_test.go +++ b/pkg/executor/composite_cache_test.go @@ -17,12 +17,12 @@ limitations under the License. package executor import ( - "os" "path" "path/filepath" "reflect" "testing" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" ) @@ -70,7 +70,7 @@ func Test_CompositeCache_AddPath_dir(t *testing.T) { tmpDir := t.TempDir() content := `meow meow meow` - if err := os.WriteFile(filepath.Join(tmpDir, "foo.txt"), []byte(content), 0777); err != nil { + if err := filesystem.WriteFile(filepath.Join(tmpDir, "foo.txt"), []byte(content), 0o777); err != nil { t.Errorf("got error writing temp file %v", err) } @@ -96,12 +96,13 @@ func Test_CompositeCache_AddPath_dir(t *testing.T) { t.Errorf("expected hash %v to equal hash %v", hash1, hash2) } } + func Test_CompositeCache_AddPath_file(t *testing.T) { - tmpfile, err := os.CreateTemp("/tmp", "foo.txt") + tmpfile, err := filesystem.CreateTemp("/tmp", "foo.txt") if err != nil { t.Errorf("got error setting up test %v", err) } - defer os.Remove(tmpfile.Name()) // clean up + defer filesystem.FS.Remove(tmpfile.Name()) // clean up content := `meow meow meow` if _, err := tmpfile.Write([]byte(content)); err != nil { @@ -138,14 +139,14 @@ func Test_CompositeCache_AddPath_file(t *testing.T) { func createFilesystemStructure(root string, directories, files []string) error { for _, d := range directories { dirPath := path.Join(root, d) - if err := os.MkdirAll(dirPath, 0755); err != nil { + if err := filesystem.MkdirAll(dirPath, 0o755); err != nil { return err } } for _, fileName := range files { filePath := path.Join(root, fileName) - err := os.WriteFile(filePath, []byte(fileName), 0644) + err := filesystem.WriteFile(filePath, []byte(fileName), 0o644) if err != nil { return err } @@ -157,7 +158,7 @@ func createFilesystemStructure(root string, directories, files []string) error { func setIgnoreContext(t *testing.T, content string) (util.FileContext, error) { var fileContext util.FileContext dockerIgnoreDir := t.TempDir() - err := os.WriteFile(dockerIgnoreDir+".dockerignore", []byte(content), 0644) + err := filesystem.WriteFile(dockerIgnoreDir+".dockerignore", []byte(content), 0o644) if err != nil { return fileContext, err } @@ -287,7 +288,7 @@ func Test_CompositeKey_AddPath_WithExtraFile_Works(t *testing.T) { t.Fatalf("Error creating filesytem structure: %s", err) } extraPath := path.Join(testDir2, test.extraFile) - err = os.WriteFile(extraPath, []byte(test.extraFile), 0644) + err = filesystem.WriteFile(extraPath, []byte(test.extraFile), 0o644) if err != nil { t.Fatalf("Error creating filesytem structure: %s", err) } @@ -357,7 +358,7 @@ func Test_CompositeKey_AddPath_WithExtraDir_Works(t *testing.T) { t.Fatalf("Error creating filesytem structure: %s", err) } extraPath := path.Join(testDir2, test.extraDir) - err = os.MkdirAll(extraPath, 0644) + err = filesystem.MkdirAll(extraPath, 0o644) if err != nil { t.Fatalf("Error creating filesytem structure: %s", err) } @@ -430,7 +431,7 @@ func Test_CompositeKey_AddPath_WithExtraFilIgnored_Works(t *testing.T) { t.Fatalf("Error creating filesytem structure: %s", err) } extraPath := path.Join(testDir2, test.extraFile) - err = os.WriteFile(extraPath, []byte(test.extraFile), 0644) + err = filesystem.WriteFile(extraPath, []byte(test.extraFile), 0o644) if err != nil { t.Fatalf("Error creating filesytem structure: %s", err) } @@ -503,7 +504,7 @@ func Test_CompositeKey_AddPath_WithExtraDirIgnored_Works(t *testing.T) { t.Fatalf("Error creating filesytem structure: %s", err) } extraPath := path.Join(testDir2, test.extraDir) - err = os.MkdirAll(extraPath, 0644) + err = filesystem.MkdirAll(extraPath, 0o644) if err != nil { t.Fatalf("Error creating filesytem structure: %s", err) } diff --git a/pkg/executor/copy_multistage_test.go b/pkg/executor/copy_multistage_test.go index e334859d8d..949fa2f437 100644 --- a/pkg/executor/copy_multistage_test.go +++ b/pkg/executor/copy_multistage_test.go @@ -25,11 +25,12 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/testutil" ) func readDirectory(dirName string) ([]fs.FileInfo, error) { - entries, err := os.ReadDir(dirName) + entries, err := filesystem.ReadDir(dirName) if err != nil { return nil, err } @@ -57,7 +58,7 @@ ENV test test From scratch as second COPY --from=first copied/bam.txt output/bam.txt` - os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0755) + filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: filepath.Join(testDir, "workspace", "Dockerfile"), SrcContext: filepath.Join(testDir, "workspace"), @@ -72,7 +73,6 @@ COPY --from=first copied/bam.txt output/bam.txt` } testutil.CheckDeepEqual(t, 1, len(files)) testutil.CheckDeepEqual(t, files[0].Name(), "bam.txt") - }) t.Run("copy a file across multistage into a directory", func(t *testing.T) { @@ -85,7 +85,7 @@ ENV test test From scratch as second COPY --from=first copied/bam.txt output/` - os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0755) + filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: filepath.Join(testDir, "workspace", "Dockerfile"), SrcContext: filepath.Join(testDir, "workspace"), @@ -111,7 +111,7 @@ ENV test test From scratch as second COPY --from=first copied another` - os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0755) + filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: filepath.Join(testDir, "workspace", "Dockerfile"), SrcContext: filepath.Join(testDir, "workspace"), @@ -129,7 +129,7 @@ COPY --from=first copied another` testutil.CheckDeepEqual(t, files[1].Name(), "bam.txt") // TODO fix this // path := filepath.Join(testDir, "output/another", "bam.link") - //linkName, err := os.Readlink(path) + //linkName, err := filesystem.FS.Readlink(path) //if err != nil { // t.Fatal(err) //} @@ -146,7 +146,7 @@ ENV test test From scratch as second COPY --from=first / output/` - os.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0755) + filesystem.WriteFile(filepath.Join(testDir, "workspace", "Dockerfile"), []byte(dockerFile), 0o755) opts := &config.KanikoOptions{ DockerfilePath: filepath.Join(testDir, "workspace", "Dockerfile"), SrcContext: filepath.Join(testDir, "workspace"), @@ -188,36 +188,36 @@ func setupMultistageTests(t *testing.T) (string, func()) { // Make directory for stage or else the executor will create with permissions 0664 // and we will run into issue https://github.com/golang/go/issues/22323 - if err := os.MkdirAll(filepath.Join(testDir, "kaniko/0"), 0755); err != nil { + if err := filesystem.MkdirAll(filepath.Join(testDir, "kaniko/0"), 0o755); err != nil { t.Fatal(err) } workspace := filepath.Join(testDir, "workspace") // Make foo - if err := os.MkdirAll(filepath.Join(workspace, "foo"), 0755); err != nil { + if err := filesystem.MkdirAll(filepath.Join(workspace, "foo"), 0o755); err != nil { t.Fatal(err) } file := filepath.Join(workspace, "foo", "bam.txt") - if err := os.WriteFile(file, []byte("meow"), 0755); err != nil { + if err := filesystem.WriteFile(file, []byte("meow"), 0o755); err != nil { t.Fatal(err) } - os.Symlink("bam.txt", filepath.Join(workspace, "foo", "bam.link")) + filesystem.FS.Symlink("bam.txt", filepath.Join(workspace, "foo", "bam.link")) // Make a file with contents link file = filepath.Join(workspace, "exec") - if err := os.WriteFile(file, []byte("woof"), 0755); err != nil { + if err := filesystem.WriteFile(file, []byte("woof"), 0o755); err != nil { t.Fatal(err) } // Make bin - if err := os.MkdirAll(filepath.Join(workspace, "bin"), 0755); err != nil { + if err := filesystem.MkdirAll(filepath.Join(workspace, "bin"), 0o755); err != nil { t.Fatal(err) } - os.Symlink("../exec", filepath.Join(workspace, "bin", "exec.link")) + filesystem.FS.Symlink("../exec", filepath.Join(workspace, "bin", "exec.link")) // set up config config.RootDir = testDir config.KanikoDir = fmt.Sprintf("%s/%s", testDir, "kaniko") // Write path to ignore list - if err := os.MkdirAll(filepath.Join(testDir, "proc"), 0755); err != nil { + if err := filesystem.MkdirAll(filepath.Join(testDir, "proc"), 0o755); err != nil { t.Fatal(err) } mFile := filepath.Join(testDir, "proc/mountinfo") @@ -225,7 +225,7 @@ func setupMultistageTests(t *testing.T) (string, func()) { `36 35 98:0 /kaniko %s/kaniko rw,noatime master:1 - ext3 /dev/root rw,errors=continue 36 35 98:0 /proc %s/proc rw,noatime master:1 - ext3 /dev/root rw,errors=continue `, testDir, testDir) - if err := os.WriteFile(mFile, []byte(mountInfo), 0644); err != nil { + if err := filesystem.WriteFile(mFile, []byte(mountInfo), 0o644); err != nil { t.Fatal(err) } config.MountInfoPath = mFile diff --git a/pkg/executor/push.go b/pkg/executor/push.go index c95aecc351..d7287fc425 100644 --- a/pkg/executor/push.go +++ b/pkg/executor/push.go @@ -30,6 +30,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" "github.com/GoogleContainerTools/kaniko/pkg/creds" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/timing" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/pkg/version" @@ -62,15 +63,13 @@ const ( DummyDestination = "docker.io/unset-repo/unset-image-name" ) -var ( - // known tag immutability errors - errTagImmutable = []string{ - // https://cloud.google.com/artifact-registry/docs/docker/troubleshoot#push - "The repository has enabled tag immutability", - // https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-tag-mutability.html - "cannot be overwritten because the repository is immutable", - } -) +// known tag immutability errors +var errTagImmutable = []string{ + // https://cloud.google.com/artifact-registry/docs/docker/troubleshoot#push + "The repository has enabled tag immutability", + // https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-tag-mutability.html + "cannot be overwritten because the repository is immutable", +} func (w *withUserAgent) RoundTrip(r *http.Request) (*http.Response, error) { ua := []string{fmt.Sprintf("kaniko/%s", version.Version())} @@ -158,14 +157,14 @@ func writeDigestFile(path string, digestByteArray []byte) error { } parentDir := filepath.Dir(path) - if _, err := os.Stat(parentDir); os.IsNotExist(err) { - if err := os.MkdirAll(parentDir, 0700); err != nil { + if _, err := filesystem.FS.Stat(parentDir); os.IsNotExist(err) { + if err := filesystem.MkdirAll(parentDir, 0o700); err != nil { logrus.Debugf("Error creating %s, %s", parentDir, err) return err } logrus.Tracef("Created directory %v", parentDir) } - return os.WriteFile(path, digestByteArray, 0644) + return filesystem.WriteFile(path, digestByteArray, 0o644) } // DoPush is responsible for pushing image to the destinations specified in opts. diff --git a/pkg/executor/push_test.go b/pkg/executor/push_test.go index 3a67843b19..122def9810 100644 --- a/pkg/executor/push_test.go +++ b/pkg/executor/push_test.go @@ -27,6 +27,7 @@ import ( "testing" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/testutil" "github.com/google/go-containerregistry/pkg/authn" @@ -111,17 +112,17 @@ func TestHeaderAdded(t *testing.T) { name string upstream string expected string - }{{ - name: "upstream env variable set", - upstream: "skaffold-v0.25.45", - expected: "kaniko/unset,skaffold-v0.25.45", - }, { - name: "upstream env variable not set", - expected: "kaniko/unset", - }, + }{ + { + name: "upstream env variable set", + upstream: "skaffold-v0.25.45", + expected: "kaniko/unset,skaffold-v0.25.45", + }, { + name: "upstream env variable not set", + expected: "kaniko/unset", + }, } for _, test := range tests { - t.Run(test.name, func(t *testing.T) { rt := &withUserAgent{t: &mockRoundTripper{}} if test.upstream != "" { @@ -139,11 +140,9 @@ func TestHeaderAdded(t *testing.T) { testutil.CheckErrorAndDeepEqual(t, false, err, test.expected, string(body)) }) } - } -type mockRoundTripper struct { -} +type mockRoundTripper struct{} func (m *mockRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { ua := r.UserAgent() @@ -209,7 +208,7 @@ func TestImageNameDigestFile(t *testing.T) { ImageNameDigestFile: "tmpFile", } - defer os.Remove("tmpFile") + defer filesystem.FS.Remove("tmpFile") if err := DoPush(image, &opts); err != nil { t.Fatalf("could not push image: %s", err) @@ -217,10 +216,9 @@ func TestImageNameDigestFile(t *testing.T) { want := []byte("gcr.io/foo/bar@" + digest.String() + "\nindex.docker.io/bob/image@" + digest.String() + "\n") - got, err := os.ReadFile("tmpFile") + got, err := filesystem.ReadFile("tmpFile") testutil.CheckErrorAndDeepEqual(t, false, err, want, got) - } func TestDoPushWithOpts(t *testing.T) { @@ -262,13 +260,14 @@ func TestDoPushWithOpts(t *testing.T) { Destinations: []string{}, }, expectedErr: true, - }} { + }, + } { t.Run(tc.name, func(t *testing.T) { image, err := random.Image(1024, 4) if err != nil { t.Fatalf("could not create image: %s", err) } - defer os.Remove("image.tar") + defer filesystem.FS.Remove("image.tar") err = DoPush(image, &tc.opts) if err != nil { @@ -280,7 +279,6 @@ func TestDoPushWithOpts(t *testing.T) { t.Error("expected error with opts not found") } } - }) } } @@ -302,7 +300,7 @@ func TestImageNameTagDigestFile(t *testing.T) { ImageNameTagDigestFile: "tmpFile", } - defer os.Remove("tmpFile") + defer filesystem.FS.Remove("tmpFile") if err := DoPush(image, &opts); err != nil { t.Fatalf("could not push image: %s", err) @@ -310,7 +308,7 @@ func TestImageNameTagDigestFile(t *testing.T) { want := []byte("gcr.io/foo/bar:123@" + digest.String() + "\nindex.docker.io/bob/image:latest@" + digest.String() + "\n") - got, err := os.ReadFile("tmpFile") + got, err := filesystem.ReadFile("tmpFile") testutil.CheckErrorAndDeepEqual(t, false, err, want, got) } @@ -402,7 +400,7 @@ func TestCheckPushPermissions(t *testing.T) { NoPushCache: test.noPushCache, } if test.existingConfig { - afero.WriteFile(newOsFs, util.DockerConfLocation(), []byte(""), os.FileMode(0644)) + afero.WriteFile(newOsFs, util.DockerConfLocation(), []byte(""), os.FileMode(0o644)) defer newOsFs.Remove(util.DockerConfLocation()) } CheckPushPermissions(&opts) @@ -441,7 +439,7 @@ func TestSkipPushPermission(t *testing.T) { SkipPushPermissionCheck: test.skipPushPermission, } if test.existingConfig { - afero.WriteFile(newOsFs, util.DockerConfLocation(), []byte(""), os.FileMode(0644)) + afero.WriteFile(newOsFs, util.DockerConfLocation(), []byte(""), os.FileMode(0o644)) defer newOsFs.Remove(util.DockerConfLocation()) } CheckPushPermissions(&opts) diff --git a/pkg/filesystem/filesystem.go b/pkg/filesystem/filesystem.go new file mode 100644 index 0000000000..7ad2a9e511 --- /dev/null +++ b/pkg/filesystem/filesystem.go @@ -0,0 +1,52 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package filesystem + +import ( + iofs "io/fs" + "os" + "path/filepath" + + "github.com/twpayne/go-vfs/v5" +) + +// FS is the default filesystem used by the package. +var FS vfs.FS = vfs.OSFS + +// IOFS returns the default filesystem as an io/fs.FS. +func IOFS() iofs.FS { + return FS +} + +// Set the filesystem to be used by the package. Changing the filesystem +// is not safe after the package has been used. +func SetFS(fs vfs.FS) { + FS = fs +} + +// TODO(mafredri): Replace with non-os specific functions. +func CreateTemp(dir, pattern string) (*os.File, error) { return os.CreateTemp(dir, pattern) } +func MkdirTemp(dir, pattern string) (string, error) { return os.MkdirTemp(dir, pattern) } + +func ReadFile(filename string) ([]byte, error) { return FS.ReadFile(filename) } +func ReadDir(name string) ([]iofs.DirEntry, error) { return FS.ReadDir(name) } +func MkdirAll(path string, perm iofs.FileMode) error { return vfs.MkdirAll(FS, path, perm) } +func Walk(root string, walkFn filepath.WalkFunc) error { return vfs.Walk(FS, root, walkFn) } +func WalkDir(root string, walkFn iofs.WalkDirFunc) error { return iofs.WalkDir(FS, root, walkFn) } +func WriteFile(filename string, data []byte, perm os.FileMode) error { + return FS.WriteFile(filename, data, perm) +} diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go index fb98432521..6b7db1f1ae 100644 --- a/pkg/snapshot/snapshot.go +++ b/pkg/snapshot/snapshot.go @@ -19,7 +19,6 @@ package snapshot import ( "errors" "fmt" - "os" "path/filepath" "runtime" "sort" @@ -71,7 +70,7 @@ func (s *Snapshotter) Key() (string, error) { // TakeSnapshot takes a snapshot of the specified files, avoiding directories in the ignorelist, and creates // a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed func (s *Snapshotter) TakeSnapshot(files []string, shdCheckDelete bool, forceBuildMetadata bool) (string, error) { - f, err := os.CreateTemp(config.KanikoDir, "") + f, err := filesystem.CreateTemp(config.KanikoDir, "") if err != nil { return "", err } @@ -83,7 +82,7 @@ func (s *Snapshotter) TakeSnapshot(files []string, shdCheckDelete bool, forceBui return "", nil } - filesToAdd, err := filesystem.ResolvePaths(files, s.ignorelist) + filesToAdd, err := util.ResolvePaths(files, s.ignorelist) if err != nil { return "", err } @@ -135,7 +134,7 @@ func (s *Snapshotter) TakeSnapshot(files []string, shdCheckDelete bool, forceBui // TakeSnapshotFS takes a snapshot of the filesystem, avoiding directories in the ignorelist, and creates // a tarball of the changed files. func (s *Snapshotter) TakeSnapshotFS() (string, error) { - f, err := os.CreateTemp(s.getSnashotPathPrefix(), "") + f, err := filesystem.CreateTemp(s.getSnashotPathPrefix(), "") if err != nil { return "", err } @@ -174,12 +173,16 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) { // which can lag if sync is not called. Unfortunately there can still be lag if too much data needs // to be flushed or the disk does its own caching/buffering. if runtime.GOOS == "linux" { - dir, err := os.Open(s.directory) + dir, err := filesystem.FS.Open(s.directory) if err != nil { return nil, nil, err } defer dir.Close() - _, _, errno := syscall.Syscall(unix.SYS_SYNCFS, dir.Fd(), 0, 0) + dirfd, ok := dir.(interface{ Fd() uintptr }) + if !ok { + return nil, nil, errors.New("filesystem open did not return a directory with a file descriptor") + } + _, _, errno := syscall.Syscall(unix.SYS_SYNCFS, dirfd.Fd(), 0, 0) if errno != 0 { return nil, nil, errno } @@ -196,7 +199,7 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) { timer := timing.Start("Resolving Paths") filesToAdd := []string{} - resolvedFiles, err := filesystem.ResolvePaths(changedPaths, s.ignorelist) + resolvedFiles, err := util.ResolvePaths(changedPaths, s.ignorelist) if err != nil { return nil, nil, err } @@ -234,7 +237,6 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) { // removeObsoleteWhiteouts filters deleted files according to their parents delete status. func removeObsoleteWhiteouts(deletedFiles map[string]struct{}) (filesToWhiteout []string) { - for path := range deletedFiles { // Only add the whiteout if the directory for the file still exists. dir := filepath.Dir(path) @@ -289,7 +291,7 @@ func writeToTar(t util.Tar, files, whiteouts []string) error { // Returns true if a parent of the given path has been replaced with anything other than a directory func parentPathIncludesNonDirectory(path string) (bool, error) { for _, parentPath := range util.ParentDirectories(path) { - lstat, err := os.Lstat(parentPath) + lstat, err := filesystem.FS.Lstat(parentPath) if err != nil { return false, err } @@ -326,7 +328,7 @@ func filesWithLinks(path string) ([]string, error) { if !filepath.IsAbs(link) { link = filepath.Join(filepath.Dir(path), link) } - if _, err := os.Stat(link); err != nil { + if _, err := filesystem.FS.Stat(link); err != nil { return []string{path}, nil //nolint:nilerr } return []string{path, link}, nil diff --git a/pkg/snapshot/snapshot_test.go b/pkg/snapshot/snapshot_test.go index 30b882d1b3..09e9a9d26b 100644 --- a/pkg/snapshot/snapshot_test.go +++ b/pkg/snapshot/snapshot_test.go @@ -19,13 +19,13 @@ package snapshot import ( "archive/tar" "io" - "os" "path/filepath" "sort" "strings" "testing" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/util" "github.com/GoogleContainerTools/kaniko/testutil" "github.com/pkg/errors" @@ -52,7 +52,7 @@ func TestSnapshotFSFileChange(t *testing.T) { t.Fatalf("Error taking snapshot of fs: %s", err) } - f, err := os.Open(tarPath) + f, err := filesystem.FS.Open(tarPath) if err != nil { t.Fatal(err) } @@ -137,7 +137,7 @@ func TestSnapshotFSChangePermissions(t *testing.T) { // Change permissions on a file batPath := filepath.Join(testDir, "bar/bat") batPathWithoutLeadingSlash := filepath.Join(testDirWithoutLeadingSlash, "bar/bat") - if err := os.Chmod(batPath, 0600); err != nil { + if err := filesystem.FS.Chmod(batPath, 0o600); err != nil { t.Fatalf("Error changing permissions on %s: %v", batPath, err) } // Take another snapshot @@ -145,7 +145,7 @@ func TestSnapshotFSChangePermissions(t *testing.T) { if err != nil { t.Fatalf("Error taking snapshot of fs: %s", err) } - f, err := os.Open(tarPath) + f, err := filesystem.FS.Open(tarPath) if err != nil { t.Fatal(err) } @@ -197,12 +197,12 @@ func TestSnapshotFSReplaceDirWithLink(t *testing.T) { // replace non-empty directory "bar" with link to file "foo" bar := filepath.Join(testDir, "bar") - err = os.RemoveAll(bar) + err = filesystem.FS.RemoveAll(bar) if err != nil { t.Fatal(err) } foo := filepath.Join(testDir, "foo") - err = os.Symlink(foo, bar) + err = filesystem.FS.Symlink(foo, bar) if err != nil { t.Fatal(err) } @@ -254,7 +254,7 @@ func TestSnapshotFiles(t *testing.T) { if err != nil { t.Fatal(err) } - defer os.Remove(tarPath) + defer filesystem.FS.Remove(tarPath) expectedFiles := []string{ filepath.Join(testDirWithoutLeadingSlash, "foo"), @@ -287,7 +287,7 @@ func TestEmptySnapshotFS(t *testing.T) { t.Fatalf("Error taking snapshot of fs: %s", err) } - f, err := os.Open(tarPath) + f, err := filesystem.FS.Open(tarPath) if err != nil { t.Fatal(err) } @@ -299,7 +299,6 @@ func TestEmptySnapshotFS(t *testing.T) { } func TestFileWithLinks(t *testing.T) { - link := "baz/link" tcs := []struct { name string @@ -386,7 +385,6 @@ func TestSnapshotPreservesFileOrder(t *testing.T) { // Take a snapshot tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, false, false) - if err != nil { t.Fatalf("Error taking snapshot of fs: %s", err) } @@ -474,7 +472,7 @@ func TestSnapshotIncludesParentDirBeforeWhiteoutFile(t *testing.T) { // Delete files filesToDelete := []string{"kaniko/file", "bar"} for _, fn := range filesToDelete { - err = os.RemoveAll(filepath.Join(testDir, fn)) + err = filesystem.FS.RemoveAll(filepath.Join(testDir, fn)) if err != nil { t.Fatalf("Error deleting file: %s", err) } @@ -555,7 +553,7 @@ func TestSnapshotPreservesWhiteoutOrder(t *testing.T) { // Delete all files for p := range newFiles { - err := os.Remove(filepath.Join(testDir, p)) + err := filesystem.FS.Remove(filepath.Join(testDir, p)) if err != nil { t.Fatalf("Error deleting file: %s", err) } @@ -597,7 +595,7 @@ func TestSnapshotOmitsUnameGname(t *testing.T) { t.Fatal(err) } - f, err := os.Open(tarPath) + f, err := filesystem.FS.Open(tarPath) if err != nil { t.Fatal(err) } @@ -614,11 +612,10 @@ func TestSnapshotOmitsUnameGname(t *testing.T) { t.Fatalf("Expected Uname/Gname for %s to be empty: Uname = '%s', Gname = '%s'", hdr.Name, hdr.Uname, hdr.Gname) } } - } func setupSymlink(dir string, link string, target string) error { - return os.Symlink(target, filepath.Join(dir, link)) + return filesystem.FS.Symlink(target, filepath.Join(dir, link)) } func sortAndCompareFilepaths(t *testing.T, testDir string, expected []string, actual []string) { @@ -673,7 +670,7 @@ func setUpTest(t *testing.T) (string, *Snapshotter, func(), error) { } func listFilesInTar(path string) ([]string, error) { - f, err := os.Open(path) + f, err := filesystem.FS.Open(path) if err != nil { return nil, err } diff --git a/pkg/util/command_util.go b/pkg/util/command_util.go index 8c4af2272c..672429093b 100644 --- a/pkg/util/command_util.go +++ b/pkg/util/command_util.go @@ -34,6 +34,7 @@ import ( "github.com/sirupsen/logrus" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) // for testing @@ -167,7 +168,7 @@ func matchSources(srcs, files []string) ([]string, error) { func IsDestDir(path string) bool { // try to stat the path - fileInfo, err := os.Stat(path) + fileInfo, err := filesystem.FS.Stat(path) if err != nil { // fall back to string-based determination return strings.HasSuffix(path, pathSeparator) || path == "." @@ -259,7 +260,7 @@ func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, resolvedSources []stri return nil } path := filepath.Join(fileContext.Root, resolvedSources[0]) - fi, err := os.Lstat(path) + fi, err := filesystem.FS.Lstat(path) if err != nil { return errors.Wrap(err, fmt.Sprintf("failed to get fileinfo for %v", path)) } diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index a27d531bb4..ead0f88d50 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -32,6 +32,7 @@ import ( "time" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/timing" "github.com/docker/docker/pkg/archive" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -88,10 +89,15 @@ var ignorelist = append([]IgnoreListEntry{}, defaultIgnoreList...) var volumes = []string{} // skipKanikoDir opts to skip the '/kaniko' dir for otiai10.copy which should be ignored in root -var skipKanikoDir = otiai10Cpy.Options{ - Skip: func(info os.FileInfo, src, dest string) (bool, error) { - return strings.HasSuffix(src, "/kaniko"), nil - }, +var skipKanikoDir = func() otiai10Cpy.Options { + return otiai10Cpy.Options{ + Skip: func(info os.FileInfo, src, dest string) (bool, error) { + return strings.HasSuffix(src, "/kaniko"), nil + }, + // TODO(mafredri): Library only uses opt.FS partially, Mkdir breaks it: + // https://github.com/otiai10/copy/issues/153 + // FS: filesystem.IOFS(), + } } type FileContext struct { @@ -269,7 +275,7 @@ func GetFSFromLayers(root string, layers []v1.Layer, opts ...FSOpt) ([]string, e continue } - if err := os.RemoveAll(path); err != nil { + if err := filesystem.FS.RemoveAll(path); err != nil { return nil, errors.Wrapf(err, "removing whiteout %s", hdr.Name) } @@ -321,7 +327,7 @@ func (r *printAfterReader) Read(p []byte) (n int, err error) { // DeleteFilesystem deletes the extracted image file system func DeleteFilesystem() error { logrus.Info("Deleting filesystem...") - return filepath.Walk(config.RootDir, func(path string, info os.FileInfo, err error) error { + return filesystem.Walk(config.RootDir, func(path string, info os.FileInfo, err error) error { if err != nil { // ignore errors when deleting. return nil //nolint:nilerr @@ -345,13 +351,13 @@ func DeleteFilesystem() error { if path == config.RootDir { return nil } - return os.RemoveAll(path) + return filesystem.FS.RemoveAll(path) }) } // isExists returns true if path exists func isExist(path string) bool { - if _, err := os.Stat(path); err == nil { + if _, err := filesystem.FS.Stat(path); err == nil { return true } return false @@ -411,11 +417,11 @@ func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader) // It's possible a file is in the tar before its directory, // or a file was copied over a directory prior to now - fi, err := os.Stat(dir) + fi, err := filesystem.FS.Stat(dir) if os.IsNotExist(err) || !fi.IsDir() { logrus.Debugf("Base %s for file %s does not exist. Creating.", base, path) - if err := os.MkdirAll(dir, 0o755); err != nil { + if err := filesystem.MkdirAll(dir, 0o755); err != nil { return err } } @@ -423,12 +429,12 @@ func ExtractFile(dest string, hdr *tar.Header, cleanedName string, tr io.Reader) // Check if something already exists at path (symlinks etc.) // If so, delete it if FilepathExists(path) { - if err := os.RemoveAll(path); err != nil { + if err := filesystem.FS.RemoveAll(path); err != nil { return errors.Wrapf(err, "error removing %s to make way for new file.", path) } } - currFile, err := os.Create(path) + currFile, err := filesystem.FS.Create(path) if err != nil { return err } @@ -467,13 +473,13 @@ 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, 0o755); err != nil { + if err := filesystem.MkdirAll(dir, 0o755); err != nil { return err } // Check if something already exists at path // If so, delete it if FilepathExists(path) { - if err := os.RemoveAll(path); err != nil { + if err := filesystem.FS.RemoveAll(path); err != nil { return errors.Wrapf(err, "error removing %s to make way for new link", hdr.Name) } } @@ -485,17 +491,17 @@ 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, 0o755); err != nil { + if err := filesystem.MkdirAll(dir, 0o755); err != nil { return err } // Check if something already exists at path // If so, delete it if FilepathExists(path) { - if err := os.RemoveAll(path); err != nil { + if err := filesystem.FS.RemoveAll(path); err != nil { return errors.Wrapf(err, "error removing %s to make way for new symlink", hdr.Name) } } - if err := os.Symlink(hdr.Linkname, path); err != nil { + if err := filesystem.FS.Symlink(hdr.Linkname, path); err != nil { return err } } @@ -555,7 +561,7 @@ func checkIgnoreListRoot(root string) bool { // From: https://www.kernel.org/doc/Documentation/filesystems/proc.txt func DetectFilesystemIgnoreList(path string) error { logrus.Trace("Detecting filesystem ignore list") - f, err := os.Open(path) + f, err := filesystem.FS.Open(path) if err != nil { return err } @@ -597,7 +603,7 @@ func RelativeFiles(fp string, root string) ([]string, error) { fullPath := filepath.Join(root, fp) cleanedRoot := filepath.Clean(root) logrus.Debugf("Getting files and contents at root %s for %s", root, fullPath) - err := filepath.Walk(fullPath, func(path string, info os.FileInfo, err error) error { + err := filesystem.Walk(fullPath, func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -653,14 +659,14 @@ func ParentDirectoriesWithoutLeadingSlash(path string) []string { // FilepathExists returns true if the path exists func FilepathExists(path string) bool { - _, err := os.Lstat(path) + _, err := filesystem.FS.Lstat(path) return !os.IsNotExist(err) } // resetFileOwnershipIfNotMatching function changes ownership of the file at path to newUID and newGID. // If the ownership already matches, chown is not executed. func resetFileOwnershipIfNotMatching(path string, newUID, newGID uint32) error { - fsInfo, err := os.Lstat(path) + fsInfo, err := filesystem.FS.Lstat(path) if err != nil { return errors.Wrap(err, "getting stat of present file") } @@ -669,7 +675,7 @@ func resetFileOwnershipIfNotMatching(path string, newUID, newGID uint32) error { return fmt.Errorf("can't convert fs.FileInfo of %v to linux syscall.Stat_t", path) } if stat.Uid != newUID && stat.Gid != newGID { - err = os.Chown(path, int(newUID), int(newGID)) + err = filesystem.FS.Chown(path, int(newUID), int(newGID)) if err != nil { return errors.Wrap(err, "reseting file ownership to root") } @@ -694,18 +700,18 @@ func CreateFile(path string, reader io.Reader, perm os.FileMode, uid uint32, gid } var renamed string - dest, err := os.Create(path) + dest, err := filesystem.FS.Create(path) if err != nil { if !errors.Is(err, syscall.ETXTBSY) { return errors.Wrap(err, "creating file") } // If the file is busy, just write to a temp file and // move to dest. - dest, err = os.CreateTemp(os.TempDir(), "") + dest, err = filesystem.CreateTemp(os.TempDir(), "") if err != nil { return errors.Wrap(err, "create temp file") } - defer os.Remove(dest.Name()) + defer filesystem.FS.Remove(dest.Name()) renamed = dest.Name() } defer dest.Close() @@ -713,7 +719,7 @@ func CreateFile(path string, reader io.Reader, perm os.FileMode, uid uint32, gid return errors.Wrap(err, "copying file") } if renamed != "" { - if err := os.Rename(renamed, path); err != nil { + if err := filesystem.FS.Rename(renamed, path); err != nil { return errors.Wrap(err, "rename temp file") } } @@ -757,7 +763,7 @@ func DownloadFileToDest(rawurl, dest string, uid, gid int64, chmod fs.FileMode) mTime = parsedMTime } } - return os.Chtimes(dest, mTime, mTime) + return filesystem.FS.Chtimes(dest, mTime, mTime) } // DetermineTargetFileOwnership returns the user provided uid/gid combination. @@ -786,7 +792,7 @@ func CopyDir(src, dest string, context FileContext, uid, gid int64, chmod fs.Fil logrus.Debugf("%s found in .dockerignore, ignoring", src) continue } - fi, err := os.Lstat(fullPath) + fi, err := filesystem.FS.Lstat(fullPath) if err != nil { return nil, errors.Wrap(err, "copying dir") } @@ -830,18 +836,18 @@ func CopySymlink(src, dest string, context FileContext) (bool, error) { return true, nil } if FilepathExists(dest) { - if err := os.RemoveAll(dest); err != nil { + if err := filesystem.FS.RemoveAll(dest); err != nil { return false, err } } if err := createParentDirectory(dest, DoNotChangeUID, DoNotChangeGID); err != nil { return false, err } - link, err := os.Readlink(src) + link, err := filesystem.FS.Readlink(src) if err != nil { logrus.Debugf("Could not read link for %s", src) } - return false, os.Symlink(link, dest) + return false, filesystem.FS.Symlink(link, dest) } // CopyFile copies the file at src to dest @@ -856,12 +862,12 @@ func CopyFile(src, dest string, context FileContext, uid, gid int64, chmod fs.Fi // See iusse #904 for an example. return false, nil } - fi, err := os.Stat(src) + fi, err := filesystem.FS.Stat(src) if err != nil { return false, err } logrus.Debugf("Copying file %s to %s", src, dest) - srcFile, err := os.Open(src) + srcFile, err := filesystem.FS.Open(src) if err != nil { return false, err } @@ -895,7 +901,7 @@ func getExcludedFiles(dockerfilePath, buildcontext string) ([]string, error) { return nil, nil } logrus.Infof("Using dockerignore file: %v", path) - contents, err := os.ReadFile(path) + contents, err := filesystem.ReadFile(path) if err != nil { return nil, errors.Wrap(err, "parsing .dockerignore") } @@ -955,10 +961,10 @@ func Volumes() []string { func MkdirAllWithPermissions(path string, mode os.FileMode, uid, gid int64) error { // Check if a file already exists on the path, if yes then delete it - info, err := os.Stat(path) + info, err := filesystem.FS.Stat(path) if err == nil && !info.IsDir() { logrus.Tracef("Removing file because it needs to be a directory %s", path) - if err := os.Remove(path); err != nil { + if err := filesystem.FS.Remove(path); err != nil { return errors.Wrapf(err, "error removing %s to make way for new directory.", path) } } @@ -966,7 +972,7 @@ func MkdirAllWithPermissions(path string, mode os.FileMode, uid, gid int64) erro return errors.Wrapf(err, "error calling stat on %s.", path) } - if err := os.MkdirAll(path, mode); err != nil { + if err := filesystem.MkdirAll(path, mode); err != nil { return err } if uid > math.MaxUint32 || gid > math.MaxUint32 { @@ -978,21 +984,21 @@ func MkdirAllWithPermissions(path string, mode os.FileMode, uid, gid int64) erro ), ) } - if err := os.Chown(path, int(uid), int(gid)); err != nil { + if err := filesystem.FS.Chown(path, int(uid), int(gid)); err != nil { return err } // In some cases, MkdirAll doesn't change the permissions, so run Chmod // Must chmod after chown because chown resets the file mode. - return os.Chmod(path, mode) + return filesystem.FS.Chmod(path, mode) } func setFilePermissions(path string, mode os.FileMode, uid, gid int) error { - if err := os.Chown(path, uid, gid); err != nil { + if err := filesystem.FS.Chown(path, uid, gid); err != nil { return err } // manually set permissions on file, since the default umask (022) will interfere // Must chmod after chown because chown resets the file mode. - return os.Chmod(path, mode) + return filesystem.FS.Chmod(path, mode) } func setFileTimes(path string, aTime, mTime time.Time) error { @@ -1011,7 +1017,7 @@ func setFileTimes(path string, aTime, mTime time.Time) error { // We set AccessTime because its a required arg but we only care about // ModTime. The file will get accessed again so AccessTime will change. - if err := os.Chtimes(path, aTime, mTime); err != nil { + if err := filesystem.FS.Chtimes(path, aTime, mTime); err != nil { return errors.Wrapf( err, "couldn't modify times: atime %v mtime %v", @@ -1027,13 +1033,17 @@ func setFileTimes(path string, aTime, mTime time.Time) error { // Make directory if directory does not exist func CreateTargetTarfile(tarpath string) (*os.File, error) { baseDir := filepath.Dir(tarpath) - if _, err := os.Lstat(baseDir); os.IsNotExist(err) { + if _, err := filesystem.FS.Lstat(baseDir); os.IsNotExist(err) { logrus.Debugf("BaseDir %s for file %s does not exist. Creating.", baseDir, tarpath) - if err := os.MkdirAll(baseDir, 0o755); err != nil { + if err := filesystem.MkdirAll(baseDir, 0o755); err != nil { return nil, err } } - return os.Create(tarpath) + f, err := filesystem.FS.Create(tarpath) + if err != nil { + return nil, err + } + return f, nil } // Returns true if a file is a symlink @@ -1047,7 +1057,7 @@ func GetSymLink(path string) (string, error) { if err := getSymlink(path); err != nil { return "", err } - return os.Readlink(path) + return filesystem.FS.Readlink(path) } func EvalSymLink(path string) (string, error) { @@ -1058,7 +1068,7 @@ func EvalSymLink(path string) (string, error) { } func getSymlink(path string) error { - fi, err := os.Lstat(path) + fi, err := filesystem.FS.Lstat(path) if err != nil { return err } @@ -1074,27 +1084,27 @@ func getSymlink(path string) error { func CopyFileOrSymlink(src string, destDir string, root string) error { destFile := filepath.Join(destDir, src) src = filepath.Join(root, src) - fi, err := os.Lstat(src) + fi, err := filesystem.FS.Lstat(src) if err != nil { return errors.Wrap(err, "getting file info") } if IsSymlink(fi) { - link, err := os.Readlink(src) + link, err := filesystem.FS.Readlink(src) if err != nil { return errors.Wrap(err, "copying file or symlink") } if err := createParentDirectory(destFile, DoNotChangeUID, DoNotChangeGID); err != nil { return err } - return os.Symlink(link, destFile) + return filesystem.FS.Symlink(link, destFile) } - if err := otiai10Cpy.Copy(src, destFile, skipKanikoDir); err != nil { + if err := otiai10Cpy.Copy(src, destFile, skipKanikoDir()); err != nil { return errors.Wrap(err, "copying file") } if err := CopyOwnership(src, destDir, root); err != nil { return errors.Wrap(err, "copying ownership") } - if err := os.Chmod(destFile, fi.Mode()); err != nil { + if err := filesystem.FS.Chmod(destFile, fi.Mode()); err != nil { return errors.Wrap(err, "copying file mode") } return nil @@ -1102,7 +1112,7 @@ func CopyFileOrSymlink(src string, destDir string, root string) error { // CopyOwnership copies the file or directory ownership recursively at src to dest func CopyOwnership(src string, destDir string, root string) error { - return filepath.Walk(src, func(path string, info os.FileInfo, err error) error { + return filesystem.Walk(src, func(path string, info os.FileInfo, err error) error { if err != nil { return err } @@ -1138,18 +1148,18 @@ func CopyOwnership(src string, destDir string, root string) error { return nil } - info, err = os.Stat(path) + info, err = filesystem.FS.Stat(path) if err != nil { return errors.Wrap(err, "reading ownership") } stat := info.Sys().(*syscall.Stat_t) - return os.Chown(destPath, int(stat.Uid), int(stat.Gid)) + return filesystem.FS.Chown(destPath, int(stat.Uid), int(stat.Gid)) }) } func createParentDirectory(path string, uid int, gid int) error { baseDir := filepath.Dir(path) - if info, err := os.Lstat(baseDir); os.IsNotExist(err) { + if info, err := filesystem.FS.Lstat(baseDir); os.IsNotExist(err) { logrus.Tracef("BaseDir %s for file %s does not exist. Creating.", baseDir, path) dir := baseDir @@ -1165,11 +1175,11 @@ func createParentDirectory(path string, uid int, gid int) error { for i := len(dirs) - 1; i >= 0; i-- { dir := dirs[i] - if _, err := os.Lstat(dir); os.IsNotExist(err) { - os.Mkdir(dir, 0o755) + if _, err := filesystem.FS.Lstat(dir); os.IsNotExist(err) { + filesystem.FS.Mkdir(dir, 0o755) if uid != DoNotChangeUID { if gid != DoNotChangeGID { - os.Chown(dir, uid, gid) + filesystem.FS.Chown(dir, uid, gid) } else { return errors.New(fmt.Sprintf("UID=%d but GID=-1, i.e. it is not set for %s", uid, dir)) } @@ -1298,7 +1308,7 @@ func GetFSInfoMap(dir string, existing map[string]os.FileInfo) (map[string]os.Fi } return nil } - if fi, err := os.Lstat(path); err == nil { + if fi, err := filesystem.FS.Lstat(path); err == nil { if fiPrevious, ok := existing[path]; ok { // check if file changed if !isSame(fiPrevious, fi) { diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 3e34cd49c9..df81b4ef4e 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -32,6 +32,7 @@ import ( "github.com/GoogleContainerTools/kaniko/pkg/config" "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/pkg/mocks/go-containerregistry/mockv1" "github.com/GoogleContainerTools/kaniko/testutil" "github.com/golang/mock/gomock" @@ -49,10 +50,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), 0o750); err != nil { + if err := filesystem.MkdirAll(filepath.Dir(path), 0o750); err != nil { t.Fatalf("Error creating tempdir: %s", err) } - if err := os.WriteFile(path, []byte(fileContents), 0o644); err != nil { + if err := filesystem.WriteFile(path, []byte(fileContents), 0o644); err != nil { t.Fatalf("Error writing file contents to %s: %s", path, err) } @@ -483,7 +484,7 @@ type checker func(root string, t *testing.T) func fileExists(p string) checker { return func(root string, t *testing.T) { - _, err := os.Stat(filepath.Join(root, p)) + _, err := filesystem.FS.Stat(filepath.Join(root, p)) if err != nil { t.Fatalf("File %s does not exist", filepath.Join(root, p)) } @@ -492,7 +493,7 @@ func fileExists(p string) checker { func fileMatches(p string, c []byte) checker { return func(root string, t *testing.T) { - actual, err := os.ReadFile(filepath.Join(root, p)) + actual, err := filesystem.ReadFile(filepath.Join(root, p)) if err != nil { t.Fatalf("error reading file: %s", p) } @@ -504,7 +505,7 @@ func fileMatches(p string, c []byte) checker { func timesMatch(p string, fTime time.Time) checker { return func(root string, t *testing.T) { - fi, err := os.Stat(filepath.Join(root, p)) + fi, err := filesystem.FS.Stat(filepath.Join(root, p)) if err != nil { t.Fatalf("error statting file %s", p) } @@ -517,7 +518,7 @@ func timesMatch(p string, fTime time.Time) checker { func permissionsMatch(p string, perms os.FileMode) checker { return func(root string, t *testing.T) { - fi, err := os.Stat(filepath.Join(root, p)) + fi, err := filesystem.FS.Stat(filepath.Join(root, p)) if err != nil { t.Fatalf("error statting file %s", p) } @@ -530,7 +531,7 @@ func permissionsMatch(p string, perms os.FileMode) checker { func linkPointsTo(src, dst string) checker { return func(root string, t *testing.T) { link := filepath.Join(root, src) - got, err := os.Readlink(link) + got, err := filesystem.FS.Readlink(link) if err != nil { t.Fatalf("error reading link %s: %s", link, err) } @@ -542,11 +543,11 @@ func linkPointsTo(src, dst string) checker { func filesAreHardlinks(first, second string) checker { return func(root string, t *testing.T) { - fi1, err := os.Stat(filepath.Join(root, first)) + fi1, err := filesystem.FS.Stat(filepath.Join(root, first)) if err != nil { t.Fatalf("error getting file %s", first) } - fi2, err := os.Stat(filepath.Join(root, second)) + fi2, err := filesystem.FS.Stat(filepath.Join(root, second)) if err != nil { t.Fatalf("error getting file %s", second) } @@ -604,7 +605,7 @@ func createUncompressedTar(fileContents map[string]string, tarFileName, testDir if err := testutil.SetupFiles(testDir, fileContents); err != nil { return err } - tarFile, err := os.Create(filepath.Join(testDir, tarFileName)) + tarFile, err := filesystem.FS.Create(filepath.Join(testDir, tarFileName)) if err != nil { return err } @@ -656,7 +657,7 @@ func Test_UnTar(t *testing.T) { if err := createUncompressedTar(tc.setupTarContents, tc.tarFileName, testDir); err != nil { t.Fatal(err) } - file, err := os.Open(filepath.Join(testDir, tc.tarFileName)) + file, err := filesystem.FS.Open(filepath.Join(testDir, tc.tarFileName)) if err != nil { t.Fatal(err) } @@ -806,7 +807,7 @@ func TestExtractFile(t *testing.T) { } else { r = t.TempDir() } - defer os.RemoveAll(r) + defer filesystem.FS.RemoveAll(r) for _, hdr := range tc.hdrs { if err := ExtractFile(r, hdr, filepath.Clean(hdr.Name), bytes.NewReader(tc.contents)); err != nil { @@ -839,7 +840,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, 0o644) + return filesystem.WriteFile(filepath.Join(r, "overwrite_me"), nil, 0o644) }, }} @@ -848,9 +849,9 @@ func TestCopySymlink(t *testing.T) { tc := tc t.Parallel() r := t.TempDir() - os.MkdirAll(filepath.Join(r, filepath.Dir(tc.linkTarget)), 0o777) + filesystem.MkdirAll(filepath.Join(r, filepath.Dir(tc.linkTarget)), 0o777) tc.linkTarget = filepath.Join(r, tc.linkTarget) - os.WriteFile(tc.linkTarget, nil, 0o644) + filesystem.WriteFile(tc.linkTarget, nil, 0o644) if tc.beforeLink != nil { if err := tc.beforeLink(r); err != nil { @@ -862,13 +863,13 @@ func TestCopySymlink(t *testing.T) { if tc.dest != "" { dest = filepath.Join(r, tc.dest) } - if err := os.Symlink(tc.linkTarget, link); err != nil { + if err := filesystem.FS.Symlink(tc.linkTarget, link); err != nil { t.Fatal(err) } if _, err := CopySymlink(link, dest, FileContext{}); err != nil { t.Fatal(err) } - if _, err := os.Lstat(dest); err != nil { + if _, err := filesystem.FS.Lstat(dest); err != nil { t.Fatalf("error reading link %s: %s", link, err) } }) @@ -979,7 +980,7 @@ func Test_CopyFile_skips_self(t *testing.T) { tempFile := filepath.Join(tempDir, "foo") expected := "bar" - if err := os.WriteFile( + if err := filesystem.WriteFile( tempFile, []byte(expected), 0o755, @@ -997,7 +998,7 @@ func Test_CopyFile_skips_self(t *testing.T) { } // Ensure file has expected contents - actualData, err := os.ReadFile(tempFile) + actualData, err := filesystem.ReadFile(tempFile) if err != nil { t.Fatal(err) } @@ -1020,7 +1021,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, 0o644); err != nil { + if err := filesystem.WriteFile(filepath.Join(root, "foobar"), d1, 0o644); err != nil { t.Fatal(err) } @@ -1106,7 +1107,7 @@ func Test_GetFSFromLayers_with_whiteouts_include_whiteout_enabled(t *testing.T) expectErr, ) // Make sure whiteout files are removed form the root. - _, err = os.Lstat(filepath.Join(root, "foobar")) + _, err = filesystem.FS.Lstat(filepath.Join(root, "foobar")) if err == nil || !os.IsNotExist(err) { t.Errorf("expected whiteout foobar file to be deleted. However found it.") } @@ -1131,7 +1132,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, 0o644); err != nil { + if err := filesystem.WriteFile(filepath.Join(root, "foobar"), d1, 0o644); err != nil { t.Fatal(err) } @@ -1221,7 +1222,7 @@ func Test_GetFSFromLayers_with_whiteouts_include_whiteout_disabled(t *testing.T) expectErr, ) // Make sure whiteout files are removed form the root. - _, err = os.Lstat(filepath.Join(root, "foobar")) + _, err = filesystem.FS.Lstat(filepath.Join(root, "foobar")) if err == nil || !os.IsNotExist(err) { t.Errorf("expected whiteout foobar file to be deleted. However found it.") } @@ -1236,7 +1237,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"), 0o775); err != nil { + if err := filesystem.FS.Mkdir(filepath.Join(root, "testdir"), 0o775); err != nil { t.Fatal(err) } @@ -1313,7 +1314,7 @@ func Test_GetFSFromLayers_ignorelist(t *testing.T) { ) // Make sure whiteout files are removed form the root. - _, err = os.Lstat(filepath.Join(root, "testdir")) + _, err = filesystem.FS.Lstat(filepath.Join(root, "testdir")) if err == nil || !os.IsNotExist(err) { t.Errorf("expected testdir to be deleted. However found it.") } @@ -1326,7 +1327,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"), 0o775); err != nil { + if err := filesystem.FS.Mkdir(filepath.Join(root, "testdir"), 0o775); err != nil { t.Fatal(err) } @@ -1369,7 +1370,7 @@ func Test_GetFSFromLayers_ignorelist(t *testing.T) { ) // Make sure testdir still exists. - _, err = os.Lstat(filepath.Join(root, "testdir")) + _, err = filesystem.FS.Lstat(filepath.Join(root, "testdir")) if err != nil { t.Errorf("expected testdir to exist, but could not Lstat it: %v", err) } @@ -1470,7 +1471,7 @@ func TestInitIgnoreList(t *testing.T) { mountInfo := `36 35 98:0 /kaniko /test/kaniko rw,noatime master:1 - ext3 /dev/root rw,errors=continue 36 35 98:0 /proc /test/proc rw,noatime master:1 - ext3 /dev/root rw,errors=continue ` - mFile, err := os.CreateTemp("", "mountinfo") + mFile, err := filesystem.CreateTemp("", "mountinfo") if err != nil { t.Fatal(err) } @@ -1532,7 +1533,7 @@ func Test_setFileTimes(t *testing.T) { p := filepath.Join(testDir, "foo.txt") - if err := os.WriteFile(p, []byte("meow"), 0o777); err != nil { + if err := filesystem.WriteFile(p, []byte("meow"), 0o777); err != nil { t.Fatal(err) } diff --git a/pkg/util/gcr_util.go b/pkg/util/gcr_util.go index ac7e946858..3d48a5b4d8 100644 --- a/pkg/util/gcr_util.go +++ b/pkg/util/gcr_util.go @@ -19,6 +19,8 @@ package util import ( "os" "path/filepath" + + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) // DockerConfLocation returns the file system location of the Docker @@ -28,7 +30,7 @@ import ( func DockerConfLocation() string { configFile := "config.json" if dockerConfig := os.Getenv("DOCKER_CONFIG"); dockerConfig != "" { - file, err := os.Stat(dockerConfig) + file, err := filesystem.FS.Stat(dockerConfig) if err == nil { if file.IsDir() { return filepath.Join(dockerConfig, configFile) diff --git a/pkg/util/gcr_util_test.go b/pkg/util/gcr_util_test.go index e7144688c1..6ec20c2c71 100644 --- a/pkg/util/gcr_util_test.go +++ b/pkg/util/gcr_util_test.go @@ -20,6 +20,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) const ( @@ -33,7 +35,7 @@ func TestDockerConfLocationWithInvalidFileLocation(t *testing.T) { t.Fatalf("Failed to unset DOCKER_CONFIG: %v", err) } tmpDir := t.TempDir() - random := "fdgdsfrdfgdf-fdfsf-24dsgfd" //replace with a really random string + random := "fdgdsfrdfgdf-fdfsf-24dsgfd" // replace with a really random string file := filepath.Join(tmpDir, random) // an random file name, shouldn't exist if err := os.Setenv(DockerConfigEnvKey, file); err != nil { t.Fatalf("Failed to unset DOCKER_CONFIG: %v", err) @@ -61,7 +63,7 @@ func TestDockerConfLocation(t *testing.T) { tmpDir := t.TempDir() dir := filepath.Join(tmpDir, "/kaniko/.docker") - os.MkdirAll(dir, os.ModePerm) + filesystem.MkdirAll(dir, os.ModePerm) if err := os.Setenv(DockerConfigEnvKey, dir); err != nil { t.Fatalf("Failed to set DOCKER_CONFIG: %v", err) } @@ -100,11 +102,11 @@ func TestDockerConfLocationWithFileLocation(t *testing.T) { if err := os.Unsetenv(DockerConfigEnvKey); err != nil { t.Fatalf("Failed to unset DOCKER_CONFIG: %v", err) } - file, err := os.CreateTemp("", "docker.conf") + file, err := filesystem.CreateTemp("", "docker.conf") if err != nil { t.Fatalf("could not create temp file: %s", err) } - defer os.Remove(file.Name()) + defer filesystem.FS.Remove(file.Name()) if err := os.Setenv(DockerConfigEnvKey, file.Name()); err != nil { t.Fatalf("Failed to unset DOCKER_CONFIG: %v", err) } diff --git a/pkg/util/groupids_fallback.go b/pkg/util/groupids_fallback.go index e336d72e9f..cb0621c14d 100644 --- a/pkg/util/groupids_fallback.go +++ b/pkg/util/groupids_fallback.go @@ -24,11 +24,11 @@ import ( "bufio" "bytes" "io" - "os" "os/user" "strconv" "strings" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -50,7 +50,7 @@ func groupIDs(u *user.User) ([]string, error) { return []string{}, nil } - f, err := os.Open(groupFile) + f, err := filesystem.FS.Open(groupFile) if err != nil { return nil, errors.Wrap(err, "open") } diff --git a/pkg/util/proc/proc.go b/pkg/util/proc/proc.go index 9592e81b3e..5dffb8907d 100644 --- a/pkg/util/proc/proc.go +++ b/pkg/util/proc/proc.go @@ -23,6 +23,8 @@ import ( "os" "regexp" "strings" + + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) // ContainerRuntime is the type for the various container runtime strings. @@ -57,23 +59,21 @@ const ( RuntimeNotFound ContainerRuntime = "not-found" ) -var ( - // ContainerRuntimes contains all the container runtimes. - ContainerRuntimes = []ContainerRuntime{ - RuntimeDocker, - RuntimeRkt, - RuntimeNspawn, - RuntimeLXC, - RuntimeLXCLibvirt, - RuntimeOpenVZ, - RuntimeKubernetes, - RuntimeGarden, - RuntimePodman, - RuntimeGVisor, - RuntimeFirejail, - RuntimeWSL, - } -) +// ContainerRuntimes contains all the container runtimes. +var ContainerRuntimes = []ContainerRuntime{ + RuntimeDocker, + RuntimeRkt, + RuntimeNspawn, + RuntimeLXC, + RuntimeLXCLibvirt, + RuntimeOpenVZ, + RuntimeKubernetes, + RuntimeGarden, + RuntimePodman, + RuntimeGVisor, + RuntimeFirejail, + RuntimeWSL, +} // GetContainerRuntime returns the container runtime the process is running in. // If pid is less than one, it returns the runtime for "self". @@ -189,7 +189,7 @@ func getContainerRuntime(input string) ContainerRuntime { } func osFileExists(file string) bool { - if _, err := os.Stat(file); !os.IsNotExist(err) { + if _, err := filesystem.FS.Stat(file); !os.IsNotExist(err) { return true } return false @@ -200,7 +200,7 @@ func readFile(file string) []byte { return nil } - b, _ := os.ReadFile(file) + b, _ := filesystem.ReadFile(file) return b } diff --git a/pkg/filesystem/resolve.go b/pkg/util/resolve.go similarity index 92% rename from pkg/filesystem/resolve.go rename to pkg/util/resolve.go index de481e31ed..56841425e9 100644 --- a/pkg/filesystem/resolve.go +++ b/pkg/util/resolve.go @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package filesystem +package util import ( "os" "path/filepath" "github.com/GoogleContainerTools/kaniko/pkg/config" - "github.com/GoogleContainerTools/kaniko/pkg/util" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -34,14 +34,14 @@ import ( // * If path is a symlink, resolve it's target. If the target is not ignored add it to the // output set. // * Add all ancestors of each path to the output set. -func ResolvePaths(paths []string, wl []util.IgnoreListEntry) (pathsToAdd []string, err error) { +func ResolvePaths(paths []string, wl []IgnoreListEntry) (pathsToAdd []string, err error) { logrus.Tracef("Resolving paths %s", paths) fileSet := make(map[string]bool) for _, f := range paths { // If the given path is part of the ignorelist ignore it - if util.IsInProvidedIgnoreList(f, wl) { + if IsInProvidedIgnoreList(f, wl) { logrus.Debugf("Path %s is in list to ignore, ignoring it", f) continue } @@ -80,7 +80,7 @@ func ResolvePaths(paths []string, wl []util.IgnoreListEntry) (pathsToAdd []strin // If the given path is a symlink and the target is part of the ignorelist // ignore the target - if util.CheckCleanedPathAgainstProvidedIgnoreList(evaled, wl) { + if CheckCleanedPathAgainstProvidedIgnoreList(evaled, wl) { logrus.Debugf("Path %s is ignored, ignoring it", evaled) continue } @@ -105,7 +105,7 @@ func filesWithParentDirs(files []string) []string { file = filepath.Clean(file) filesSet[file] = true - for _, dir := range util.ParentDirectories(file) { + for _, dir := range ParentDirectories(file) { dir = filepath.Clean(dir) filesSet[dir] = true } @@ -134,12 +134,12 @@ func resolveSymlinkAncestor(path string) (string, error) { loop: for newPath != config.RootDir { - fi, err := os.Lstat(newPath) + fi, err := filesystem.FS.Lstat(newPath) if err != nil { return "", errors.Wrap(err, "resolvePaths: failed to lstat") } - if util.IsSymlink(fi) { + if IsSymlink(fi) { last = filepath.Base(newPath) newPath = filepath.Dir(newPath) } else { diff --git a/pkg/filesystem/resolve_test.go b/pkg/util/resolve_test.go similarity index 78% rename from pkg/filesystem/resolve_test.go rename to pkg/util/resolve_test.go index 57f7f47ada..9e9f016438 100644 --- a/pkg/filesystem/resolve_test.go +++ b/pkg/util/resolve_test.go @@ -14,17 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -package filesystem +package util import ( "fmt" - "os" "path/filepath" "reflect" "sort" "testing" - "github.com/GoogleContainerTools/kaniko/pkg/util" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" ) func Test_ResolvePaths(t *testing.T) { @@ -62,25 +61,25 @@ func Test_ResolvePaths(t *testing.T) { fLink := filepath.Join(dir, "link", f) fTarget := filepath.Join(dir, "target", f) - if err := os.MkdirAll(filepath.Dir(fTarget), 0777); err != nil { + if err := filesystem.MkdirAll(filepath.Dir(fTarget), 0o777); err != nil { t.Fatal(err) } - if err := os.WriteFile(fTarget, []byte{}, 0777); err != nil { + if err := filesystem.WriteFile(fTarget, []byte{}, 0o777); err != nil { t.Fatal(err) } - if err := os.MkdirAll(filepath.Dir(fLink), 0777); err != nil { + if err := filesystem.MkdirAll(filepath.Dir(fLink), 0o777); err != nil { t.Fatal(err) } - if err := os.Symlink(fTarget, fLink); err != nil { + if err := filesystem.FS.Symlink(fTarget, fLink); err != nil { t.Fatal(err) } } t.Run("none are ignored", func(t *testing.T) { - wl := []util.IgnoreListEntry{} + wl := []IgnoreListEntry{} inputFiles := []string{} expectedFiles := []string{} @@ -102,7 +101,7 @@ func Test_ResolvePaths(t *testing.T) { }) t.Run("some are ignored", func(t *testing.T) { - wl := []util.IgnoreListEntry{ + wl := []IgnoreListEntry{ { Path: filepath.Join(dir, "link", "baz"), }, @@ -118,7 +117,7 @@ func Test_ResolvePaths(t *testing.T) { link := filepath.Join(dir, "link", f) inputFiles = append(inputFiles, link) - if util.IsInProvidedIgnoreList(link, wl) { + if IsInProvidedIgnoreList(link, wl) { t.Logf("skipping %s", link) continue } @@ -127,7 +126,7 @@ func Test_ResolvePaths(t *testing.T) { target := filepath.Join(dir, "target", f) - if util.IsInProvidedIgnoreList(target, wl) { + if IsInProvidedIgnoreList(target, wl) { t.Logf("skipping %s", target) continue } @@ -138,15 +137,15 @@ func Test_ResolvePaths(t *testing.T) { link := filepath.Join(dir, "link", "zoom/") target := filepath.Join(dir, "target", "zaam/") - if err := os.MkdirAll(target, 0777); err != nil { + if err := filesystem.MkdirAll(target, 0o777); err != nil { t.Fatal(err) } - if err := os.WriteFile(filepath.Join(target, "meow.txt"), []byte{}, 0777); err != nil { + if err := filesystem.WriteFile(filepath.Join(target, "meow.txt"), []byte{}, 0o777); err != nil { t.Fatal(err) } - if err := os.Symlink(target, link); err != nil { + if err := filesystem.FS.Symlink(target, link); err != nil { t.Fatal(err) } @@ -171,7 +170,7 @@ func Test_ResolvePaths(t *testing.T) { inputFiles := []string{} expectedFiles := []string{} - wl := []util.IgnoreListEntry{} + wl := []IgnoreListEntry{} files, err := ResolvePaths(inputFiles, wl) @@ -185,13 +184,13 @@ func Test_resolveSymlinkAncestor(t *testing.T) { targetDir := filepath.Join(testDir, "bar", "baz") - if err := os.MkdirAll(targetDir, 0777); err != nil { + if err := filesystem.MkdirAll(targetDir, 0o777); err != nil { t.Fatal(err) } targetPath := filepath.Join(targetDir, "bam.txt") - if err := os.WriteFile(targetPath, []byte("meow"), 0777); err != nil { + if err := filesystem.WriteFile(targetPath, []byte("meow"), 0o777); err != nil { t.Fatal(err) } @@ -200,17 +199,17 @@ func Test_resolveSymlinkAncestor(t *testing.T) { t.Run("path is a symlink", func(t *testing.T) { testDir, targetPath := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) linkDir := filepath.Join(testDir, "foo", "buzz") - if err := os.MkdirAll(linkDir, 0777); err != nil { + if err := filesystem.MkdirAll(linkDir, 0o777); err != nil { t.Fatal(err) } linkPath := filepath.Join(linkDir, "zoom.txt") - if err := os.Symlink(targetPath, linkPath); err != nil { + if err := filesystem.FS.Symlink(targetPath, linkPath); err != nil { t.Fatal(err) } @@ -228,10 +227,10 @@ func Test_resolveSymlinkAncestor(t *testing.T) { t.Run("dir ends with / is not a symlink", func(t *testing.T) { testDir, _ := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) linkDir := filepath.Join(testDir, "var", "www") - if err := os.MkdirAll(linkDir, 0777); err != nil { + if err := filesystem.MkdirAll(linkDir, 0o777); err != nil { t.Fatal(err) } @@ -249,21 +248,21 @@ func Test_resolveSymlinkAncestor(t *testing.T) { t.Run("path is a dead symlink", func(t *testing.T) { testDir, targetPath := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) linkDir := filepath.Join(testDir, "foo", "buzz") - if err := os.MkdirAll(linkDir, 0777); err != nil { + if err := filesystem.MkdirAll(linkDir, 0o777); err != nil { t.Fatal(err) } linkPath := filepath.Join(linkDir, "zoom.txt") - if err := os.Symlink(targetPath, linkPath); err != nil { + if err := filesystem.FS.Symlink(targetPath, linkPath); err != nil { t.Fatal(err) } - if err := os.Remove(targetPath); err != nil { + if err := filesystem.FS.Remove(targetPath); err != nil { t.Fatal(err) } @@ -281,7 +280,7 @@ func Test_resolveSymlinkAncestor(t *testing.T) { t.Run("path is not a symlink", func(t *testing.T) { testDir, targetPath := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) expected := targetPath @@ -297,19 +296,19 @@ func Test_resolveSymlinkAncestor(t *testing.T) { t.Run("parent of path is a symlink", func(t *testing.T) { testDir, targetPath := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) targetDir := filepath.Dir(targetPath) linkDir := filepath.Join(testDir, "foo") - if err := os.MkdirAll(linkDir, 0777); err != nil { + if err := filesystem.MkdirAll(linkDir, 0o777); err != nil { t.Fatal(err) } linkDir = filepath.Join(linkDir, "gaz") - if err := os.Symlink(targetDir, linkDir); err != nil { + if err := filesystem.FS.Symlink(targetDir, linkDir); err != nil { t.Fatal(err) } @@ -329,23 +328,23 @@ func Test_resolveSymlinkAncestor(t *testing.T) { t.Run("parent of path is a dead symlink", func(t *testing.T) { testDir, targetPath := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) targetDir := filepath.Dir(targetPath) linkDir := filepath.Join(testDir, "foo") - if err := os.MkdirAll(linkDir, 0777); err != nil { + if err := filesystem.MkdirAll(linkDir, 0o777); err != nil { t.Fatal(err) } linkDir = filepath.Join(linkDir, "gaz") - if err := os.Symlink(targetDir, linkDir); err != nil { + if err := filesystem.FS.Symlink(targetDir, linkDir); err != nil { t.Fatal(err) } - if err := os.RemoveAll(targetDir); err != nil { + if err := filesystem.FS.RemoveAll(targetDir); err != nil { t.Fatal(err) } @@ -359,13 +358,13 @@ func Test_resolveSymlinkAncestor(t *testing.T) { t.Run("great grandparent of path is a symlink", func(t *testing.T) { testDir, targetPath := setupDirs(t) - defer os.RemoveAll(testDir) + defer filesystem.FS.RemoveAll(testDir) targetDir := filepath.Dir(targetPath) linkDir := filepath.Join(testDir, "foo") - if err := os.Symlink(filepath.Dir(targetDir), linkDir); err != nil { + if err := filesystem.FS.Symlink(filepath.Dir(targetDir), linkDir); err != nil { t.Fatal(err) } diff --git a/pkg/util/tar_util.go b/pkg/util/tar_util.go index 2faf9cb991..41012f1688 100644 --- a/pkg/util/tar_util.go +++ b/pkg/util/tar_util.go @@ -30,6 +30,7 @@ import ( "time" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/system" "github.com/pkg/errors" @@ -80,7 +81,7 @@ func CreateTarballOfDirectory(pathToDir string, f io.Writer) error { return tarWriter.AddFileToTar(path) } - return filepath.WalkDir(pathToDir, walkFn) + return filesystem.WalkDir(pathToDir, walkFn) } // Close will close any open streams used by Tar. @@ -90,14 +91,14 @@ func (t *Tar) Close() { // AddFileToTar adds the file at path p to the tar func (t *Tar) AddFileToTar(p string) error { - i, err := os.Lstat(p) + i, err := filesystem.FS.Lstat(p) if err != nil { return fmt.Errorf("Failed to get file info for %s: %w", p, err) } linkDst := "" if i.Mode()&os.ModeSymlink != 0 { var err error - linkDst, err = os.Readlink(p) + linkDst, err = filesystem.FS.Readlink(p) if err != nil { return err } @@ -155,7 +156,7 @@ func (t *Tar) AddFileToTar(p string) error { if !(i.Mode().IsRegular()) || hardlink { return nil } - r, err := os.Open(p) + r, err := filesystem.FS.Open(p) if err != nil { return err } @@ -252,7 +253,7 @@ func getSyscallStatT(i os.FileInfo) *syscall.Stat_t { func UnpackLocalTarArchive(path, dest string) ([]string, error) { // First, we need to check if the path is a local tar archive if compressed, compressionLevel := fileIsCompressedTar(path); compressed { - file, err := os.Open(path) + file, err := filesystem.FS.Open(path) if err != nil { return nil, err } @@ -270,7 +271,7 @@ func UnpackLocalTarArchive(path, dest string) ([]string, error) { } } if fileIsUncompressedTar(path) { - file, err := os.Open(path) + file, err := filesystem.FS.Open(path) if err != nil { return nil, err } @@ -288,7 +289,7 @@ func IsFileLocalTarArchive(src string) bool { } func fileIsCompressedTar(src string) (bool, archive.Compression) { - r, err := os.Open(src) + r, err := filesystem.FS.Open(src) if err != nil { return false, -1 } @@ -302,12 +303,12 @@ func fileIsCompressedTar(src string) (bool, archive.Compression) { } func fileIsUncompressedTar(src string) bool { - r, err := os.Open(src) + r, err := filesystem.FS.Open(src) if err != nil { return false } defer r.Close() - fi, err := os.Lstat(src) + fi, err := filesystem.FS.Lstat(src) if err != nil { return false } @@ -324,7 +325,7 @@ func fileIsUncompressedTar(src string) bool { // UnpackCompressedTar unpacks the compressed tar at path to dir func UnpackCompressedTar(path, dir string) error { - file, err := os.Open(path) + file, err := filesystem.FS.Open(path) if err != nil { return err } diff --git a/pkg/util/tar_util_test.go b/pkg/util/tar_util_test.go index 18ba4e00bc..0f773ade4c 100644 --- a/pkg/util/tar_util_test.go +++ b/pkg/util/tar_util_test.go @@ -28,12 +28,15 @@ import ( "testing" "time" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/GoogleContainerTools/kaniko/testutil" ) -var regularFiles = []string{"file", "file.tar", "file.tar.gz"} -var uncompressedTars = []string{"uncompressed", "uncompressed.tar"} -var compressedTars = []string{"compressed", "compressed.tar.gz"} +var ( + regularFiles = []string{"file", "file.tar", "file.tar.gz"} + uncompressedTars = []string{"uncompressed", "uncompressed.tar"} + compressedTars = []string{"compressed", "compressed.tar.gz"} +) func Test_IsLocalTarArchive(t *testing.T) { testDir := t.TempDir() @@ -61,12 +64,12 @@ func Test_AddFileToTar(t *testing.T) { testDir := t.TempDir() path := filepath.Join(testDir, regularFiles[0]) - if err := os.WriteFile(path, []byte("hello"), os.ModePerm); err != nil { + if err := filesystem.WriteFile(path, []byte("hello"), os.ModePerm); err != nil { t.Fatal(err) } // use a pre-determined time with non-zero microseconds to avoid flakiness mtime := time.UnixMicro(1635533172891395) - if err := os.Chtimes(path, mtime, mtime); err != nil { + if err := filesystem.FS.Chtimes(path, mtime, mtime); err != nil { t.Fatal(err) } @@ -97,7 +100,7 @@ func setUpFilesAndTars(testDir string) error { } for _, uncompressedTar := range uncompressedTars { - tarFile, err := os.Create(filepath.Join(testDir, uncompressedTar)) + tarFile, err := filesystem.FS.Create(filepath.Join(testDir, uncompressedTar)) if err != nil { return err } @@ -107,7 +110,7 @@ func setUpFilesAndTars(testDir string) error { } for _, compressedTar := range compressedTars { - tarFile, err := os.Create(filepath.Join(testDir, compressedTar)) + tarFile, err := filesystem.FS.Create(filepath.Join(testDir, compressedTar)) if err != nil { return err } @@ -140,7 +143,7 @@ func Test_CreateTarballOfDirectory(t *testing.T) { testutil.CheckError(t, wantErr, err) extracedFilesDir := filepath.Join(tmpDir, "extracted") - err = os.Mkdir(extracedFilesDir, 0755) + err = filesystem.FS.Mkdir(extracedFilesDir, 0o755) if err != nil { t.Error(err) return @@ -148,7 +151,7 @@ func Test_CreateTarballOfDirectory(t *testing.T) { files, err := UnTar(f, extracedFilesDir) testutil.CheckError(t, wantErr, err) for _, filePath := range files { - fileInfo, err := os.Lstat(filePath) + fileInfo, err := filesystem.FS.Lstat(filePath) testutil.CheckError(t, wantErr, err) if fileInfo.IsDir() { // skip directory @@ -157,7 +160,7 @@ func Test_CreateTarballOfDirectory(t *testing.T) { if modTime := fileInfo.ModTime(); modTime.Equal(time.Unix(0, 0)) { t.Errorf("unexpected modtime %q of %q", modTime, fileInfo.Name()) } - file, err := os.Open(filePath) + file, err := filesystem.FS.Open(filePath) testutil.CheckError(t, wantErr, err) body, err := io.ReadAll(file) testutil.CheckError(t, wantErr, err) @@ -170,7 +173,7 @@ func createFilesInTempDir(t *testing.T, tmpDir string) { for i := 0; i < 2; i++ { fName := filepath.Join(tmpDir, fmt.Sprint(i)) content := fmt.Sprintf("hello from %d\n", i) - if err := os.WriteFile(fName, []byte(content), 0666); err != nil { + if err := filesystem.WriteFile(fName, []byte(content), 0o666); err != nil { t.Error(err) return } @@ -184,7 +187,7 @@ func Test_NewReproducibleTar(t *testing.T) { // Create tarball ignoring timestamps tw := NewReproducibleTar(f) - if err := filepath.WalkDir(tmpDir, func(path string, _ fs.DirEntry, err error) error { + if err := filesystem.WalkDir(tmpDir, func(path string, _ fs.DirEntry, err error) error { if err != nil { return err } @@ -197,7 +200,7 @@ func Test_NewReproducibleTar(t *testing.T) { } extracedFilesDir := filepath.Join(tmpDir, "extracted") - if err := os.Mkdir(extracedFilesDir, 0755); err != nil { + if err := filesystem.FS.Mkdir(extracedFilesDir, 0o755); err != nil { t.Fatal(err) } files, err := UnTar(f, extracedFilesDir) @@ -205,7 +208,7 @@ func Test_NewReproducibleTar(t *testing.T) { t.Fatalf("untar: %s", err.Error()) } for _, filePath := range files { - fileInfo, err := os.Lstat(filePath) + fileInfo, err := filesystem.FS.Lstat(filePath) if err != nil { t.Fatalf("stat %q: %s", filePath, err.Error()) } @@ -217,7 +220,7 @@ func Test_NewReproducibleTar(t *testing.T) { if modTime := fileInfo.ModTime(); !modTime.Equal(time.Unix(0, 0)) { t.Errorf("unexpected modtime %q of %q", modTime, filePath) } - file, err := os.Open(filePath) + file, err := filesystem.FS.Open(filePath) if err != nil { t.Fatalf("open file %q: %s", filePath, err.Error()) } diff --git a/pkg/util/transport_util.go b/pkg/util/transport_util.go index e6cdf9dd9f..8b0c7c4a76 100644 --- a/pkg/util/transport_util.go +++ b/pkg/util/transport_util.go @@ -20,12 +20,11 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "os" - "strings" - "net/http" + "strings" "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/sirupsen/logrus" ) @@ -43,7 +42,7 @@ func (p *X509CertPool) value() *x509.CertPool { } func (p *X509CertPool) append(path string) error { - pem, err := os.ReadFile(path) + pem, err := filesystem.ReadFile(path) if err != nil { return err } @@ -57,8 +56,7 @@ type KeyPairLoader interface { load(string, string) (tls.Certificate, error) } -type X509KeyPairLoader struct { -} +type X509KeyPairLoader struct{} func (p *X509KeyPairLoader) load(certFile, keyFile string) (tls.Certificate, error) { return tls.LoadX509KeyPair(certFile, keyFile) diff --git a/pkg/util/util.go b/pkg/util/util.go index 92ca866c71..6c6acc4ee9 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -31,6 +31,7 @@ import ( "syscall" "time" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/minio/highwayhash" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -48,7 +49,7 @@ func Hasher() func(string) (string, error) { key := make([]byte, highwayhash.Size) hasher := func(p string) (string, error) { h, _ := highwayhash.New(key) - fi, err := os.Lstat(p) + fi, err := filesystem.FS.Lstat(p) if err != nil { return "", err } @@ -64,7 +65,7 @@ func Hasher() func(string) (string, error) { if capability != nil { h.Write(capability) } - f, err := os.Open(p) + f, err := filesystem.FS.Open(p) if err != nil { return "", err } @@ -75,7 +76,7 @@ func Hasher() func(string) (string, error) { return "", err } } else if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - linkPath, err := os.Readlink(p) + linkPath, err := filesystem.FS.Readlink(p) if err != nil { return "", err } @@ -91,7 +92,7 @@ func Hasher() func(string) (string, error) { func CacheHasher() func(string) (string, error) { hasher := func(p string) (string, error) { h := md5.New() - fi, err := os.Lstat(p) + fi, err := filesystem.FS.Lstat(p) if err != nil { return "", err } @@ -119,7 +120,7 @@ func CacheHasher() func(string) (string, error) { } if fi.Mode().IsRegular() { - f, err := os.Open(p) + f, err := filesystem.FS.Open(p) if err != nil { return "", err } @@ -128,7 +129,7 @@ func CacheHasher() func(string) (string, error) { return "", err } } else if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - linkPath, err := os.Readlink(p) + linkPath, err := filesystem.FS.Readlink(p) if err != nil { return "", err } @@ -145,7 +146,7 @@ func CacheHasher() func(string) (string, error) { func MtimeHasher() func(string) (string, error) { hasher := func(p string) (string, error) { h := md5.New() - fi, err := os.Lstat(p) + fi, err := filesystem.FS.Lstat(p) if err != nil { return "", err } @@ -160,7 +161,7 @@ func MtimeHasher() func(string) (string, error) { func RedoHasher() func(string) (string, error) { hasher := func(p string) (string, error) { h := md5.New() - fi, err := os.Lstat(p) + fi, err := filesystem.FS.Lstat(p) if err != nil { return "", err } diff --git a/testutil/util.go b/testutil/util.go index 6d876ec373..99d124a324 100644 --- a/testutil/util.go +++ b/testutil/util.go @@ -18,12 +18,12 @@ package testutil import ( "fmt" - "os" "os/user" "path/filepath" "reflect" "testing" + "github.com/GoogleContainerTools/kaniko/pkg/filesystem" "github.com/google/go-cmp/cmp" ) @@ -31,10 +31,10 @@ import ( func SetupFiles(path string, files map[string]string) error { for p, c := range files { path := filepath.Join(path, p) - if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil { + if err := filesystem.MkdirAll(filepath.Dir(path), 0o750); err != nil { return err } - if err := os.WriteFile(path, []byte(c), 0644); err != nil { + if err := filesystem.WriteFile(path, []byte(c), 0o644); err != nil { return err } } @@ -48,6 +48,7 @@ type CurrentUser struct { } func GetCurrentUser(t *testing.T) CurrentUser { + t.Helper() currentUser, err := user.Current() if err != nil { t.Fatalf("Cannot get current user: %s", err) @@ -90,12 +91,14 @@ func CheckErrorAndDeepEqual(t *testing.T, shouldErr bool, err error, expected, a } func CheckError(t *testing.T, shouldErr bool, err error) { + t.Helper() if err := checkErr(shouldErr, err); err != nil { t.Error(err) } } func CheckNoError(t *testing.T, err error) { + t.Helper() if err != nil { t.Errorf("%+v", err) } diff --git a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go index 1a24b10d76..4f1b23edbe 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go +++ b/vendor/github.com/google/go-containerregistry/pkg/v1/mutate/mutate.go @@ -447,6 +447,8 @@ func Time(img v1.Image, t time.Time) (v1.Image, error) { } func layerTime(layer v1.Layer, t time.Time) (v1.Layer, error) { + return layer, nil + layerReader, err := layer.Uncompressed() if err != nil { return nil, fmt.Errorf("getting layer: %w", err) @@ -468,7 +470,7 @@ func layerTime(layer v1.Layer, t time.Time) (v1.Layer, error) { header.ModTime = t - //PAX and GNU Format support additional timestamps in the header + // PAX and GNU Format support additional timestamps in the header if header.Format == tar.FormatPAX || header.Format == tar.FormatGNU { header.AccessTime = t header.ChangeTime = t diff --git a/vendor/github.com/twpayne/go-vfs/v5/.gitignore b/vendor/github.com/twpayne/go-vfs/v5/.gitignore new file mode 100644 index 0000000000..7447f89a59 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/.gitignore @@ -0,0 +1 @@ +/bin \ No newline at end of file diff --git a/vendor/github.com/twpayne/go-vfs/v5/.golangci.yml b/vendor/github.com/twpayne/go-vfs/v5/.golangci.yml new file mode 100644 index 0000000000..35fc90b87b --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/.golangci.yml @@ -0,0 +1,129 @@ +go-version: '1.21' + +linters: + enable: + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - decorder + - dogsled + - dupl + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + - execinquery + - exhaustive + - exportloopref + - forbidigo + - forcetypeassert + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - goconst + - gocritic + - gocyclo + - godot + - godox + - goerr113 + - gofmt + - gofumpt + - goheader + - goimports + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - inamedparam + - ineffassign + - ireturn + - lll + - loggercheck + - maintidx + - makezero + - mirror + - misspell + - musttag + - nakedret + - nilerr + - nilnil + - noctx + - nolintlint + - nonamedreturns + - nosprintfhostport + - perfsprint + - prealloc + - predeclared + - promlinter + - protogetter + - reassign + - rowserrcheck + - sloglint + - spancheck + - sqlclosecheck + - staticcheck + - stylecheck + - tagalign + - tagliatelle + - tenv + - testifylint + - testpackage + - thelper + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign + - whitespace + - zerologlint + disable: + - asasalint + - cyclop + - depguard + - exhaustruct + - funlen + - gochecknoglobals + - gochecknoinits + - gocognit + - gomnd + - interfacebloat + - nestif + - nlreturn + - paralleltest + - revive + - testableexamples + - tparallel + - varnamelen + - wrapcheck + - wsl + +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/twpayne/go-vfs) + gofumpt: + extra-rules: true + module-path: github.com/twpayne/go-vfs + goimports: + local-prefixes: github.com/twpayne/go-vfs + misspell: + locale: US + +issues: + exclude-rules: + - linters: + - goerr113 + text: "do not define dynamic errors, use wrapped static errors instead" diff --git a/vendor/github.com/twpayne/go-vfs/v5/LICENSE b/vendor/github.com/twpayne/go-vfs/v5/LICENSE new file mode 100644 index 0000000000..24f8fc050f --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 Tom Payne + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/twpayne/go-vfs/v5/Makefile b/vendor/github.com/twpayne/go-vfs/v5/Makefile new file mode 100644 index 0000000000..821eb75618 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/Makefile @@ -0,0 +1,35 @@ +GO?=go +GOLANGCI_LINT_VERSION=$(shell grep GOLANGCI_LINT_VERSION: .github/workflows/main.yml | awk '{ print $$2 }') + +.PHONY: smoketest +smoketest: test lint + +.PHONY: test +test: + ${GO} test ./... + +.PHONY: lint +lint: ensure-golangci-lint + ./bin/golangci-lint run + +.PHONY: format +format: ensure-gofumports + find . -name \*.go | xargs ./bin/gofumports -local github.com/twpayne/chezmoi -w + +.PHONY: ensure-tools +ensure-tools: \ + ensure-gofumports \ + ensure-golangci-lint + +.PHONY: ensure-gofumports +ensure-gofumports: + if [ ! -x bin/gofumports ] ; then \ + mkdir -p bin ; \ + GOBIN=$(shell pwd)/bin ${GO} install mvdan.cc/gofumpt/gofumports@latest ; \ + fi + +.PHONY: ensure-golangci-lint +ensure-golangci-lint: + if [ ! -x bin/golangci-lint ] || ( ./bin/golangci-lint --version | grep -Fqv "version ${GOLANGCI_LINT_VERSION}" ) ; then \ + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- v${GOLANGCI_LINT_VERSION} ; \ + fi \ No newline at end of file diff --git a/vendor/github.com/twpayne/go-vfs/v5/README.md b/vendor/github.com/twpayne/go-vfs/v5/README.md new file mode 100644 index 0000000000..c130325160 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/README.md @@ -0,0 +1,158 @@ +# go-vfs + +[![PkgGoDev](https://pkg.go.dev/badge/github.com/twpayne/go-vfs/v5)](https://pkg.go.dev/github.com/twpayne/go-vfs/v5) + +Package `vfs` provides an abstraction of the `os` and `io` packages that is easy +to test. + +## Key features + +* File system abstraction layer for commonly-used `os` and `io` functions from + the standard library. + +* Powerful and easy-to-use declarative testing framework, `vfst`. You declare + the desired state of the filesystem after your code has run, and `vfst` tests + that the filesystem matches that state. For a quick tour of `vfst`'s features, + see [the examples in the + documentation](https://godoc.org/github.com/twpayne/go-vfs/v5/vfst#pkg-examples). + +* Compatibility with + [`github.com/spf13/afero`](https://github.com/spf13/afero) and + [`github.com/src-d/go-billy`](https://github.com/src-d/go-billy). + +## Quick start + +`vfs` provides implementations of the `FS` interface: + +```go +// An FS is an abstraction over commonly-used functions in the os and io +// packages. +type FS interface { + Chmod(name string, mode fs.FileMode) error + Chown(name string, uid, git int) error + Chtimes(name string, atime, mtime time.Time) error + Create(name string) (*os.File, error) + Glob(pattern string) ([]string, error) + Lchown(name string, uid, git int) error + Link(oldname, newname string) error + Lstat(name string) (fs.FileInfo, error) + Mkdir(name string, perm fs.FileMode) error + Open(name string) (fs.File, error) + OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) + PathSeparator() rune + RawPath(name string) (string, error) + ReadDir(dirname string) ([]fs.DirEntry, error) + ReadFile(filename string) ([]byte, error) + Readlink(name string) (string, error) + Remove(name string) error + RemoveAll(name string) error + Rename(oldpath, newpath string) error + Stat(name string) (fs.FileInfo, error) + Symlink(oldname, newname string) error + Truncate(name string, size int64) error + WriteFile(filename string, data []byte, perm fs.FileMode) error +} +``` + +To use `vfs`, you write your code to use the `FS` interface, and then use +`vfst` to test it. + +`vfs` also provides functions `MkdirAll` (equivalent to `os.MkdirAll`), +`Contains` (an improved `filepath.HasPrefix`), and `Walk` (equivalent to +`filepath.Walk`) that operate on an `FS`. + +The implementations of `FS` provided are: + +* `OSFS` which calls the underlying `os` and `io` functions directly. + +* `PathFS` which transforms all paths to provide a poor-man's `chroot`. + +* `ReadOnlyFS` which prevents modification of the underlying FS. + +* `TestFS` which assists running tests on a real filesystem but in a temporary + directory that is easily cleaned up. It uses `OSFS` under the hood. + +Example usage: + +```go +// writeConfigFile is the function we're going to test. It can make arbitrary +// changes to the filesystem through fileSystem. +func writeConfigFile(fileSystem vfs.FS) error { + return fileSystem.WriteFile("/home/user/app.conf", []byte(`app config`), 0644) +} + +// TestWriteConfigFile is our test function. +func TestWriteConfigFile(t *testing.T) { + // Create and populate an temporary directory with a home directory. + fileSystem, cleanup, err := vfst.NewTestFS(map[string]any{ + "/home/user/.bashrc": "# contents of user's .bashrc\n", + }) + + // Check that the directory was populated successfully. + if err != nil { + t.Fatalf("vfsTest.NewTestFS(_) == _, _, %v, want _, _, ", err) + } + + // Ensure that the temporary directory is removed. + defer cleanup() + + // Call the function we want to test. + if err := writeConfigFile(fileSystem); err != nil { + t.Error(err) + } + + // Check properties of the filesystem after our function has modified it. + vfst.RunTests(t, fileSystem, "app_conf", + vfst.TestPath("/home/user/app.conf", + vfst.TestModeIsRegular(), + vfst.TestModePerm(0644), + vfst.TestContentsString("app config"), + ), + ) +} +``` + +## `github.com/spf13/afero` compatibility + +There is a compatibility shim for +[`github.com/spf13/afero`](https://github.com/spf13/afero) in +[`github.com/twpayne/go-vfsafero`](https://github.com/twpayne/go-vfsafero). This +allows you to use `vfst` to test existing code that uses +[`afero.FS`](https://godoc.org/github.com/spf13/afero#Fs). See [the +documentation](https://godoc.org/github.com/twpayne/go-vfsafero) for an example. + +## `github.com/src-d/go-billy` compatibility + +There is a compatibility shim for +[`github.com/src-d/go-billy`](https://github.com/src-d/go-billy) in +[`github.com/twpayne/go-vfsbilly`](https://github.com/twpayne/go-vfsbilly). This +allows you to use `vfst` to test existing code that uses +[`billy.Filesystem`](https://godoc.org/github.com/src-d/go-billy#Filesystem). +See [the documentation](https://godoc.org/github.com/twpayne/go-vfsbilly) for an +example. + +## Motivation + +`vfs` was inspired by +[`github.com/spf13/afero`](https://github.com/spf13/afero). So, why not use +`afero`? + +* `afero` has several critical bugs in its in-memory mock filesystem + implementation `MemMapFs`, to the point that it is unusable for non-trivial + test cases. `vfs` does not attempt to implement an in-memory mock filesystem, + and instead only provides a thin layer around the standard library's `os` and + `io` packages, and as such should have fewer bugs. + +* `afero` does not support creating or reading symbolic links, and its + `LstatIfPossible` interface is clumsy to use as it is not part of the + `afero.Fs` interface. `vfs` provides out-of-the-box support for symbolic links + with all methods in the `FS` interface. + +* `afero` has been effectively abandoned by its author, and a "friendly fork" + ([`github.com/absfs/afero`](https://github.com/absfs/afero)) has not seen much + activity. `vfs`, by providing much less functionality than `afero`, should be + smaller and easier to maintain. + +## License + +MIT diff --git a/vendor/github.com/twpayne/go-vfs/v5/contains.go b/vendor/github.com/twpayne/go-vfs/v5/contains.go new file mode 100644 index 0000000000..998e312014 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/contains.go @@ -0,0 +1,69 @@ +package vfs + +import ( + "errors" + "io/fs" + "os" + "path/filepath" + "syscall" +) + +// A Stater implements Stat. It is assumed that the fs.FileInfos returned by +// Stat are compatible with os.SameFile. +type Stater interface { + Stat(name string) (fs.FileInfo, error) +} + +// Contains returns true if p is reachable by traversing through prefix. prefix +// must exist, but p may not. It is an expensive but accurate alternative to the +// deprecated filepath.HasPrefix. +func Contains(fileSystem Stater, p, prefix string) (bool, error) { + prefixFI, err := fileSystem.Stat(prefix) + if err != nil { + return false, err + } + for { + fi, err := fileSystem.Stat(p) + switch { + case err == nil: + if os.SameFile(fi, prefixFI) { + return true, nil + } + goto TryParent + case errors.Is(err, fs.ErrNotExist): + goto TryParent + case errors.Is(err, fs.ErrPermission): + goto TryParent + default: + // Remove any fs.PathError or os.SyscallError wrapping, if present. + Unwrap: + for { + var pathError *fs.PathError + var syscallError *os.SyscallError + switch { + case errors.As(err, &pathError): + err = pathError.Err + case errors.As(err, &syscallError): + err = syscallError.Err + default: + break Unwrap + } + } + // Ignore some syscall.Errnos. + var syscallErrno syscall.Errno + if errors.As(err, &syscallErrno) { + if _, ignore := ignoreErrnoInContains[syscallErrno]; ignore { + goto TryParent + } + } + return false, err + } + TryParent: + parentDir := filepath.Dir(p) + if parentDir == p { + // Return when we stop making progress. + return false, nil + } + p = parentDir + } +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/emptyfs.go b/vendor/github.com/twpayne/go-vfs/v5/emptyfs.go new file mode 100644 index 0000000000..17760f36b1 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/emptyfs.go @@ -0,0 +1,36 @@ +package vfs + +import ( + "io/fs" + "os" + "time" +) + +// An EmptyFS is a VFS that does not contain any files. +type EmptyFS struct{} + +func (EmptyFS) Chmod(name string, mode fs.FileMode) error { return os.ErrNotExist } +func (EmptyFS) Chown(name string, uid, git int) error { return os.ErrNotExist } +func (EmptyFS) Chtimes(name string, atime, mtime time.Time) error { return os.ErrNotExist } +func (EmptyFS) Create(name string) (*os.File, error) { return nil, os.ErrNotExist } +func (EmptyFS) Glob(pattern string) ([]string, error) { return nil, os.ErrNotExist } +func (EmptyFS) Lchown(name string, uid, git int) error { return os.ErrNotExist } +func (EmptyFS) Link(oldname, newname string) error { return os.ErrNotExist } +func (EmptyFS) Lstat(name string) (fs.FileInfo, error) { return nil, os.ErrNotExist } +func (EmptyFS) Mkdir(name string, perm fs.FileMode) error { return os.ErrNotExist } +func (EmptyFS) Open(name string) (fs.File, error) { return nil, os.ErrNotExist } +func (EmptyFS) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) { + return nil, os.ErrNotExist +} +func (EmptyFS) PathSeparator() rune { return '/' } +func (EmptyFS) RawPath(name string) (string, error) { return name, nil } +func (EmptyFS) ReadDir(dirname string) ([]fs.DirEntry, error) { return nil, os.ErrNotExist } +func (EmptyFS) ReadFile(filename string) ([]byte, error) { return nil, os.ErrNotExist } +func (EmptyFS) Readlink(name string) (string, error) { return "", os.ErrNotExist } +func (EmptyFS) Remove(name string) error { return nil } +func (EmptyFS) RemoveAll(name string) error { return nil } +func (EmptyFS) Rename(oldpath, newpath string) error { return os.ErrNotExist } +func (EmptyFS) Stat(name string) (fs.FileInfo, error) { return nil, os.ErrNotExist } +func (EmptyFS) Symlink(oldname, newname string) error { return os.ErrNotExist } +func (EmptyFS) Truncate(name string, size int64) error { return os.ErrNotExist } +func (EmptyFS) WriteFile(filename string, data []byte, perm fs.FileMode) error { return os.ErrNotExist } diff --git a/vendor/github.com/twpayne/go-vfs/v5/mkdirall.go b/vendor/github.com/twpayne/go-vfs/v5/mkdirall.go new file mode 100644 index 0000000000..53b9f835b1 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/mkdirall.go @@ -0,0 +1,57 @@ +package vfs + +import ( + "errors" + "io/fs" + "path/filepath" +) + +// A MkdirStater implements all the functionality needed by MkdirAll. +type MkdirStater interface { + Mkdir(name string, perm fs.FileMode) error + Stat(name string) (fs.FileInfo, error) +} + +// MkdirAll is equivalent to os.MkdirAll but operates on fileSystem. +func MkdirAll(fileSystem MkdirStater, path string, perm fs.FileMode) error { + err := fileSystem.Mkdir(path, perm) + switch { + case err == nil: + // Mkdir was successful. + return nil + case errors.Is(err, fs.ErrExist): + // path already exists, but we don't know whether it's a directory or + // something else. We get this error if we try to create a subdirectory + // of a non-directory, for example if the parent directory of path is a + // file. There's a race condition here between the call to Mkdir and the + // call to Stat but we can't avoid it because there's not enough + // information in the returned error from Mkdir. We need to distinguish + // between "path already exists and is already a directory" and "path + // already exists and is not a directory". Between the call to Mkdir and + // the call to Stat path might have changed. + info, statErr := fileSystem.Stat(path) + if statErr != nil { + return statErr + } + if !info.IsDir() { + return err + } + return nil + case errors.Is(err, fs.ErrNotExist): + // Parent directory does not exist. Create the parent directory + // recursively, then try again. + parentDir := filepath.Dir(path) + if parentDir == "/" || parentDir == "." { + // We cannot create the root directory or the current directory, so + // return the original error. + return err + } + if err := MkdirAll(fileSystem, parentDir, perm); err != nil { + return err + } + return fileSystem.Mkdir(path, perm) + default: + // Some other error. + return err + } +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/osfs.go b/vendor/github.com/twpayne/go-vfs/v5/osfs.go new file mode 100644 index 0000000000..da122e4893 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/osfs.go @@ -0,0 +1,128 @@ +package vfs + +import ( + "io/fs" + "os" + "path/filepath" + "time" +) + +type osfs struct{} + +// OSFS is the FS that calls os and io functions directly. +var OSFS = &osfs{} + +// Chmod implements os.Chmod. +func (osfs) Chmod(name string, mode fs.FileMode) error { + return os.Chmod(name, mode) +} + +// Chown implements os.Chown. +func (osfs) Chown(name string, uid, gid int) error { + return os.Chown(name, uid, gid) +} + +// Chtimes implements os.Chtimes. +func (osfs) Chtimes(name string, atime, mtime time.Time) error { + return os.Chtimes(name, atime, mtime) +} + +// Create implements os.Create. +func (osfs) Create(name string) (*os.File, error) { + return os.Create(name) +} + +// Glob implements filepath.Glob. +func (osfs) Glob(pattern string) ([]string, error) { + return filepath.Glob(pattern) +} + +// Lchown implements os.Lchown. +func (osfs) Lchown(name string, uid, gid int) error { + return os.Lchown(name, uid, gid) +} + +// Link implements os.Link. +func (osfs) Link(oldname, newname string) error { + return os.Link(oldname, newname) +} + +// Lstat implements os.Lstat. +func (osfs) Lstat(name string) (fs.FileInfo, error) { + return os.Lstat(name) +} + +// Mkdir implements os.Mkdir. +func (osfs) Mkdir(name string, perm fs.FileMode) error { + return os.Mkdir(name, perm) +} + +// Open implements os.Open. +func (osfs) Open(name string) (fs.File, error) { + return os.Open(name) +} + +// OpenFile implements os.OpenFile. +func (osfs) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) { + return os.OpenFile(name, flag, perm) +} + +// PathSeparator returns os.PathSeparator. +func (osfs) PathSeparator() rune { + return os.PathSeparator +} + +// RawPath returns the path to path on the underlying filesystem. +func (osfs) RawPath(path string) (string, error) { + return path, nil +} + +// ReadDir implements os.ReadDir. +func (osfs) ReadDir(dirname string) ([]fs.DirEntry, error) { + return os.ReadDir(dirname) +} + +// ReadFile implements os.ReadFile. +func (osfs) ReadFile(name string) ([]byte, error) { + return os.ReadFile(name) +} + +// Readlink implements os.Readlink. +func (osfs) Readlink(name string) (string, error) { + return os.Readlink(name) +} + +// Remove implements os.Remove. +func (osfs) Remove(name string) error { + return os.Remove(name) +} + +// RemoveAll implements os.RemoveAll. +func (osfs) RemoveAll(name string) error { + return os.RemoveAll(name) +} + +// Rename implements os.Rename. +func (osfs) Rename(oldpath, newpath string) error { + return os.Rename(oldpath, newpath) +} + +// Stat implements os.Stat. +func (osfs) Stat(name string) (fs.FileInfo, error) { + return os.Stat(name) +} + +// Symlink implements os.Symlink. +func (osfs) Symlink(oldname, newname string) error { + return os.Symlink(oldname, newname) +} + +// Truncate implements os.Truncate. +func (osfs) Truncate(name string, size int64) error { + return os.Truncate(name, size) +} + +// WriteFile implements os.WriteFile. +func (osfs) WriteFile(filename string, data []byte, perm fs.FileMode) error { + return os.WriteFile(filename, data, perm) +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/pathfs.go b/vendor/github.com/twpayne/go-vfs/v5/pathfs.go new file mode 100644 index 0000000000..fa1073dbc2 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/pathfs.go @@ -0,0 +1,278 @@ +package vfs + +import ( + "io/fs" + "os" + "path" + "path/filepath" + "syscall" + "time" +) + +// A PathFS operates on an existing FS, but prefixes all names with a path. All +// names must be absolute paths, with the exception of symlinks, which may be +// relative. +type PathFS struct { + fileSystem FS + path string +} + +// NewPathFS returns a new *PathFS operating on fileSystem and prefixing all +// names with path. +func NewPathFS(fileSystem FS, path string) *PathFS { + return &PathFS{ + fileSystem: fileSystem, + path: filepath.ToSlash(path), + } +} + +// Chmod implements os.Chmod. +func (p *PathFS) Chmod(name string, mode fs.FileMode) error { + realName, err := p.join("Chmod", name) + if err != nil { + return err + } + return p.fileSystem.Chmod(realName, mode) +} + +// Chown implements os.Chown. +func (p *PathFS) Chown(name string, uid, gid int) error { + realName, err := p.join("Chown", name) + if err != nil { + return err + } + return p.fileSystem.Chown(realName, uid, gid) +} + +// Chtimes implements os.Chtimes. +func (p *PathFS) Chtimes(name string, atime, mtime time.Time) error { + realName, err := p.join("Chtimes", name) + if err != nil { + return err + } + return p.fileSystem.Chtimes(realName, atime, mtime) +} + +// Create implements os.Create. +func (p *PathFS) Create(name string) (*os.File, error) { + realName, err := p.join("Create", name) + if err != nil { + return nil, err + } + return p.fileSystem.Create(realName) +} + +// Glob implements filepath.Glob. +func (p *PathFS) Glob(pattern string) ([]string, error) { + realPattern, err := p.join("Glob", pattern) + if err != nil { + return nil, err + } + matches, err := p.fileSystem.Glob(realPattern) + if err != nil { + return nil, err + } + for i, match := range matches { + matches[i], err = trimPrefix(match, p.path) + if err != nil { + return nil, err + } + } + return matches, nil +} + +// Join returns p's path joined with name. +func (p *PathFS) Join(op, name string) (string, error) { + return p.join("Join", name) +} + +// Lchown implements os.Lchown. +func (p *PathFS) Lchown(name string, uid, gid int) error { + realName, err := p.join("Lchown", name) + if err != nil { + return err + } + return p.fileSystem.Lchown(realName, uid, gid) +} + +// Link implements os.Link. +func (p *PathFS) Link(oldname, newname string) error { + var realOldname string + if path.IsAbs(oldname) { + var err error + realOldname, err = p.join("Link", oldname) + if err != nil { + return err + } + } else { + realOldname = oldname + } + realNewname, err := p.join("Link", newname) + if err != nil { + return err + } + return p.fileSystem.Link(realOldname, realNewname) +} + +// Lstat implements os.Lstat. +func (p *PathFS) Lstat(name string) (fs.FileInfo, error) { + realName, err := p.join("Lstat", name) + if err != nil { + return nil, err + } + return p.fileSystem.Lstat(realName) +} + +// Mkdir implements os.Mkdir. +func (p *PathFS) Mkdir(name string, perm fs.FileMode) error { + realName, err := p.join("Mkdir", name) + if err != nil { + return err + } + return p.fileSystem.Mkdir(realName, perm) +} + +// Open implements os.Open. +func (p *PathFS) Open(name string) (fs.File, error) { + realName, err := p.join("Open", name) + if err != nil { + return nil, err + } + return p.fileSystem.Open(realName) +} + +// OpenFile implements os.OpenFile. +func (p *PathFS) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) { + realName, err := p.join("OpenFile", name) + if err != nil { + return nil, err + } + return p.fileSystem.OpenFile(realName, flag, perm) +} + +// PathSeparator implements PathSeparator. +func (p *PathFS) PathSeparator() rune { + return p.fileSystem.PathSeparator() +} + +// RawPath implements RawPath. +func (p *PathFS) RawPath(path string) (string, error) { + return p.join("RawPath", path) +} + +// ReadDir implements os.ReadDir. +func (p *PathFS) ReadDir(dirname string) ([]fs.DirEntry, error) { + realDirname, err := p.join("ReadDir", dirname) + if err != nil { + return nil, err + } + return p.fileSystem.ReadDir(realDirname) +} + +// ReadFile implements os.ReadFile. +func (p *PathFS) ReadFile(name string) ([]byte, error) { + realName, err := p.join("ReadFile", name) + if err != nil { + return nil, err + } + return p.fileSystem.ReadFile(realName) +} + +// Readlink implements os.Readlink. +func (p *PathFS) Readlink(name string) (string, error) { + realName, err := p.join("Readlink", name) + if err != nil { + return "", err + } + return p.fileSystem.Readlink(realName) +} + +// Remove implements os.Remove. +func (p *PathFS) Remove(name string) error { + realName, err := p.join("Remove", name) + if err != nil { + return err + } + return p.fileSystem.Remove(realName) +} + +// RemoveAll implements os.RemoveAll. +func (p *PathFS) RemoveAll(name string) error { + realName, err := p.join("RemoveAll", name) + if err != nil { + return err + } + return p.fileSystem.RemoveAll(realName) +} + +// Rename implements os.Rename. +func (p *PathFS) Rename(oldpath, newpath string) error { + realOldpath, err := p.join("Rename", oldpath) + if err != nil { + return err + } + realNewpath, err := p.join("Rename", newpath) + if err != nil { + return err + } + return p.fileSystem.Rename(realOldpath, realNewpath) +} + +// Stat implements os.Stat. +func (p *PathFS) Stat(name string) (fs.FileInfo, error) { + realName, err := p.join("Stat", name) + if err != nil { + return nil, err + } + return p.fileSystem.Stat(realName) +} + +// Symlink implements os.Symlink. +func (p *PathFS) Symlink(oldname, newname string) error { + var realOldname string + if path.IsAbs(oldname) { + var err error + realOldname, err = p.join("Symlink", oldname) + if err != nil { + return err + } + } else { + realOldname = oldname + } + realNewname, err := p.join("Symlink", newname) + if err != nil { + return err + } + return p.fileSystem.Symlink(realOldname, realNewname) +} + +// Truncate implements os.Truncate. +func (p *PathFS) Truncate(name string, size int64) error { + realName, err := p.join("Truncate", name) + if err != nil { + return err + } + return p.fileSystem.Truncate(realName, size) +} + +// WriteFile implements io.WriteFile. +func (p *PathFS) WriteFile(filename string, data []byte, perm fs.FileMode) error { + realFilename, err := p.join("WriteFile", filename) + if err != nil { + return err + } + return p.fileSystem.WriteFile(realFilename, data, perm) +} + +// join returns p's path joined with name. +func (p *PathFS) join(op, name string) (string, error) { + name = relativizePath(name) + if !path.IsAbs(name) { + return "", &os.PathError{ + Op: op, + Path: name, + Err: syscall.EPERM, + } + } + return filepath.Join(p.path, name), nil +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/posix.go b/vendor/github.com/twpayne/go-vfs/v5/posix.go new file mode 100644 index 0000000000..f671ebdb6d --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/posix.go @@ -0,0 +1,28 @@ +//go:build !windows +// +build !windows + +package vfs + +import ( + "strings" + "syscall" +) + +//nolint:gochecknoglobals +var ignoreErrnoInContains = map[syscall.Errno]struct{}{ + syscall.ELOOP: {}, + syscall.EMLINK: {}, + syscall.ENAMETOOLONG: {}, + syscall.ENOENT: {}, + syscall.EOVERFLOW: {}, +} + +// relativizePath, on POSIX systems, just returns path. +func relativizePath(path string) string { + return path +} + +// trimPrefix, on POSIX systems, trims prefix from path. +func trimPrefix(path, prefix string) (string, error) { + return strings.TrimPrefix(path, prefix), nil +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/readonlyfs.go b/vendor/github.com/twpayne/go-vfs/v5/readonlyfs.go new file mode 100644 index 0000000000..dcb35febb9 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/readonlyfs.go @@ -0,0 +1,148 @@ +package vfs + +import ( + "io/fs" + "os" + "syscall" + "time" +) + +// A ReadOnlyFS operates on an existing FS, but any methods that +// modify the FS return an error. +type ReadOnlyFS struct { + fileSystem FS +} + +// NewReadOnlyFS returns a new *ReadOnlyFS operating on fileSystem. +func NewReadOnlyFS(fileSystem FS) *ReadOnlyFS { + return &ReadOnlyFS{ + fileSystem: fileSystem, + } +} + +// Chmod implements os.Chmod. +func (r *ReadOnlyFS) Chmod(name string, mode fs.FileMode) error { + return permError("Chmod", name) +} + +// Chown implements os.Chown. +func (r *ReadOnlyFS) Chown(name string, uid, gid int) error { + return permError("Chown", name) +} + +// Chtimes implements os.Chtimes. +func (r *ReadOnlyFS) Chtimes(name string, atime, mtime time.Time) error { + return permError("Chtimes", name) +} + +// Create implements os.Create. +func (r *ReadOnlyFS) Create(name string) (*os.File, error) { + return nil, permError("Create", name) +} + +// Glob implements filepath.Glob. +func (r *ReadOnlyFS) Glob(pattern string) ([]string, error) { + return r.fileSystem.Glob(pattern) +} + +// Lchown implements os.Lchown. +func (r *ReadOnlyFS) Lchown(name string, uid, gid int) error { + return permError("Lchown", name) +} + +// Link implements os.Link. +func (r *ReadOnlyFS) Link(oldname, newname string) error { + return permError("Link", newname) +} + +// Lstat implements os.Lstat. +func (r *ReadOnlyFS) Lstat(name string) (fs.FileInfo, error) { + return r.fileSystem.Lstat(name) +} + +// Mkdir implements os.Mkdir. +func (r *ReadOnlyFS) Mkdir(name string, perm fs.FileMode) error { + return permError("Mkdir", name) +} + +// Open implements os.Open. +func (r *ReadOnlyFS) Open(name string) (fs.File, error) { + return r.fileSystem.Open(name) +} + +// OpenFile implements os.OpenFile. +func (r *ReadOnlyFS) OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) { + if flag&(os.O_RDONLY|os.O_WRONLY|os.O_RDWR) != os.O_RDONLY { + return nil, permError("OpenFile", name) + } + return r.fileSystem.OpenFile(name, flag, perm) +} + +// PathSeparator implements PathSeparator. +func (r *ReadOnlyFS) PathSeparator() rune { + return r.fileSystem.PathSeparator() +} + +// ReadDir implements os.ReadDir. +func (r *ReadOnlyFS) ReadDir(name string) ([]fs.DirEntry, error) { + return r.fileSystem.ReadDir(name) +} + +// ReadFile implements os.ReadFile. +func (r *ReadOnlyFS) ReadFile(name string) ([]byte, error) { + return r.fileSystem.ReadFile(name) +} + +// Readlink implements os.Readlink. +func (r *ReadOnlyFS) Readlink(name string) (string, error) { + return r.fileSystem.Readlink(name) +} + +// Remove implements os.Remove. +func (r *ReadOnlyFS) Remove(name string) error { + return permError("Remove", name) +} + +// RemoveAll implements os.RemoveAll. +func (r *ReadOnlyFS) RemoveAll(name string) error { + return permError("RemoveAll", name) +} + +// Rename implements os.Rename. +func (r *ReadOnlyFS) Rename(oldpath, newpath string) error { + return permError("Rename", oldpath) +} + +// RawPath implements RawPath. +func (r *ReadOnlyFS) RawPath(path string) (string, error) { + return r.fileSystem.RawPath(path) +} + +// Stat implements os.Stat. +func (r *ReadOnlyFS) Stat(name string) (fs.FileInfo, error) { + return r.fileSystem.Stat(name) +} + +// Symlink implements os.Symlink. +func (r *ReadOnlyFS) Symlink(oldname, newname string) error { + return permError("Symlink", newname) +} + +// Truncate implements os.Truncate. +func (r *ReadOnlyFS) Truncate(name string, size int64) error { + return permError("Truncate", name) +} + +// WriteFile implements os.WriteFile. +func (r *ReadOnlyFS) WriteFile(filename string, data []byte, perm fs.FileMode) error { + return permError("WriteFile", filename) +} + +// permError returns an *os.PathError with Err syscall.EPERM. +func permError(op, path string) error { + return &os.PathError{ + Op: op, + Path: path, + Err: syscall.EPERM, + } +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/vfs.go b/vendor/github.com/twpayne/go-vfs/v5/vfs.go new file mode 100644 index 0000000000..0904603254 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/vfs.go @@ -0,0 +1,37 @@ +// Package vfs provides an abstraction of the os and io packages that is easy to +// test. +package vfs + +import ( + "io/fs" + "os" + "time" +) + +// An FS is an abstraction over commonly-used functions in the os and io +// packages. +type FS interface { + Chmod(name string, mode fs.FileMode) error + Chown(name string, uid, git int) error + Chtimes(name string, atime, mtime time.Time) error + Create(name string) (*os.File, error) + Glob(pattern string) ([]string, error) + Lchown(name string, uid, git int) error + Link(oldname, newname string) error + Lstat(name string) (fs.FileInfo, error) + Mkdir(name string, perm fs.FileMode) error + Open(name string) (fs.File, error) + OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) + PathSeparator() rune + RawPath(name string) (string, error) + ReadDir(dirname string) ([]fs.DirEntry, error) + ReadFile(filename string) ([]byte, error) + Readlink(name string) (string, error) + Remove(name string) error + RemoveAll(name string) error + Rename(oldpath, newpath string) error + Stat(name string) (fs.FileInfo, error) + Symlink(oldname, newname string) error + Truncate(name string, size int64) error + WriteFile(filename string, data []byte, perm fs.FileMode) error +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/walk.go b/vendor/github.com/twpayne/go-vfs/v5/walk.go new file mode 100644 index 0000000000..61fa9f72ba --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/walk.go @@ -0,0 +1,85 @@ +package vfs + +//nolint:godox +// FIXME implement path/filepath.WalkDir + +import ( + "errors" + "io/fs" + "path/filepath" + "sort" +) + +// SkipDir is fs.SkipDir. +var SkipDir = fs.SkipDir + +// A LstatReadDirer implements all the functionality needed by Walk. +type LstatReadDirer interface { + Lstat(name string) (fs.FileInfo, error) + ReadDir(name string) ([]fs.DirEntry, error) +} + +type dirEntriesByName []fs.DirEntry + +func (is dirEntriesByName) Len() int { return len(is) } +func (is dirEntriesByName) Less(i, j int) bool { return is[i].Name() < is[j].Name() } +func (is dirEntriesByName) Swap(i, j int) { is[i], is[j] = is[j], is[i] } + +// walk recursively walks fileSystem from path. +func walk(fileSystem LstatReadDirer, path string, walkFn filepath.WalkFunc, info fs.FileInfo, err error) error { + if err != nil { + return walkFn(path, info, err) + } + err = walkFn(path, info, nil) + if !info.IsDir() { + return err + } + if errors.Is(err, fs.SkipDir) { + return nil + } + dirEntries, err := fileSystem.ReadDir(path) + if err != nil { + switch err := walkFn(path, info, err); { + case errors.Is(err, fs.SkipDir): + return nil + case err != nil: + return err + } + } + sort.Sort(dirEntriesByName(dirEntries)) + for _, dirEntry := range dirEntries { + name := dirEntry.Name() + if name == "." || name == ".." { + continue + } + path := filepath.Join(path, dirEntry.Name()) + info, err := dirEntry.Info() + if err != nil { + switch err := walkFn(path, info, err); { + case errors.Is(err, fs.SkipDir) && (info == nil || info.IsDir()): + continue + case err != nil: + return err + } + } + if err := walk(fileSystem, path, walkFn, info, nil); err != nil { + return err + } + } + return nil +} + +// Walk is the equivalent of filepath.Walk but operates on fileSystem. Entries +// are returned in lexicographical order. +func Walk(fileSystem LstatReadDirer, path string, walkFn filepath.WalkFunc) error { + info, err := fileSystem.Lstat(path) + return walk(fileSystem, path, walkFn, info, err) +} + +// WalkSlash is the equivalent of Walk but all paths are converted to use +// forward slashes with filepath.ToSlash. +func WalkSlash(fileSystem LstatReadDirer, path string, walkFn filepath.WalkFunc) error { + return Walk(fileSystem, path, func(path string, info fs.FileInfo, err error) error { + return walkFn(filepath.ToSlash(path), info, err) + }) +} diff --git a/vendor/github.com/twpayne/go-vfs/v5/windows.go b/vendor/github.com/twpayne/go-vfs/v5/windows.go new file mode 100644 index 0000000000..6bbcc871a5 --- /dev/null +++ b/vendor/github.com/twpayne/go-vfs/v5/windows.go @@ -0,0 +1,43 @@ +//go:build windows +// +build windows + +package vfs + +import ( + "path/filepath" + "strings" + "syscall" + + "golang.org/x/sys/windows" +) + +var ignoreErrnoInContains = map[syscall.Errno]struct{}{ + syscall.ELOOP: {}, + syscall.EMLINK: {}, + syscall.ENAMETOOLONG: {}, + syscall.ENOENT: {}, + syscall.EOVERFLOW: {}, + windows.ERROR_CANT_RESOLVE_FILENAME: {}, +} + +// relativizePath, on Windows, strips any leading volume name from path. Since +// this is used to prepare paths to have the prefix prepended, returned values +// use slashes instead of backslashes. +func relativizePath(path string) string { + if volumeName := filepath.VolumeName(path); volumeName != "" { + path = path[len(volumeName):] + } + return filepath.ToSlash(path) +} + +// trimPrefix, on Windows, trims prefix from path and returns an absolute path. +// prefix must be a /-separated path. Since this is used to prepare results to +// be returned to the calling client, returned values use backslashes instead of +// slashes +func trimPrefix(path, prefix string) (string, error) { + trimmedPath, err := filepath.Abs(strings.TrimPrefix(filepath.ToSlash(path), prefix)) + if err != nil { + return "", err + } + return filepath.FromSlash(trimmedPath), nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index b45ca39e88..5e044581ea 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1043,6 +1043,9 @@ github.com/subosito/gotenv # github.com/toqueteos/webbrowser v1.2.0 ## explicit; go 1.12 github.com/toqueteos/webbrowser +# github.com/twpayne/go-vfs/v5 v5.0.4 +## explicit; go 1.21 +github.com/twpayne/go-vfs/v5 # github.com/vbatts/tar-split v0.11.5 ## explicit; go 1.17 github.com/vbatts/tar-split/archive/tar