Skip to content

[FUTURE] [EXP] filesystem package #4240

New issue

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

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

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ linters:
- revive
# Gocritic
- gocritic
- forbidigo

# 3. We used to use these, but have now removed them

Expand All @@ -41,6 +42,10 @@ linters:
# - nakedret

settings:
forbidigo:
forbid:
- pattern: ^os\.WriteFile.*$
msg: os.WriteFile is neither atomic nor durable - use nerdctl filesystem.WriteFile instead
staticcheck:
checks:
# Below is the default set
Expand Down
4 changes: 2 additions & 2 deletions cmd/nerdctl/compose/compose_up_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package compose
import (
"fmt"
"io"
"os"
"strings"
"testing"
"time"
Expand All @@ -32,6 +31,7 @@ import (

"github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers"
"github.com/containerd/nerdctl/v2/pkg/composer/serviceparser"
"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil"
Expand Down Expand Up @@ -503,7 +503,7 @@ func TestComposeUpProfile(t *testing.T) {
// write the env.common file to tmpdir
tmpDir := t.TempDir()
envFilePath := fmt.Sprintf("%s/env.common", tmpDir)
err := os.WriteFile(envFilePath, []byte("TEST_ENV_INJECTION=WORKS\n"), 0644)
err := filesystem.WriteFile(envFilePath, []byte("TEST_ENV_INJECTION=WORKS\n"), 0644)
assert.NilError(t, err)

dockerComposeYAML := fmt.Sprintf(`
Expand Down
3 changes: 2 additions & 1 deletion cmd/nerdctl/container/container_cp_acid_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"gotest.tools/v3/icmd"

"github.com/containerd/nerdctl/v2/pkg/containerutil"
"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
Expand Down Expand Up @@ -70,7 +71,7 @@ func TestCopyAcid(t *testing.T) {
base.Cmd("exec", roContainer, "sh", "-euxc", "cd /vol2/dir2/rw; ln -s ../../../ relativelinktoroot").AssertOK()
base.Cmd("exec", roContainer, "sh", "-euxc", "cd /vol2/dir2/rw; ln -s / absolutelinktoroot").AssertOK()
// Create file on the host
err := os.WriteFile(sourceFile, sourceFileContent, filePerm)
err := filesystem.WriteFile(sourceFile, sourceFileContent, filePerm)
assert.NilError(t, err)
}

Expand Down
19 changes: 10 additions & 9 deletions cmd/nerdctl/container/container_cp_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"gotest.tools/v3/icmd"

"github.com/containerd/nerdctl/v2/pkg/containerutil"
"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
Expand Down Expand Up @@ -453,7 +454,7 @@ func TestCopyFromContainer(t *testing.T) {
ExitCode: 0,
},
setup: func(base *testutil.Base, container string, destPath string) {
err := os.WriteFile(destPath, []byte(""), filePerm)
err := filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand All @@ -464,7 +465,7 @@ func TestCopyFromContainer(t *testing.T) {
ExitCode: 0,
},
setup: func(base *testutil.Base, container string, destPath string) {
err := os.WriteFile(destPath, []byte(""), filePerm)
err := filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand All @@ -476,7 +477,7 @@ func TestCopyFromContainer(t *testing.T) {
Err: containerutil.ErrDestinationIsNotADir.Error(),
},
setup: func(base *testutil.Base, container string, destPath string) {
err := os.WriteFile(destPath, []byte(""), filePerm)
err := filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand All @@ -488,7 +489,7 @@ func TestCopyFromContainer(t *testing.T) {
Err: containerutil.ErrDestinationIsNotADir.Error(),
},
setup: func(base *testutil.Base, container string, destPath string) {
err := os.WriteFile(destPath, []byte(""), filePerm)
err := filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand Down Expand Up @@ -588,7 +589,7 @@ func TestCopyFromContainer(t *testing.T) {
setup: func(base *testutil.Base, container string, destPath string) {
err := os.MkdirAll(filepath.Dir(destPath), dirPerm)
assert.NilError(t, err)
err = os.WriteFile(destPath, []byte(""), filePerm)
err = filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand All @@ -602,7 +603,7 @@ func TestCopyFromContainer(t *testing.T) {
setup: func(base *testutil.Base, container string, destPath string) {
err := os.MkdirAll(filepath.Dir(destPath), dirPerm)
assert.NilError(t, err)
err = os.WriteFile(destPath, []byte(""), filePerm)
err = filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand All @@ -616,7 +617,7 @@ func TestCopyFromContainer(t *testing.T) {
setup: func(base *testutil.Base, container string, destPath string) {
err := os.MkdirAll(filepath.Dir(destPath), dirPerm)
assert.NilError(t, err)
err = os.WriteFile(destPath, []byte(""), filePerm)
err = filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand All @@ -630,7 +631,7 @@ func TestCopyFromContainer(t *testing.T) {
setup: func(base *testutil.Base, container string, destPath string) {
err := os.MkdirAll(filepath.Dir(destPath), dirPerm)
assert.NilError(t, err)
err = os.WriteFile(destPath, []byte(""), filePerm)
err = filesystem.WriteFile(destPath, []byte(""), filePerm)
assert.NilError(t, err)
},
},
Expand Down Expand Up @@ -838,7 +839,7 @@ func cpTestHelper(t *testing.T, tg *testgroup) {
// Create file on the host
err := os.MkdirAll(filepath.Dir(sourceFile), dirPerm)
assert.NilError(t, err)
err = os.WriteFile(sourceFile, sourceFileContent, filePerm)
err = filesystem.WriteFile(sourceFile, sourceFileContent, filePerm)
assert.NilError(t, err)
}

Expand Down
3 changes: 2 additions & 1 deletion cmd/nerdctl/container/container_inspect_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/containerd/nerdctl/mod/tigron/expect"
"github.com/containerd/nerdctl/mod/tigron/test"

"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/infoutil"
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
"github.com/containerd/nerdctl/v2/pkg/labels"
Expand Down Expand Up @@ -535,7 +536,7 @@ RUN groupadd -r test && useradd -r -g test test
USER test
`, testutil.UbuntuImage)

err := os.WriteFile(filepath.Join(data.Temp().Path(), "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(data.Temp().Path(), "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)

helpers.Ensure("build", "-t", data.Identifier(), data.Temp().Path())
Expand Down
3 changes: 2 additions & 1 deletion cmd/nerdctl/container/container_run_cgroup_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/containerd/nerdctl/mod/tigron/test"

"github.com/containerd/nerdctl/v2/pkg/cmd/container"
"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
Expand Down Expand Up @@ -241,7 +242,7 @@ func TestRunDevice(t *testing.T) {
assert.NilError(t, err)
t.Logf("lo[%d] = %+v", i, lo[i])
loContent := fmt.Sprintf("lo%d-content", i)
assert.NilError(t, os.WriteFile(lo[i].Device, []byte(loContent), 0o700))
assert.NilError(t, filesystem.WriteFile(lo[i].Device, []byte(loContent), 0o700))
data.Labels().Set("loContent"+strconv.Itoa(i), loContent)
}

Expand Down
7 changes: 4 additions & 3 deletions cmd/nerdctl/container/container_run_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/containerd/nerdctl/mod/tigron/test"

"github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers"
"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
"github.com/containerd/nerdctl/v2/pkg/strutil"
"github.com/containerd/nerdctl/v2/pkg/testutil"
Expand Down Expand Up @@ -188,7 +189,7 @@ func TestRunIpcHost(t *testing.T) {
base := testutil.NewBase(t)
testFilePath := filepath.Join("/dev/shm",
fmt.Sprintf("%s-%d-%s", testutil.Identifier(t), os.Geteuid(), base.Target))
err := os.WriteFile(testFilePath, []byte(""), 0644)
err := filesystem.WriteFile(testFilePath, []byte(""), 0644)
assert.NilError(base.T, err)
defer os.Remove(testFilePath)

Expand Down Expand Up @@ -691,7 +692,7 @@ func TestRunDeviceCDIWithNerdctlConfig(t *testing.T) {
writeTestCDISpec(t, cdiSpecDir)

tomlPath := filepath.Join(t.TempDir(), "nerdctl.toml")
err := os.WriteFile(tomlPath, []byte(fmt.Sprintf(`
err := filesystem.WriteFile(tomlPath, []byte(fmt.Sprintf(`
cdi_spec_dirs = ["%s"]
`, cdiSpecDir)), 0400)
assert.NilError(t, err)
Expand Down Expand Up @@ -719,6 +720,6 @@ devices:
err := os.MkdirAll(cdiSpecDir, 0700)
assert.NilError(t, err)
cdiSpecPath := filepath.Join(cdiSpecDir, "vendor1.yaml")
err = os.WriteFile(cdiSpecPath, []byte(testCDIVendor1), 0400)
err = filesystem.WriteFile(cdiSpecPath, []byte(testCDIVendor1), 0400)
assert.NilError(t, err)
}
4 changes: 3 additions & 1 deletion cmd/nerdctl/helpers/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ import (
"testing"

"gotest.tools/v3/assert"

"github.com/containerd/nerdctl/v2/pkg/filesystem"
)

func CreateBuildContext(t *testing.T, dockerfile string) string {
tmpDir := t.TempDir()
err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644)
err := filesystem.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644)
assert.NilError(t, err)
return tmpDir
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/nerdctl/image/image_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package image
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"slices"
Expand All @@ -32,6 +31,7 @@ import (
"github.com/containerd/nerdctl/mod/tigron/require"
"github.com/containerd/nerdctl/mod/tigron/test"

"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/tabutil"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
Expand Down Expand Up @@ -149,7 +149,7 @@ LABEL version=0.1
RUN echo "actually creating a layer so that docker sets the createdAt time"
`, testutil.CommonImage)
buildCtx := data.Temp().Path()
err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)
data.Labels().Set("buildCtx", buildCtx)
},
Expand Down Expand Up @@ -298,7 +298,7 @@ func TestImagesFilterDangling(t *testing.T) {
CMD ["echo", "nerdctl-build-notag-string"]
`, testutil.CommonImage)
buildCtx := data.Temp().Path()
err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)
data.Labels().Set("buildCtx", buildCtx)
},
Expand Down
10 changes: 5 additions & 5 deletions cmd/nerdctl/image/image_prune_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package image

import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
Expand All @@ -30,6 +29,7 @@ import (
"github.com/containerd/nerdctl/mod/tigron/require"
"github.com/containerd/nerdctl/mod/tigron/test"

"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
)
Expand Down Expand Up @@ -72,7 +72,7 @@ func TestImagePrune(t *testing.T) {
`, testutil.CommonImage)

buildCtx := data.Temp().Path()
err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)
helpers.Ensure("build", buildCtx)
// After we rebuild with tag, docker will no longer show the <none> version from above
Expand Down Expand Up @@ -120,7 +120,7 @@ func TestImagePrune(t *testing.T) {
`, testutil.CommonImage)

buildCtx := data.Temp().Path()
err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)
helpers.Ensure("build", buildCtx)
helpers.Ensure("build", "-t", identifier, buildCtx)
Expand Down Expand Up @@ -164,7 +164,7 @@ CMD ["echo", "nerdctl-test-image-prune-filter-label"]
LABEL foo=bar
LABEL version=0.1`, testutil.CommonImage)
buildCtx := data.Temp().Path()
err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)
helpers.Ensure("build", "-t", data.Identifier(), buildCtx)
imgList := helpers.Capture("images")
Expand Down Expand Up @@ -204,7 +204,7 @@ LABEL version=0.1`, testutil.CommonImage)
RUN echo "Anything, so that we create actual content for docker to set the current time for CreatedAt"
CMD ["echo", "nerdctl-test-image-prune-until"]`, testutil.CommonImage)
buildCtx := data.Temp().Path()
err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)
helpers.Ensure("build", "-t", data.Identifier(), buildCtx)
imgList := helpers.Capture("images")
Expand Down
3 changes: 2 additions & 1 deletion cmd/nerdctl/ipfs/ipfs_registry_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/containerd/nerdctl/mod/tigron/require"
"github.com/containerd/nerdctl/mod/tigron/test"

"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
)
Expand Down Expand Up @@ -138,7 +139,7 @@ CMD ["echo", "nerdctl-build-test-string"]
`, data.Labels().Get(ipfsImageURLKey))

buildCtx := data.Temp().Path()
err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
err := filesystem.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600)
assert.NilError(helpers.T(), err)

helpers.Ensure("build", "-t", data.Identifier("built-image"), buildCtx)
Expand Down
6 changes: 3 additions & 3 deletions cmd/nerdctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ import (
"github.com/containerd/nerdctl/v2/pkg/config"
ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults"
"github.com/containerd/nerdctl/v2/pkg/errutil"
"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/logging"
"github.com/containerd/nerdctl/v2/pkg/rootlessutil"
"github.com/containerd/nerdctl/v2/pkg/store"
"github.com/containerd/nerdctl/v2/pkg/version"
)

Expand Down Expand Up @@ -248,12 +248,12 @@ Config file ($NERDCTL_TOML): %s
}

// Since we store containers' stateful information on the filesystem per namespace, we need namespaces to be
// valid, safe path segments. This is enforced by store.ValidatePathComponent.
// valid, safe path segments.
// Note that the container runtime will further enforce additional restrictions on namespace names
// (containerd treats namespaces as valid identifiers - eg: alphanumericals + dash, starting with a letter)
// See https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#path-segment-names for
// considerations about path segments identifiers.
if err = store.ValidatePathComponent(globalOptions.Namespace); err != nil {
if err = filesystem.ValidatePathComponent(globalOptions.Namespace); err != nil {
return err
}
if appNeedsRootlessParentMain(cmd, args) {
Expand Down
3 changes: 2 additions & 1 deletion cmd/nerdctl/volume/volume_inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ import (
"github.com/containerd/nerdctl/mod/tigron/test"
"github.com/containerd/nerdctl/mod/tigron/tig"

"github.com/containerd/nerdctl/v2/pkg/filesystem"
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/native"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
)

func createFileWithSize(mountPoint string, size int64) error {
token := make([]byte, size)
_, _ = rand.Read(token)
err := os.WriteFile(filepath.Join(mountPoint, "test-file"), token, 0644)
err := filesystem.WriteFile(filepath.Join(mountPoint, "test-file"), token, 0644)
return err
}

Expand Down
2 changes: 1 addition & 1 deletion docs/dev/auditing_dockerfile.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ On a warm cache, it is still over 150MB and 30+ seconds.
In and of itself, this is hard to reduce, as we need these...

Actions:
- [ ] we could cache the module download location to reduce round-trips on modules that are shared accross
- [ ] we could cache the module download location to reduce round-trips on modules that are shared across
different projects
- [ ] we are likely installing nerdctl modules six times - (once per architecture during the build phase, then once per
ubuntu version and architecture during the tests runs (this is not even accounted for in the audit above)) - it should
Expand Down
2 changes: 1 addition & 1 deletion docs/dev/store.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ containers can be named the same), etc.
However, storing data on the filesystem in a reliable way comes with challenges:
- incomplete writes may happen (because of a system restart, or an application crash), leaving important structured files
in a broken state
- concurrent writes, or reading while writing would obviously be a problem as well, be it accross goroutines, or between
- concurrent writes, or reading while writing would obviously be a problem as well, be it across goroutines, or between
concurrent executions of the nerdctl binary, or embedded in a third-party application that does concurrently access resources

The `pkg/store` package does provide a "storage" abstraction that takes care of these issues, generally providing
Expand Down
Loading
Loading