implements dagger do
Signed-off-by: Richard Jones <richard@dagger.io>
This commit is contained in:
parent
621edd6b2f
commit
6cdf13223c
140
cmd/dagger/cmd/do.go
Normal file
140
cmd/dagger/cmd/do.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
@ -30,7 +30,7 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringArray("cache-from", []string{},
|
rootCmd.PersistentFlags().StringArray("cache-from", []string{},
|
||||||
"External cache sources (eg. user/app:cache, type=local,src=path/to/dir)")
|
"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) {
|
rootCmd.PersistentPreRun = func(cmd *cobra.Command, _ []string) {
|
||||||
go checkVersion()
|
go checkVersion()
|
||||||
@ -45,6 +45,7 @@ func init() {
|
|||||||
versionCmd,
|
versionCmd,
|
||||||
docCmd,
|
docCmd,
|
||||||
mod.Cmd,
|
mod.Cmd,
|
||||||
|
doCmd,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
|
||||||
|
34
plan/action.go
Normal file
34
plan/action.go
Normal file
@ -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
|
||||||
|
}
|
83
plan/plan.go
83
plan/plan.go
@ -17,11 +17,16 @@ import (
|
|||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ActionsPath = "actions"
|
||||||
|
)
|
||||||
|
|
||||||
type Plan struct {
|
type Plan struct {
|
||||||
config Config
|
config Config
|
||||||
|
|
||||||
context *plancontext.Context
|
context *plancontext.Context
|
||||||
source *compiler.Value
|
source *compiler.Value
|
||||||
|
action *Action
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -66,6 +71,8 @@ func Load(ctx context.Context, cfg Config) (*Plan, error) {
|
|||||||
source: v,
|
source: v,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.fillAction()
|
||||||
|
|
||||||
if err := p.configPlatform(); err != nil {
|
if err := p.configPlatform(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -85,6 +92,10 @@ func (p *Plan) Source() *compiler.Value {
|
|||||||
return p.source
|
return p.source
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Plan) Action() *Action {
|
||||||
|
return p.action
|
||||||
|
}
|
||||||
|
|
||||||
// configPlatform load the platform specified in the context
|
// configPlatform load the platform specified in the context
|
||||||
// Buildkit will then run every operation using that platform
|
// Buildkit will then run every operation using that platform
|
||||||
// If platform is not define, context keep default 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 {
|
func newRunner(pctx *plancontext.Context, s solver.Solver, computed *compiler.Value) cueflow.TaskFunc {
|
||||||
return func(flowVal cue.Value) (cueflow.Runner, error) {
|
return func(flowVal cue.Value) (cueflow.Runner, error) {
|
||||||
v := compiler.Wrap(flowVal)
|
v := compiler.Wrap(flowVal)
|
||||||
|
115
tests/plan.bats
115
tests/plan.bats
@ -7,154 +7,77 @@ setup() {
|
|||||||
@test "plan/hello" {
|
@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
|
# Europa loader handles the cwd differently, therefore we need to CD into the tree at or below the parent of cue.mod
|
||||||
cd "$TESTDIR"
|
cd "$TESTDIR"
|
||||||
"$DAGGER" up ./plan/hello-europa
|
"$DAGGER" "do" -p ./plan/hello-europa test
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/proxy invalid schema" {
|
@test "plan/proxy invalid schema" {
|
||||||
cd "$TESTDIR"
|
cd "$TESTDIR"
|
||||||
run "$DAGGER" up ./plan/proxy/invalid_schema.cue
|
run "$DAGGER" "do" -p ./plan/proxy/invalid_schema.cue verify
|
||||||
assert_failure
|
assert_failure
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/proxy invalid value" {
|
@test "plan/proxy invalid value" {
|
||||||
cd "$TESTDIR"
|
cd "$TESTDIR"
|
||||||
run "$DAGGER" up ./plan/proxy/invalid_value.cue
|
run "$DAGGER" "do" -p ./plan/proxy/invalid_value.cue verify
|
||||||
assert_failure
|
assert_failure
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/proxy incomplete unix" {
|
@test "plan/proxy incomplete unix" {
|
||||||
cd "$TESTDIR"
|
cd "$TESTDIR"
|
||||||
run "$DAGGER" up ./plan/proxy/incomplete_unix.cue
|
run "$DAGGER" "do" -p ./plan/proxy/incomplete_unix.cue verify
|
||||||
assert_failure
|
assert_failure
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/proxy incomplete service" {
|
@test "plan/proxy incomplete service" {
|
||||||
cd "$TESTDIR"
|
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'
|
assert_output --partial 'mount "docker" is not concrete'
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/proxy unix" {
|
@test "plan/proxy unix" {
|
||||||
cd "$TESTDIR"
|
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"
|
cd "$TESTDIR"
|
||||||
"$DAGGER" up ./plan/inputs/directories/exists.cue
|
"$DAGGER" "do" -p ./plan/inputs/directories/valid exists
|
||||||
}
|
|
||||||
|
|
||||||
@test "plan/inputs/directories relative directories" {
|
run "$DAGGER" "do" -p ./plan/inputs/directories/invalid notExists
|
||||||
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
|
|
||||||
assert_failure
|
assert_failure
|
||||||
assert_output --partial 'fasdfsdfs" does not exist'
|
assert_output --partial 'fasdfsdfs" does not exist'
|
||||||
}
|
|
||||||
|
|
||||||
@test "plan/inputs/directories conflicting values" {
|
run "$DAGGER" "do" -p ./plan/inputs/directories/valid conflictingValues
|
||||||
cd "$TESTDIR"
|
|
||||||
run "$DAGGER" up ./plan/inputs/directories/conflicting_values.cue
|
|
||||||
assert_failure
|
assert_failure
|
||||||
assert_output --partial 'conflicting values "local directory" and "local dfsadf"'
|
assert_output --partial 'conflicting values "local directory" and "local dfsadf"'
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/inputs/secrets" {
|
@test "plan/inputs/secrets" {
|
||||||
cd "$TESTDIR"
|
cd "$TESTDIR"
|
||||||
"$DAGGER" up ./plan/inputs/secrets/exec.cue
|
"$DAGGER" "do" -p ./plan/inputs/secrets test valid
|
||||||
"$DAGGER" up ./plan/inputs/secrets/exec_relative.cue
|
"$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_failure
|
||||||
assert_output --partial 'failed: exec: "rtyet": executable file not found'
|
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_failure
|
||||||
assert_output --partial 'option'
|
assert_output --partial 'option'
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/with" {
|
@test "plan/with" {
|
||||||
cd "$TESTDIR"
|
cd "$TESTDIR"
|
||||||
"$DAGGER" up --with 'inputs: params: foo:"bar"' ./plan/with/params.cue
|
"$DAGGER" "do" --with 'inputs: params: foo:"bar"' -p ./plan/with test params
|
||||||
"$DAGGER" up --with 'actions: verify: env: FOO: "bar"' ./plan/with/actions.cue
|
"$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_failure
|
||||||
assert_output --partial "conflicting values string and 1"
|
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_failure
|
||||||
assert_output --partial "actions.verify.env.FOO: non-concrete value string"
|
assert_output --partial "actions.test.params.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"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "plan/platform" {
|
@test "plan/platform" {
|
||||||
|
74
tests/plan/do/actions.cue
Normal file
74
tests/plan/do/actions.cue
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,18 +6,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
dagger.#Plan & {
|
dagger.#Plan & {
|
||||||
actions: {
|
actions: test: {
|
||||||
image: dagger.#Pull & {
|
_image: dagger.#Pull & {
|
||||||
source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3"
|
source: "alpine:3.15.0@sha256:e7d88de73db3d3fd9b2d63aa7f447a10fd0220b7cbf39803c803f2af9ba256b3"
|
||||||
}
|
}
|
||||||
|
|
||||||
exec: dagger.#Exec & {
|
_exec: dagger.#Exec & {
|
||||||
input: image.output
|
input: _image.output
|
||||||
args: ["sh", "-c", "echo -n Hello Europa > /out.txt"]
|
args: ["sh", "-c", "echo -n Hello Europa > /out.txt"]
|
||||||
}
|
}
|
||||||
|
|
||||||
verify: dagger.#ReadFile & {
|
_verify: dagger.#ReadFile & {
|
||||||
input: exec.output
|
input: _exec.output
|
||||||
path: "/out.txt"
|
path: "/out.txt"
|
||||||
} & {
|
} & {
|
||||||
// assert result
|
// assert result
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
3
tests/plan/inputs/directories/invalid/invalid.cue
Normal file
3
tests/plan/inputs/directories/invalid/invalid.cue
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
inputs: directories: test: path: "./fasdfsdfs"
|
31
tests/plan/inputs/directories/main.cue
Normal file
31
tests/plan/inputs/directories/main.cue
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
3
tests/plan/inputs/directories/valid/valid.cue
Normal file
3
tests/plan/inputs/directories/valid/valid.cue
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
inputs: directories: test: path: "."
|
@ -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--------"
|
|
||||||
"""#,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
||||||
"""#,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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--------"
|
|
||||||
"""#,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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--------"
|
|
||||||
"""#,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
59
tests/plan/inputs/secrets/secrets.cue
Normal file
59
tests/plan/inputs/secrets/secrets.cue
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
test
|
hello europa
|
@ -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"
|
|
||||||
"""#,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
||||||
"""#,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
31
tests/plan/with/with.cue
Normal file
31
tests/plan/with/with.cue
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user