diff --git a/docs/reference/europa/dagger/engine.md b/docs/reference/europa/dagger/engine.md index 0db8b5c5..05f964ea 100644 --- a/docs/reference/europa/dagger/engine.md +++ b/docs/reference/europa/dagger/engine.md @@ -152,7 +152,7 @@ _No output._ ## engine.#Mkdir -Create a directory +Create one or multiple directory in a container ### engine.#Mkdir Inputs @@ -212,8 +212,6 @@ _No output._ ## engine.#ReadFile -Read a file from a filesystem tree - ### engine.#ReadFile Inputs _No input._ diff --git a/docs/reference/europa/dagger/engine/README.md b/docs/reference/europa/dagger/engine/README.md index 4e75f679..ca890581 100644 --- a/docs/reference/europa/dagger/engine/README.md +++ b/docs/reference/europa/dagger/engine/README.md @@ -56,6 +56,18 @@ _No input._ _No output._ +## engine.#Mkdir + +Create one or multiple directory in a container + +### engine.#Mkdir Inputs + +_No input._ + +### engine.#Mkdir Outputs + +_No output._ + ## engine.#Mount A transient filesystem mount. diff --git a/docs/reference/europa/dagger/engine/spec/engine.md b/docs/reference/europa/dagger/engine/spec/engine.md index df6f2351..2073079f 100644 --- a/docs/reference/europa/dagger/engine/spec/engine.md +++ b/docs/reference/europa/dagger/engine/spec/engine.md @@ -150,7 +150,7 @@ _No output._ ## engine.#Mkdir -Create a directory +Create one or multiple directory in a container Create a directory ### engine.#Mkdir Inputs diff --git a/plan/task/mkdir.go b/plan/task/mkdir.go new file mode 100644 index 00000000..cf6999bb --- /dev/null +++ b/plan/task/mkdir.go @@ -0,0 +1,81 @@ +package task + +import ( + "context" + "io/fs" + + "cuelang.org/go/cue" + "github.com/moby/buildkit/client/llb" + "go.dagger.io/dagger/compiler" + "go.dagger.io/dagger/plancontext" + "go.dagger.io/dagger/solver" +) + +func init() { + Register("Mkdir", func() Task { return &mkdirTask{} }) +} + +type mkdirTask struct { +} + +func (t *mkdirTask) Run(ctx context.Context, pctx *plancontext.Context, s solver.Solver, v *compiler.Value) (*compiler.Value, error) { + path, err := v.Lookup("path").String() + if err != nil { + return nil, err + } + + // Mode (int) + mode, err := v.Lookup("mode").Int64() + if err != nil { + return nil, err + } + + // Retrieve options + mkdirOpts := []llb.MkdirOption{} + var opts struct { + Parents bool + } + + if err := v.Decode(&opts); err != nil { + return nil, err + } + + if opts.Parents { + mkdirOpts = append(mkdirOpts, llb.WithParents(true)) + } + + // Retrieve input Filesystem + input, err := pctx.FS.FromValue(v.Lookup("input")) + if err != nil { + return nil, err + } + + // Retrieve input llb state + inputState, err := input.Result().ToState() + if err != nil { + return nil, err + } + + // Add Mkdir operation on input llb state + outputState := inputState.File( + llb.Mkdir(path, fs.FileMode(mode), mkdirOpts...), + withCustomName(v, "Mkdir %s", path), + ) + + // Compute state + result, err := s.Solve(ctx, outputState, pctx.Platform.Get()) + if err != nil { + return nil, err + } + + // Retrieve result result filesystem + outputFS := pctx.FS.New(result) + + // Init output + output := compiler.NewValue() + + if err := output.FillPath(cue.ParsePath("output"), outputFS.MarshalCUE()); err != nil { + return nil, err + } + return output, nil +} diff --git a/stdlib/europa/dagger/engine/fs.cue b/stdlib/europa/dagger/engine/fs.cue index c564fe95..215d4cbe 100644 --- a/stdlib/europa/dagger/engine/fs.cue +++ b/stdlib/europa/dagger/engine/fs.cue @@ -1,6 +1,26 @@ package engine -// Read a file from a filesystem tree +// Create one or multiple directory in a container +#Mkdir: { + $dagger: task: _name: "Mkdir" + + // Container filesystem + input: #FS + + // Path of the directory to create + // It can be nested (e.g : "/foo" or "/foo/bar") + path: string + + // Permissions to set + mode: *0o755 | int + + // If set, it creates parents' directory if they do not exist + parents: *true | false + + // Modified filesystem + output: #FS +} + #ReadFile: { $dagger: task: _name: "ReadFile" @@ -40,23 +60,6 @@ package engine output: #FS } -// Create a directory -#Mkdir: { - @dagger(notimplemented) - $dagger: task: _name: "Mkdir" - - input: #FS - - // Path of the directory - path: string - // FIXME: permissions? - mode: int - // Create parent directories as needed? - parents: *true | false - - output: #FS -} - // Copy files from one FS tree to another #Copy: { $dagger: task: _name: "Copy" diff --git a/tests/tasks.bats b/tests/tasks.bats index 79d7cc4a..a8080d5d 100644 --- a/tests/tasks.bats +++ b/tests/tasks.bats @@ -56,7 +56,23 @@ setup() { cd "$TESTDIR"/tasks/copy "$DAGGER" --europa up ./copy_exec.cue "$DAGGER" --europa up ./copy_file.cue - + run "$DAGGER" --europa up ./copy_exec_invalid.cue assert_failure } + + +@test "task: #Mkdir" { + # Make directory + cd "$TESTDIR"/tasks/mkdir + "$DAGGER" --europa up ./mkdir.cue + + # Create parents + cd "$TESTDIR"/tasks/mkdir + "$DAGGER" --europa up ./mkdir_parents.cue + + # Disable parents creation + cd "$TESTDIR"/tasks/mkdir + run "$DAGGER" --europa up ./mkdir_failure_disable_parents.cue + assert_failure +} \ No newline at end of file diff --git a/tests/tasks/mkdir/cue.mod/module.cue b/tests/tasks/mkdir/cue.mod/module.cue new file mode 100644 index 00000000..f8af9cef --- /dev/null +++ b/tests/tasks/mkdir/cue.mod/module.cue @@ -0,0 +1 @@ +module: "" diff --git a/tests/tasks/mkdir/cue.mod/pkg/.gitignore b/tests/tasks/mkdir/cue.mod/pkg/.gitignore new file mode 100644 index 00000000..2d4dc1ae --- /dev/null +++ b/tests/tasks/mkdir/cue.mod/pkg/.gitignore @@ -0,0 +1,3 @@ +# generated by dagger +alpha.dagger.io +dagger.lock diff --git a/tests/tasks/mkdir/mkdir.cue b/tests/tasks/mkdir/mkdir.cue new file mode 100644 index 00000000..5305bab8 --- /dev/null +++ b/tests/tasks/mkdir/mkdir.cue @@ -0,0 +1,33 @@ +package main + +import ( + "alpha.dagger.io/europa/dagger/engine" +) + +engine.#Plan & { + actions: { + image: engine.#Pull & { + source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" + } + + mkdir: engine.#Mkdir & { + input: image.output + path: "/test" + } + + writeChecker: engine.#WriteFile & { + input: mkdir.output + path: "/test/foo" + contents: "bar" + mode: 700 + } + + readChecker: engine.#ReadFile & { + input: writeChecker.output + path: "/test/foo" + } & { + // assert result + contents: "bar" + } + } +} diff --git a/tests/tasks/mkdir/mkdir_failure_disable_parents.cue b/tests/tasks/mkdir/mkdir_failure_disable_parents.cue new file mode 100644 index 00000000..8888400d --- /dev/null +++ b/tests/tasks/mkdir/mkdir_failure_disable_parents.cue @@ -0,0 +1,34 @@ +package main + +import ( + "alpha.dagger.io/europa/dagger/engine" +) + +engine.#Plan & { + actions: { + image: engine.#Pull & { + source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" + } + + mkdir: engine.#Mkdir & { + input: image.output + path: "/test/baz" + parents: false + } + + writeChecker: engine.#WriteFile & { + input: mkdir.output + path: "/test/baz/foo" + contents: "bar" + mode: 700 + } + + readChecker: engine.#ReadFile & { + input: writeChecker.output + path: "/test/baz/foo" + } & { + // assert result + contents: "bar" + } + } +} diff --git a/tests/tasks/mkdir/mkdir_parents.cue b/tests/tasks/mkdir/mkdir_parents.cue new file mode 100644 index 00000000..7d642382 --- /dev/null +++ b/tests/tasks/mkdir/mkdir_parents.cue @@ -0,0 +1,33 @@ +package main + +import ( + "alpha.dagger.io/europa/dagger/engine" +) + +engine.#Plan & { + actions: { + image: engine.#Pull & { + source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" + } + + mkdir: engine.#Mkdir & { + input: image.output + path: "/test/baz" + } + + writeChecker: engine.#WriteFile & { + input: mkdir.output + path: "/test/baz/foo" + contents: "bar" + mode: 700 + } + + readChecker: engine.#ReadFile & { + input: writeChecker.output + path: "/test/baz/foo" + } & { + // assert result + contents: "bar" + } + } +}