diff --git a/cmd/dagger/cmd/do.go b/cmd/dagger/cmd/do.go new file mode 100644 index 00000000..ce081685 --- /dev/null +++ b/cmd/dagger/cmd/do.go @@ -0,0 +1,140 @@ +package cmd + +import ( + "context" + "fmt" + "os" + "strings" + "text/tabwriter" + + "cuelang.org/go/cue" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "go.dagger.io/dagger/cmd/dagger/cmd/common" + "go.dagger.io/dagger/cmd/dagger/logger" + "go.dagger.io/dagger/plan" + "go.dagger.io/dagger/solver" + "golang.org/x/term" +) + +var doCmd = &cobra.Command{ + Use: "do [OPTIONS] ACTION [SUBACTION...]", + Short: "Execute a dagger action.", + // Args: cobra.MinimumNArgs(1), + PreRun: func(cmd *cobra.Command, args []string) { + // Fix Viper bug for duplicate flags: + // https://github.com/spf13/viper/issues/233 + if err := viper.BindPFlags(cmd.Flags()); err != nil { + panic(err) + } + }, + Run: func(cmd *cobra.Command, args []string) { + if len(args) < 1 { + doHelp(cmd, nil) + return + } + + var ( + lg = logger.New() + tty *logger.TTYOutput + err error + ) + + if f := viper.GetString("log-format"); f == "tty" || f == "auto" && term.IsTerminal(int(os.Stdout.Fd())) { + tty, err = logger.NewTTYOutput(os.Stderr) + if err != nil { + lg.Fatal().Err(err).Msg("failed to initialize TTY logger") + } + tty.Start() + defer tty.Stop() + + lg = lg.Output(tty) + } + + ctx := lg.WithContext(cmd.Context()) + cl := common.NewClient(ctx) + + p, err := loadPlan(getTargetPath(args).String()) + if err != nil { + lg.Fatal().Err(err).Msg("failed to load plan") + } + + err = cl.Do(ctx, p.Context(), func(ctx context.Context, s solver.Solver) error { + _, err := p.Up(ctx, s) + if err != nil { + return err + } + + return nil + }) + + // FIXME: rework telemetry + + if err != nil { + lg.Fatal().Err(err).Msg("failed to up environment") + } + }, +} + +func loadPlan(target string) (*plan.Plan, error) { + project := viper.GetString("project") + return plan.Load(context.Background(), plan.Config{ + Args: []string{project}, + With: viper.GetStringSlice("with"), + Target: target, + Vendor: !viper.GetBool("no-vendor"), + }) +} + +func getTargetPath(args []string) cue.Path { + actionLookupArgs := []string{plan.ActionsPath} + actionLookupArgs = append(actionLookupArgs, args...) + actionLookupSelectors := []cue.Selector{} + for _, a := range actionLookupArgs { + actionLookupSelectors = append(actionLookupSelectors, cue.Str(a)) + } + return cue.MakePath(actionLookupSelectors...) +} + +func doHelp(cmd *cobra.Command, _ []string) { + w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.StripEscape) + defer w.Flush() + + p, err := loadPlan("") + if err != nil { + fmt.Printf("%s", err) + fmt.Fprintln(w, "failed to load plan") + return + } + project := viper.GetString("project") + actionLookupPath := getTargetPath(cmd.Flags().Args()) + actions := p.Action().FindByPath(actionLookupPath).Children + + fmt.Printf(`Execute a dagger action. + +%s + +Plan loaded from %s: +%s +`, cmd.UsageString(), project, "\n"+actionLookupPath.String()+":") + + // fmt.Fprintln(w, "Actions\tDescription\tPackage") + // fmt.Fprintln(w, "\t\t") + for _, a := range actions { + if !a.Hidden { + lineParts := []string{"", a.Name, strings.TrimSpace(a.Comment)} + fmt.Fprintln(w, strings.Join(lineParts, "\t")) + } + } +} + +func init() { + doCmd.Flags().StringArrayP("with", "w", []string{}, "") + doCmd.Flags().Bool("no-vendor", false, "Force up, disable inputs check") + + doCmd.SetHelpFunc(doHelp) + + if err := viper.BindPFlags(doCmd.Flags()); err != nil { + panic(err) + } +} diff --git a/cmd/dagger/cmd/root.go b/cmd/dagger/cmd/root.go index 37252ab6..570dc8e1 100644 --- a/cmd/dagger/cmd/root.go +++ b/cmd/dagger/cmd/root.go @@ -30,7 +30,7 @@ func init() { rootCmd.PersistentFlags().StringArray("cache-from", []string{}, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)") - rootCmd.PersistentFlags().String("project", "", "Specify a project directory (defaults to current)") + rootCmd.PersistentFlags().StringP("project", "p", "./", "Specify a project directory (defaults to current)") rootCmd.PersistentPreRun = func(cmd *cobra.Command, _ []string) { go checkVersion() @@ -45,6 +45,7 @@ func init() { versionCmd, docCmd, mod.Cmd, + doCmd, ) if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil { diff --git a/plan/action.go b/plan/action.go new file mode 100644 index 00000000..0cb79a23 --- /dev/null +++ b/plan/action.go @@ -0,0 +1,34 @@ +package plan + +import ( + "cuelang.org/go/cue" +) + +type Action struct { + Name string + Hidden bool + Path cue.Path + Comment string + Children []*Action + // pkg string +} + +func (a *Action) AddChild(c *Action) { + a.Children = append(a.Children, c) +} + +func (a *Action) FindByPath(path cue.Path) *Action { + queue := []*Action{a} + + for len(queue) > 0 { + nextUp := queue[0] + queue = queue[1:] + if nextUp.Path.String() == path.String() { + return nextUp + } + if len(nextUp.Children) > 0 { + queue = append(queue, nextUp.Children...) + } + } + return nil +} diff --git a/plan/plan.go b/plan/plan.go index 0354c0f0..97ee83b4 100644 --- a/plan/plan.go +++ b/plan/plan.go @@ -17,11 +17,16 @@ import ( "go.opentelemetry.io/otel" ) +const ( + ActionsPath = "actions" +) + type Plan struct { config Config context *plancontext.Context source *compiler.Value + action *Action } type Config struct { @@ -66,6 +71,8 @@ func Load(ctx context.Context, cfg Config) (*Plan, error) { source: v, } + p.fillAction() + if err := p.configPlatform(); err != nil { return nil, err } @@ -85,6 +92,10 @@ func (p *Plan) Source() *compiler.Value { return p.source } +func (p *Plan) Action() *Action { + return p.action +} + // configPlatform load the platform specified in the context // Buildkit will then run every operation using that platform // If platform is not define, context keep default platform @@ -186,6 +197,78 @@ func (p *Plan) Up(ctx context.Context, s solver.Solver) (*compiler.Value, error) } } +func (p *Plan) fillAction() { + cfg := &cueflow.Config{ + FindHiddenTasks: true, + Root: cue.ParsePath(ActionsPath), + } + + flow := cueflow.New( + cfg, + p.source.Cue(), + noOpRunner, + ) + + actions := p.source.Lookup(ActionsPath) + actionsComment := "" + for _, cg := range actions.Doc() { + actionsComment += cg.Text() + } + p.action = &Action{ + ActionsPath, + false, + actions.Path(), + actionsComment, + []*Action{}, + } + + tasks := flow.Tasks() + + for _, t := range tasks { + var q []cue.Selector + prevAction := p.action + for _, s := range t.Path().Selectors() { + q = append(q, s) + path := cue.MakePath(q...) + a := prevAction.FindByPath(path) + if a == nil { + v := p.Source().LookupPath(path) + childComment := "" + for _, cg := range v.Doc() { + childComment += cg.Text() + } + + a = &Action{ + s.String(), + s.PkgPath() != "", + path, + childComment, + []*Action{}, + } + prevAction.AddChild(a) + } + prevAction = a + } + } +} + +func noOpRunner(flowVal cue.Value) (cueflow.Runner, error) { + v := compiler.Wrap(flowVal) + _, err := task.Lookup(v) + if err != nil { + // Not a task + if err == task.ErrNotTask { + return nil, nil + } + return nil, err + } + + // Wrapper around `task.Run` that handles logging, tracing, etc. + return cueflow.RunnerFunc(func(t *cueflow.Task) error { + return nil + }), nil +} + func newRunner(pctx *plancontext.Context, s solver.Solver, computed *compiler.Value) cueflow.TaskFunc { return func(flowVal cue.Value) (cueflow.Runner, error) { v := compiler.Wrap(flowVal) diff --git a/tests/plan.bats b/tests/plan.bats index 262850d5..d356f8c1 100644 --- a/tests/plan.bats +++ b/tests/plan.bats @@ -7,154 +7,77 @@ setup() { @test "plan/hello" { # Europa loader handles the cwd differently, therefore we need to CD into the tree at or below the parent of cue.mod cd "$TESTDIR" - "$DAGGER" up ./plan/hello-europa + "$DAGGER" "do" -p ./plan/hello-europa test } @test "plan/proxy invalid schema" { cd "$TESTDIR" - run "$DAGGER" up ./plan/proxy/invalid_schema.cue + run "$DAGGER" "do" -p ./plan/proxy/invalid_schema.cue verify assert_failure } @test "plan/proxy invalid value" { cd "$TESTDIR" - run "$DAGGER" up ./plan/proxy/invalid_value.cue + run "$DAGGER" "do" -p ./plan/proxy/invalid_value.cue verify assert_failure } @test "plan/proxy incomplete unix" { cd "$TESTDIR" - run "$DAGGER" up ./plan/proxy/incomplete_unix.cue + run "$DAGGER" "do" -p ./plan/proxy/incomplete_unix.cue verify assert_failure } @test "plan/proxy incomplete service" { cd "$TESTDIR" - run "$DAGGER" up ./plan/proxy/incomplete_service.cue + run "$DAGGER" "do" -p ./plan/proxy/incomplete_service.cue verify assert_output --partial 'mount "docker" is not concrete' } @test "plan/proxy unix" { cd "$TESTDIR" - "$DAGGER" up ./plan/proxy/unix.cue + "$DAGGER" "do" -p ./plan/proxy/unix.cue verify } -@test "plan/inputs/directories exists" { +@test "plan/inputs/directories" { cd "$TESTDIR" - "$DAGGER" up ./plan/inputs/directories/exists.cue -} + "$DAGGER" "do" -p ./plan/inputs/directories/valid exists -@test "plan/inputs/directories relative directories" { - cd "$TESTDIR" - cd "$TESTDIR"/plan/inputs - - "$DAGGER" up ./directories/exists.cue -} - -@test "plan/inputs/directories not exists" { - cd "$TESTDIR" - run "$DAGGER" up ./plan/inputs/directories/not_exists.cue + run "$DAGGER" "do" -p ./plan/inputs/directories/invalid notExists assert_failure assert_output --partial 'fasdfsdfs" does not exist' -} -@test "plan/inputs/directories conflicting values" { - cd "$TESTDIR" - run "$DAGGER" up ./plan/inputs/directories/conflicting_values.cue + run "$DAGGER" "do" -p ./plan/inputs/directories/valid conflictingValues assert_failure assert_output --partial 'conflicting values "local directory" and "local dfsadf"' } @test "plan/inputs/secrets" { cd "$TESTDIR" - "$DAGGER" up ./plan/inputs/secrets/exec.cue - "$DAGGER" up ./plan/inputs/secrets/exec_relative.cue + "$DAGGER" "do" -p ./plan/inputs/secrets test valid + "$DAGGER" "do" -p ./plan/inputs/secrets test relative - run "$DAGGER" up ./plan/inputs/secrets/invalid_command.cue + run "$DAGGER" "do" -p ./plan/inputs/secrets test badCommand assert_failure assert_output --partial 'failed: exec: "rtyet": executable file not found' - run "$DAGGER" up ./plan/inputs/secrets/invalid_command_options.cue + run "$DAGGER" "do" -p ./plan/inputs/secrets test badArgs assert_failure assert_output --partial 'option' } @test "plan/with" { cd "$TESTDIR" - "$DAGGER" up --with 'inputs: params: foo:"bar"' ./plan/with/params.cue - "$DAGGER" up --with 'actions: verify: env: FOO: "bar"' ./plan/with/actions.cue + "$DAGGER" "do" --with 'inputs: params: foo:"bar"' -p ./plan/with test params + "$DAGGER" "do" --with 'actions: test: direct: env: FOO: "bar"' -p ./plan/with test direct - run "$DAGGER" up --with 'inputs: params: foo:1' ./plan/with/params.cue + run "$DAGGER" "do" --with 'inputs: params: foo:1' -p ./plan/with test params assert_failure assert_output --partial "conflicting values string and 1" - run "$DAGGER" up ./plan/with/params.cue + run "$DAGGER" "do" -p ./plan/with test params assert_failure - assert_output --partial "actions.verify.env.FOO: non-concrete value string" -} - -@test "plan/outputs/directories" { - cd "$TESTDIR"/plan/outputs/directories - - "$DAGGER" up ./outputs.cue - assert [ -f "./out/test_outputs" ] - - rm -f "./out/test_outputs" -} - -@test "plan/outputs/directories relative paths" { - cd "$TESTDIR"/plan - - "$DAGGER" up ./outputs/directories/relative.cue - assert [ -f "./outputs/directories/out/test_relative" ] - - rm -f "./outputs/directories/out/test_relative" -} - -@test "plan/outputs/files normal usage" { - cd "$TESTDIR"/plan/outputs/files - - "$DAGGER" up ./usage.cue - - run ./test_usage - assert_output "Hello World!" - - run ls -l "./test_usage" - assert_output --partial "-rwxr-x---" - - rm -f "./test_usage" -} - -@test "plan/outputs/files relative path" { - cd "$TESTDIR"/plan - - "$DAGGER" up ./outputs/files/relative.cue - assert [ -f "./outputs/files/test_relative" ] - - rm -f "./outputs/files/test_relative" -} - -@test "plan/outputs/files default permissions" { - cd "$TESTDIR"/plan/outputs/files - - "$DAGGER" up ./default_permissions.cue - - run ls -l "./test_default_permissions" - assert_output --partial "-rw-r--r--" - - rm -f "./test_default_permissions" -} - -@test "plan/outputs/files no contents" { - cd "$TESTDIR"/plan/outputs/files - - run "$DAGGER" up ./no_contents.cue - assert_failure - assert_output --partial "contents is not set" - - assert [ ! -f "./test_no_contents" ] - - rm -f "./test_no_contents" + assert_output --partial "actions.test.params.env.FOO: non-concrete value string" } @test "plan/platform" { diff --git a/tests/plan/do/actions.cue b/tests/plan/do/actions.cue new file mode 100644 index 00000000..6a697f8d --- /dev/null +++ b/tests/plan/do/actions.cue @@ -0,0 +1,74 @@ +package main + +import ( + "dagger.io/dagger" + "universe.dagger.io/yarn" + "universe.dagger.io/docker" +) + +dagger.#Plan & { + + // All the things! + actions: { + + // Run core integration tests + "core-integration": _ + + // Format all cue files + cuefmt: _ + + // Lint and format all cue files + cuelint: _ + + // Build a debug version of the dev dagger binary + "dagger-debug": _ + + // Test docs + "doc-test": _ + + // Generate docs + docs: _ + + // Generate & lint docs + docslint: _ + + // Run Europa universe tests + "europa-universe-test": _ + + // Go lint + golint: _ + + // Show how to get started & what targets are available + help: _ + + // Install a dev dagger binary + install: _ + + // Run all integration tests + integration: _ + + // Lint everything + lint: _ + + // Run shellcheck + shellcheck: _ + + // Run all tests + test: _ + + // Find all TODO items + todo: _ + + // Run universe tests + "universe-test": _ + + // Build, test and deploy frontend web client + frontend: { + // Build via yarn + build: yarn.#Build + + // Test via headless browser + test: docker.#Run + } + } +} diff --git a/tests/plan/hello-europa/main.cue b/tests/plan/hello-europa/main.cue index 0ae85271..37bb61cf 100644 --- a/tests/plan/hello-europa/main.cue +++ b/tests/plan/hello-europa/main.cue @@ -6,18 +6,18 @@ import ( ) dagger.#Plan & { - actions: { - image: dagger.#Pull & { + actions: test: { + _image: dagger.#Pull & { source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" } - exec: dagger.#Exec & { - input: image.output + _exec: dagger.#Exec & { + input: _image.output args: ["sh", "-c", "echo -n Hello Europa > /out.txt"] } - verify: dagger.#ReadFile & { - input: exec.output + _verify: dagger.#ReadFile & { + input: _exec.output path: "/out.txt" } & { // assert result diff --git a/tests/plan/inputs/directories/conflicting_values.cue b/tests/plan/inputs/directories/conflicting_values.cue deleted file mode 100644 index 46da76e6..00000000 --- a/tests/plan/inputs/directories/conflicting_values.cue +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - inputs: directories: test: path: "." - actions: verify: dagger.#ReadFile & { - input: inputs.directories.test.contents - path: "test.txt" - } & { - contents: "local dfsadf" // should fail with conflicting values - } -} diff --git a/tests/plan/inputs/directories/exists.cue b/tests/plan/inputs/directories/exists.cue deleted file mode 100644 index 0b061e48..00000000 --- a/tests/plan/inputs/directories/exists.cue +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - inputs: directories: test: path: "." - actions: verify: dagger.#ReadFile & { - input: inputs.directories.test.contents - path: "test.txt" - } & { - contents: "local directory" - } -} diff --git a/tests/plan/inputs/directories/invalid/invalid.cue b/tests/plan/inputs/directories/invalid/invalid.cue new file mode 100644 index 00000000..00facedf --- /dev/null +++ b/tests/plan/inputs/directories/invalid/invalid.cue @@ -0,0 +1,3 @@ +package main + +inputs: directories: test: path: "./fasdfsdfs" diff --git a/tests/plan/inputs/directories/main.cue b/tests/plan/inputs/directories/main.cue new file mode 100644 index 00000000..ce485da4 --- /dev/null +++ b/tests/plan/inputs/directories/main.cue @@ -0,0 +1,31 @@ +package main + +import ( + "dagger.io/dagger" +) + +dagger.#Plan & { + inputs: directories: test: path: string + + actions: { + _readFile: dagger.#ReadFile & { + input: inputs.directories.test.contents + path: "test.txt" + } + + // Test that file exists and contains correct content + exists: _readFile & { + contents: "local directory" + } + + // Test that file does NOT exist + notExists: _readFile & { + contents: "local directory" + } + + // Test that file exists and contains conflicting content + conflictingValues: _readFile & { + contents: "local dfsadf" + } + } +} diff --git a/tests/plan/inputs/directories/not_exists.cue b/tests/plan/inputs/directories/not_exists.cue deleted file mode 100644 index 02eb1b97..00000000 --- a/tests/plan/inputs/directories/not_exists.cue +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - // should fail because path does not exist locally - inputs: directories: test: path: "./fasdfsdfs" - actions: verify: dagger.#ReadFile & { - input: inputs.directories.test.contents - path: "test.txt" - } & { - contents: "local directory" - } -} diff --git a/tests/plan/inputs/directories/test.txt b/tests/plan/inputs/directories/valid/test.txt similarity index 100% rename from tests/plan/inputs/directories/test.txt rename to tests/plan/inputs/directories/valid/test.txt diff --git a/tests/plan/inputs/directories/valid/valid.cue b/tests/plan/inputs/directories/valid/valid.cue new file mode 100644 index 00000000..cc876590 --- /dev/null +++ b/tests/plan/inputs/directories/valid/valid.cue @@ -0,0 +1,3 @@ +package main + +inputs: directories: test: path: "." diff --git a/tests/plan/inputs/secrets/exec.cue b/tests/plan/inputs/secrets/exec.cue deleted file mode 100644 index c083f489..00000000 --- a/tests/plan/inputs/secrets/exec.cue +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - inputs: secrets: echo: command: { - name: "echo" - args: ["hello europa"] - } - - actions: { - - image: dagger.#Pull & { - source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" - } - - verify: dagger.#Exec & { - input: image.output - mounts: secret: { - dest: "/run/secrets/test" - contents: inputs.secrets.echo.contents - } - args: [ - "sh", "-c", - #""" - test "$(cat /run/secrets/test)" = "hello europa" - ls -l /run/secrets/test | grep -- "-r--------" - """#, - ] - } - } -} diff --git a/tests/plan/inputs/secrets/exec_relative.cue b/tests/plan/inputs/secrets/exec_relative.cue deleted file mode 100644 index 8e961a01..00000000 --- a/tests/plan/inputs/secrets/exec_relative.cue +++ /dev/null @@ -1,33 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - inputs: secrets: echo: command: { - name: "cat" - args: ["./test.txt"] - } - - actions: { - - image: dagger.#Pull & { - source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" - } - - verify: dagger.#Exec & { - input: image.output - mounts: secret: { - dest: "/run/secrets/test" - contents: inputs.secrets.echo.contents - } - args: [ - "sh", "-c", - #""" - test "$(cat /run/secrets/test)" = "test" - """#, - ] - } - } -} diff --git a/tests/plan/inputs/secrets/invalid_command.cue b/tests/plan/inputs/secrets/invalid_command.cue deleted file mode 100644 index f6012906..00000000 --- a/tests/plan/inputs/secrets/invalid_command.cue +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - inputs: secrets: echo: command: { - name: "rtyet" // should fail because command doesn't exist - args: ["hello europa"] - } - - actions: { - - image: dagger.#Pull & { - source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" - } - - verify: dagger.#Exec & { - input: image.output - mounts: secret: { - dest: "/run/secrets/test" - contents: inputs.secrets.echo.contents - } - args: [ - "sh", "-c", - #""" - test "$(cat /run/secrets/test)" = "hello europa" - ls -l /run/secrets/test | grep -- "-r--------" - """#, - ] - } - } -} diff --git a/tests/plan/inputs/secrets/invalid_command_options.cue b/tests/plan/inputs/secrets/invalid_command_options.cue deleted file mode 100644 index 040ed80a..00000000 --- a/tests/plan/inputs/secrets/invalid_command_options.cue +++ /dev/null @@ -1,33 +0,0 @@ -package main - -import ( -) - -dagger.#Plan & { - inputs: secrets: echo: command: { - name: "cat" - args: ["--sfgjkhf"] // // should fail because invalid option - } - - actions: { - - image: dagger.#Pull & { - source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" - } - - verify: dagger.#Exec & { - input: image.output - mounts: secret: { - dest: "/run/secrets/test" - contents: inputs.secrets.echo.contents - } - args: [ - "sh", "-c", - #""" - test "$(cat /run/secrets/test)" = "hello europa" - ls -l /run/secrets/test | grep -- "-r--------" - """#, - ] - } - } -} diff --git a/tests/plan/inputs/secrets/secrets.cue b/tests/plan/inputs/secrets/secrets.cue new file mode 100644 index 00000000..a8369797 --- /dev/null +++ b/tests/plan/inputs/secrets/secrets.cue @@ -0,0 +1,59 @@ +package main + +import ( + "dagger.io/dagger" +) + +dagger.#Plan & { + inputs: secrets: { + echo: command: { + name: "echo" + args: ["hello europa"] + } + + relative: command: { + name: "cat" + args: ["./test.txt"] + } + + badCommand: command: { + name: "rtyet" // should fail because command doesn't exist + args: ["hello europa"] + } + + badArgs: command: { + name: "cat" + args: ["--sfgjkhf"] // // should fail because invalid option + } + } + + actions: { + + _image: dagger.#Pull & { + source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" + } + + test: { + + [string]: dagger.#Exec & { + input: _image.output + mounts: secret: { + dest: "/run/secrets/test" + // contents: inputs.secrets.echo.contents + } + args: [ + "sh", "-c", + #""" + test "$(cat /run/secrets/test)" = "hello europa" + ls -l /run/secrets/test | grep -- "-r--------" + """#, + ] + } + + valid: mounts: secret: contents: inputs.secrets.echo.contents + relative: mounts: secret: contents: inputs.secrets.relative.contents + badCommand: mounts: secret: contents: inputs.secrets.badCommand.contents + badArgs: mounts: secret: contents: inputs.secrets.badArgs.contents + } + } +} diff --git a/tests/plan/inputs/secrets/test.txt b/tests/plan/inputs/secrets/test.txt index 30d74d25..557126b8 100644 --- a/tests/plan/inputs/secrets/test.txt +++ b/tests/plan/inputs/secrets/test.txt @@ -1 +1 @@ -test \ No newline at end of file +hello europa \ No newline at end of file diff --git a/tests/plan/with/actions.cue b/tests/plan/with/actions.cue deleted file mode 100644 index 34e45b34..00000000 --- a/tests/plan/with/actions.cue +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - - actions: { - image: dagger.#Pull & { - source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" - } - - verify: dagger.#Exec & { - input: image.output - env: FOO: string - args: [ - "sh", "-c", - #""" - test -n "$FOO" - """#, - ] - } - } -} diff --git a/tests/plan/with/params.cue b/tests/plan/with/params.cue deleted file mode 100644 index fc4317a9..00000000 --- a/tests/plan/with/params.cue +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "dagger.io/dagger" -) - -dagger.#Plan & { - inputs: params: foo: string - - actions: { - image: dagger.#Pull & { - source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" - } - - verify: dagger.#Exec & { - input: image.output - env: FOO: inputs.params.foo - args: [ - "sh", "-c", - #""" - test "$FOO" = "bar" - """#, - ] - } - } -} diff --git a/tests/plan/with/with.cue b/tests/plan/with/with.cue new file mode 100644 index 00000000..a6a6334e --- /dev/null +++ b/tests/plan/with/with.cue @@ -0,0 +1,31 @@ +package main + +import ( + "dagger.io/dagger" +) + +dagger.#Plan & { + inputs: params: foo: string + + actions: { + _image: dagger.#Pull & { + source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3" + } + + test: { + [string]: dagger.#Exec & { + input: _image.output + env: FOO: string + args: [ + "sh", "-c", + #""" + test -n "$FOO" + """#, + ] + } + + direct: {} + params: env: FOO: inputs.params.foo + } + } +}