diff --git a/cmd/query_lambda.go b/cmd/query_lambda.go index 03a9cfc..30fdc9c 100644 --- a/cmd/query_lambda.go +++ b/cmd/query_lambda.go @@ -5,6 +5,7 @@ import ( "os" "strings" + "github.com/rockset/rockset-go-client" "github.com/rockset/rockset-go-client/openapi" "github.com/rockset/rockset-go-client/option" "github.com/spf13/cobra" @@ -163,10 +164,12 @@ func NewExecuteQueryLambdaCmd() *cobra.Command { var opts []option.QueryLambdaOption if version, _ := cmd.Flags().GetString(flag.Version); version != "" { + logger.Info("executing ql with", "version", version) opts = []option.QueryLambdaOption{option.WithVersion(version)} } if tag, _ := cmd.Flags().GetString("tag"); tag != "" { opts = []option.QueryLambdaOption{option.WithTag(tag)} + logger.Info("executing ql with", "tag", tag) } params, _ := cmd.Flags().GetStringArray("param") @@ -219,9 +222,14 @@ func newCreateQueryLambdaCmd() *cobra.Command { Annotations: group("lambda"), RunE: func(cmd *cobra.Command, args []string) error { ws, _ := cmd.Flags().GetString(flag.Workspace) - sql, _ := cmd.Flags().GetString(flag.SQL) + sqlFile, _ := cmd.Flags().GetString(flag.SQL) description, _ := cmd.Flags().GetString(flag.Description) + sql, err := os.ReadFile(sqlFile) + if err != nil { + return err + } + ctx := cmd.Context() rs, err := config.Client(cmd, Version) if err != nil { @@ -233,12 +241,17 @@ func newCreateQueryLambdaCmd() *cobra.Command { options = append(options, option.WithQueryLambdaDescription(description)) } - ql, err := rs.CreateQueryLambda(ctx, ws, args[0], sql, options...) + ql, err := rs.CreateQueryLambda(ctx, ws, args[0], string(sql), options...) if err != nil { return err } - _, _ = fmt.Fprintf(cmd.OutOrStdout(), "created query lambda %s in %s", ql.GetName(), ql.GetWorkspace()) + if err = waitUntilQLActive(rs, cmd, ws, args[0], ql.GetVersion()); err != nil { + return err + } + + _, _ = fmt.Fprintf(cmd.OutOrStdout(), "created query lambda %s.%s:%s\n", + ql.GetWorkspace(), ql.GetName(), ql.GetVersion()) return nil }, @@ -247,6 +260,7 @@ func newCreateQueryLambdaCmd() *cobra.Command { _ = cmd.RegisterFlagCompletionFunc(flag.Workspace, completion.Workspace(Version)) cmd.Flags().String(flag.Description, "", "description of the query lambda") + cmd.Flags().Bool(flag.Wait, false, "wait until query lambda is ready") cmd.Flags().String(flag.SQL, "", "file containing SQL") _ = cobra.MarkFlagRequired(cmd.Flags(), flag.SQL) @@ -277,7 +291,7 @@ func newDeleteQueryLambdaCmd() *cobra.Command { return err } - _, _ = fmt.Fprintf(cmd.OutOrStdout(), "deleted query lambda %s in %s", args[0], ws) + _, _ = fmt.Fprintf(cmd.OutOrStdout(), "deleted query lambda %s in %s\n", args[0], ws) return nil }, @@ -300,9 +314,14 @@ func newUpdateQueryLambdaCmd() *cobra.Command { ValidArgsFunction: completion.Lambda(Version), RunE: func(cmd *cobra.Command, args []string) error { ws, _ := cmd.Flags().GetString(flag.Workspace) - sql, _ := cmd.Flags().GetString(flag.SQL) + sqlFile, _ := cmd.Flags().GetString(flag.SQL) description, _ := cmd.Flags().GetString(flag.Description) + sql, err := os.ReadFile(sqlFile) + if err != nil { + return err + } + ctx := cmd.Context() rs, err := config.Client(cmd, Version) if err != nil { @@ -314,12 +333,17 @@ func newUpdateQueryLambdaCmd() *cobra.Command { options = append(options, option.WithQueryLambdaDescription(description)) } - ql, err := rs.UpdateQueryLambda(ctx, ws, args[0], sql, options...) + ql, err := rs.UpdateQueryLambda(ctx, ws, args[0], string(sql), options...) if err != nil { return err } - _, _ = fmt.Fprintf(cmd.OutOrStdout(), "updated query lambda %s in %s", ql.GetName(), ql.GetWorkspace()) + if err = waitUntilQLActive(rs, cmd, ws, args[0], ql.GetVersion()); err != nil { + return err + } + + _, _ = fmt.Fprintf(cmd.OutOrStdout(), "updated query lambda %s.%s:%s", + ql.GetWorkspace(), ql.GetName(), ql.GetVersion()) return nil }, @@ -328,6 +352,7 @@ func newUpdateQueryLambdaCmd() *cobra.Command { _ = cmd.RegisterFlagCompletionFunc(flag.Workspace, completion.Workspace(Version)) cmd.Flags().String(flag.Description, "", "description of the query lambda") + cmd.Flags().Bool(flag.Wait, false, "wait until query lambda is ready") cmd.Flags().String(flag.SQL, "", "file containing SQL") _ = cobra.MarkFlagRequired(cmd.Flags(), flag.SQL) @@ -335,3 +360,18 @@ func newUpdateQueryLambdaCmd() *cobra.Command { return &cmd } + +func waitUntilQLActive(rs *rockset.RockClient, cmd *cobra.Command, ws, name, version string) error { + wait, err := cmd.Flags().GetBool(flag.Wait) + if err != nil { + return err + } + if wait { + // TODO notify the user that we're waiting + if err := rs.Wait.UntilQueryLambdaVersionActive(cmd.Context(), ws, name, version); err != nil { + return fmt.Errorf("failed to wait for %s.%s:%s to be active: %v", ws, name, version, err) + } + } + + return nil +} diff --git a/cmd/query_lambda_test.go b/cmd/query_lambda_test.go index 7c424fb..9b89625 100644 --- a/cmd/query_lambda_test.go +++ b/cmd/query_lambda_test.go @@ -3,20 +3,80 @@ package cmd_test import ( + "fmt" + "regexp" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" "github.com/rockset/cli/cmd" "github.com/rockset/cli/internal/test" ) -func TestExecuteLambdaCmd(t *testing.T) { - test.SkipUnlessIntegrationTest(t) +type QueryLambdaSuite struct { + suite.Suite + name string + version string +} + +func TestQueryLambda(t *testing.T) { + s := QueryLambdaSuite{name: "dummy"} + suite.Run(t, &s) +} + +func (s *QueryLambdaSuite) Test_0_Create() { + c := cmd.NewRootCmd("test") + out := test.WrapAndExecute(s.T(), c, "create", "ql", "--sql", "testdata/query_lambda.sql", "--wait", s.name) + + re := regexp.MustCompile(`created query lambda commons\.\w+:(\w+)`) + m := re.FindStringSubmatch(out.String()) + s.NotNil(m) + s.version = m[1] +} + +func (s *QueryLambdaSuite) Test_1_Get() { + c := cmd.NewRootCmd("test") + out := test.WrapAndExecute(s.T(), c, "get", "ql", "--version", s.version, s.name) + + s.NotEmpty(out.String()) +} + +func (s *QueryLambdaSuite) Test_2_List() { + c := cmd.NewRootCmd("test") + out := test.WrapAndExecute(s.T(), c, "list", "ql") + + s.NotEmpty(out.String()) +} + +func (s *QueryLambdaSuite) Test_3_Execute() { + c := cmd.NewRootCmd("test") + out := test.WrapAndExecute(s.T(), c, "execute", "ql", "--version", s.version, s.name) + + s.NotEmpty(out.String()) +} + +func (s *QueryLambdaSuite) Test_4_Update() { + c := cmd.NewRootCmd("test") + out := test.WrapAndExecute(s.T(), c, "update", "ql", "--sql", "testdata/query_lambda_updated.sql", "--wait", s.name) + + re := regexp.MustCompile(`updated query lambda commons\.\w+:(\w+)`) + m := re.FindStringSubmatch(out.String()) + s.NotNil(m) + s.version = m[1] +} + +func (s *QueryLambdaSuite) Test_5_Execute() { + c := cmd.NewRootCmd("test") + out := test.WrapAndExecute(s.T(), c, "execute", "ql", "--version", s.version, s.name) + + s.NotEmpty(out.String()) +} + +// TODO test invoking using a tag too +func (s *QueryLambdaSuite) Test_6_Delete() { c := cmd.NewRootCmd("test") - // TODO test ql with --param - out := test.WrapAndExecute(t, c, "execute", "ql", "events2") + out := test.WrapAndExecute(s.T(), c, "delete", "ql", s.name) - assert.NotEmpty(t, out.String()) + s.Equal(fmt.Sprintf("deleted query lambda %s in commons\n", s.name), out.String()) } diff --git a/cmd/testdata/query_lambda.sql b/cmd/testdata/query_lambda.sql index e69de29..2737eb4 100644 --- a/cmd/testdata/query_lambda.sql +++ b/cmd/testdata/query_lambda.sql @@ -0,0 +1,10 @@ +SELECT + COUNT(e.type) AS type_cnt, + e.label +FROM + commons._events e +GROUP BY + e.label +ORDER BY + type_cnt DESC, + e.label diff --git a/cmd/verbs.go b/cmd/verbs.go index 4f7c053..75855cb 100644 --- a/cmd/verbs.go +++ b/cmd/verbs.go @@ -26,7 +26,7 @@ func addVerbs(root *cobra.Command) { executeCmd := cobra.Command{ Use: "execute", - Aliases: []string{"e"}, + Aliases: []string{"exec", "e"}, Short: "execute query", Long: "execute Rockset query", } diff --git a/internal/test/cmd.go b/internal/test/cmd.go index d6091d3..ad4e4a7 100644 --- a/internal/test/cmd.go +++ b/internal/test/cmd.go @@ -4,7 +4,6 @@ import ( "bytes" "github.com/rockset/cli/config" "github.com/stretchr/testify/require" - "log" "testing" "github.com/spf13/cobra" @@ -30,7 +29,7 @@ func Wrapper(t *testing.T, c *cobra.Command, args ...string) *bytes.Buffer { // WrapAndExecute wraps the command with Wrapper and then executes it func WrapAndExecute(t *testing.T, c *cobra.Command, args ...string) *bytes.Buffer { t.Helper() - log.Printf("args: %+v", args) + out := Wrapper(t, c, args...) require.NoError(t, c.Execute())