diff --git a/cmd/dagger/cmd/common.go b/cmd/dagger/cmd/common.go new file mode 100644 index 00000000..a3de45b2 --- /dev/null +++ b/cmd/dagger/cmd/common.go @@ -0,0 +1,33 @@ +package cmd + +import ( + "os" + "path/filepath" + + "github.com/rs/zerolog" + "github.com/spf13/cobra" +) + +// getRouteName returns the selected route name (based on explicit CLI selection or current work dir) +func getRouteName(lg zerolog.Logger, cmd *cobra.Command) string { + routeName, err := cmd.Flags().GetString("route") + if err != nil { + lg.Fatal().Err(err).Str("flag", "route").Msg("unable to resolve flag") + } + + if routeName != "" { + return routeName + } + + workDir, err := os.Getwd() + if err != nil { + lg.Fatal().Err(err).Msg("failed to get current working dir") + } + + currentDir := filepath.Base(workDir) + if currentDir == "/" { + return "root" + } + + return currentDir +} diff --git a/cmd/dagger/cmd/down.go b/cmd/dagger/cmd/down.go new file mode 100644 index 00000000..fb0f3dac --- /dev/null +++ b/cmd/dagger/cmd/down.go @@ -0,0 +1,45 @@ +package cmd + +import ( + "dagger.io/go/cmd/dagger/logger" + "dagger.io/go/dagger" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var downCmd = &cobra.Command{ + Use: "down", + Short: "Take a route offline (WARNING: may destroy infrastructure)", + Args: cobra.NoArgs, + 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) { + lg := logger.New() + ctx := lg.WithContext(cmd.Context()) + + routeName := getRouteName(lg, cmd) + route, err := dagger.LookupRoute(routeName) + if err != nil { + lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route") + } + + // TODO: Implement options: --no-cache + if err := route.Down(ctx); err != nil { + lg.Fatal().Err(err).Str("route-name", routeName).Str("route-id", route.ID).Msg("failed to up the route") + } + }, +} + +func init() { + newCmd.Flags().Bool("--no-cache", false, "Disable all run cache") + + if err := viper.BindPFlags(newCmd.Flags()); err != nil { + panic(err) + } +} diff --git a/cmd/dagger/cmd/list.go b/cmd/dagger/cmd/list.go new file mode 100644 index 00000000..108f9928 --- /dev/null +++ b/cmd/dagger/cmd/list.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var listCmd = &cobra.Command{ + Use: "list", + Short: "List available routes", + Args: cobra.NoArgs, + 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) { + // lg := logger.New() + // ctx := lg.WithContext(cmd.Context()) + + panic("not implemented") + }, +} + +func init() { + if err := viper.BindPFlags(listCmd.Flags()); err != nil { + panic(err) + } +} diff --git a/cmd/dagger/cmd/new.go b/cmd/dagger/cmd/new.go new file mode 100644 index 00000000..5ea4a13f --- /dev/null +++ b/cmd/dagger/cmd/new.go @@ -0,0 +1,66 @@ +package cmd + +import ( + "dagger.io/go/cmd/dagger/logger" + "dagger.io/go/dagger" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var newCmd = &cobra.Command{ + Use: "new", + Short: "Create a new route", + Args: cobra.NoArgs, + 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) { + lg := logger.New() + ctx := lg.WithContext(cmd.Context()) + + // nolint:staticcheck + upRoute, err := cmd.Flags().GetBool("up") + if err != nil { + lg.Fatal().Err(err).Str("flag", "up").Msg("unable to resolve flag") + } + + // nolint:staticcheck + routeName := getRouteName(lg, cmd) + + // TODO: Implement options: --layout-*, --setup + // FIXME: give route name in create opts + route, err := dagger.CreateRoute(ctx) + if err != nil { + lg.Fatal().Err(err).Msg("failed to create route") + } + lg.Info().Str("route-id", route.ID).Str("route-name", routeName).Msg("created route") + + if upRoute { + lg.Info().Str("route-id", route.ID).Msg("bringing route online") + if err := route.Up(ctx); err != nil { + lg.Fatal().Err(err).Str("route-id", route.ID).Msg("failed to create route") + } + } + }, +} + +func init() { + newCmd.Flags().StringP("name", "n", "", "Specify a route name") + newCmd.Flags().BoolP("up", "u", false, "Bring the route online") + + newCmd.Flags().String("layout-dir", "", "Load layout from a local directory") + newCmd.Flags().String("layout-git", "", "Load layout from a git repository") + newCmd.Flags().String("layout-package", "", "Load layout from a cue package") + newCmd.Flags().String("layout-file", "", "Load layout from a cue or json file") + + newCmd.Flags().String("setup", "auto", "Specify whether to prompt user for initial setup (no|yes|auto)") + + if err := viper.BindPFlags(newCmd.Flags()); err != nil { + panic(err) + } +} diff --git a/cmd/dagger/cmd/query.go b/cmd/dagger/cmd/query.go new file mode 100644 index 00000000..a3d39496 --- /dev/null +++ b/cmd/dagger/cmd/query.go @@ -0,0 +1,58 @@ +package cmd + +import ( + "fmt" + + "dagger.io/go/cmd/dagger/logger" + "dagger.io/go/dagger" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var queryCmd = &cobra.Command{ + Use: "query", + Short: "Query the contents of a route", + Args: cobra.ExactArgs(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) { + lg := logger.New() + ctx := lg.WithContext(cmd.Context()) + + routeName := getRouteName(lg, cmd) + route, err := dagger.LookupRoute(routeName) + if err != nil { + lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route") + } + + expr := args[0] + + out, err := route.Query(ctx, expr) + if err != nil { + lg.Fatal().Err(err).Str("route-name", routeName).Str("route-id", route.ID).Msg("failed to query route") + } + + fmt.Println(out) + // TODO: Implement options: --no-*, --format, --revision + + }, +} + +func init() { + newCmd.Flags().String("revision", "latest", "Query a specific version of the route") + newCmd.Flags().StringP("format", "f", "", "Output format (json|yaml|cue|text|env)") + + newCmd.Flags().BoolP("--no-input", "I", false, "Exclude inputs from query") + newCmd.Flags().BoolP("--no-output", "O", false, "Exclude outputs from query") + newCmd.Flags().BoolP("--no-layout", "L", false, "Exclude outputs from query") + + if err := viper.BindPFlags(newCmd.Flags()); err != nil { + panic(err) + } +} diff --git a/cmd/dagger/cmd/root.go b/cmd/dagger/cmd/root.go index d791760b..2bbdf465 100644 --- a/cmd/dagger/cmd/root.go +++ b/cmd/dagger/cmd/root.go @@ -14,24 +14,21 @@ import ( var rootCmd = &cobra.Command{ Use: "dagger", - Short: "Open-source workflow engine", + Short: "A system for application delivery as code (ADC)", } func init() { rootCmd.PersistentFlags().String("log-format", "", "Log format (json, pretty). Defaults to json if the terminal is not a tty") rootCmd.PersistentFlags().StringP("log-level", "l", "debug", "Log level") + rootCmd.PersistentFlags().StringP("route", "r", "", "Select a route") rootCmd.AddCommand( computeCmd, - // Create an env - // Change settings on an env - // View or edit env serti - // settingsCmd, - // Query the state of an env - // getCmd, - // unsetCmd, - // computeCmd, - // listCmd, + newCmd, + listCmd, + queryCmd, + upCmd, + downCmd, ) if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil { diff --git a/cmd/dagger/cmd/up.go b/cmd/dagger/cmd/up.go new file mode 100644 index 00000000..833cc7f7 --- /dev/null +++ b/cmd/dagger/cmd/up.go @@ -0,0 +1,45 @@ +package cmd + +import ( + "dagger.io/go/cmd/dagger/logger" + "dagger.io/go/dagger" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var upCmd = &cobra.Command{ + Use: "up", + Short: "Bring a route online with latest layout and inputs", + Args: cobra.NoArgs, + 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) { + lg := logger.New() + ctx := lg.WithContext(cmd.Context()) + + routeName := getRouteName(lg, cmd) + route, err := dagger.LookupRoute(routeName) + if err != nil { + lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route") + } + + // TODO: Implement options: --no-cache + if err := route.Up(ctx); err != nil { + lg.Fatal().Err(err).Str("route-name", routeName).Str("route-id", route.ID).Msg("failed to up the route") + } + }, +} + +func init() { + newCmd.Flags().Bool("--no-cache", false, "Disable all run cache") + + if err := viper.BindPFlags(newCmd.Flags()); err != nil { + panic(err) + } +} diff --git a/dagger/route.go b/dagger/route.go index 2e9e1992..5773834c 100644 --- a/dagger/route.go +++ b/dagger/route.go @@ -6,49 +6,52 @@ import ( "dagger.io/go/dagger/compiler" ) - // A deployment route type Route struct { // Globally unique route ID ID string - } func CreateRoute(ctx context.Context, opts ...CreateOpt) (*Route, error) { panic("NOT IMPLEMENTED") } + type CreateOpt interface{} // FIXME func DeleteRoute(ctx context.Context, opts ...DeleteOpt) (*Route, error) { panic("NOT IMPLEMENTED") } + type DeleteOpt interface{} // FIXME -func LookupRoute(name string, opts ...LookupOpt) (string, error) { +func LookupRoute(name string, opts ...LookupOpt) (*Route, error) { panic("NOT IMPLEMENTED") } + type LookupOpt interface{} // FIXME - -func LoadRoute(ctx context.Context, ID string, opts ...LoadOpt) (*Route, error) { +func LoadRoute(ctx context.Context, id string, opts ...LoadOpt) (*Route, error) { panic("NOT IMPLEMENTED") } -type LoadOpt interface{} // FIXME +type LoadOpt interface{} // FIXME func (r *Route) Up(ctx context.Context, opts ...UpOpt) error { panic("NOT IMPLEMENTED") } + type UpOpt interface{} // FIXME func (r *Route) Down(ctx context.Context, opts ...DownOpt) error { panic("NOT IMPLEMENTED") } + type DownOpt interface{} // FIXME func (r *Route) Query(ctx context.Context, expr interface{}, opts ...QueryOpt) (*compiler.Value, error) { panic("NOT IMPLEMENTED") } + type QueryOpt interface{} // FIXME // FIXME: manage base