From af514499d68ca404b93ccaa0efb215f4dbaacebb Mon Sep 17 00:00:00 2001 From: Luc DUZAN Date: Mon, 16 Sep 2024 13:07:21 +0200 Subject: [PATCH] run sql --- client/console_client.go | 20 ++++++++++ cmd/execute_sql.go | 61 ++++++++++++++++++++++++++++++ cmd/root.go | 1 + docker/initializer.json | 23 +++++++++++ indexed_topic.yaml | 7 ++++ schema/console-default-schema.json | 2 +- test_final_exec.sh | 1 + 7 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 cmd/execute_sql.go create mode 100644 indexed_topic.yaml diff --git a/client/console_client.go b/client/console_client.go index 8bd763f..b4af9f4 100644 --- a/client/console_client.go +++ b/client/console_client.go @@ -382,6 +382,26 @@ func (client *Client) CreateApplicationInstanceToken(applicationInstanceName, na } } +type SqlResult struct { + Header []string `json:"header"` + Row [][]interface{} `json:"row"` +} + +func (client *Client) ExecuteSql(maxLine int, sql string) (SqlResult, error) { + var result SqlResult + client.setApiKeyFromEnvIfNeeded() + url := client.baseUrl + "/public/sql/v1/execute" + resp, err := client.client.R().SetBody(sql).SetQueryParam("maxLine", fmt.Sprintf("%d", maxLine)).Post(url) + if err != nil { + return result, err + } else if resp.IsError() { + return result, fmt.Errorf(extractApiError(resp)) + } else { + err = json.Unmarshal(resp.Body(), &result) + return result, err + } +} + func (client *Client) DeleteToken(uuid string) error { client.setApiKeyFromEnvIfNeeded() url := client.baseUrl + "/token/v1/" + uuid diff --git a/cmd/execute_sql.go b/cmd/execute_sql.go new file mode 100644 index 0000000..ff2c805 --- /dev/null +++ b/cmd/execute_sql.go @@ -0,0 +1,61 @@ +package cmd + +import ( + "fmt" + "os" + + "text/tabwriter" + + "github.com/conduktor/ctl/schema" + "github.com/spf13/cobra" +) + +func initSql(kinds schema.KindCatalog) { + _, ok := kinds["IndexedTopic"] + if ok { + numLine := 1 + var sqlCmd = &cobra.Command{ + Use: "sql", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + sqlResult, err := consoleApiClient().ExecuteSql(numLine, args[0]) + if err != nil { + fmt.Fprintf(os.Stderr, "Could not execute SQL: %s\n", err) + os.Exit(1) + } + + minwidth := 0 + tabwidth := 2 + padding := 2 + padchar := byte(' ') + flags := uint(0) + writer := tabwriter.NewWriter(os.Stdout, minwidth, tabwidth, padding, padchar, flags) + headerStr := "" + for _, column := range sqlResult.Header { + if headerStr != "" { + headerStr += "\t" + column + } else { + headerStr += column + } + } + fmt.Fprintln(writer, headerStr) + for _, line := range sqlResult.Row { + lineStr := "" + for _, data := range line { + dataStr := fmt.Sprintf("%v", data) + if lineStr != "" { + lineStr += "\t" + dataStr + } else { + lineStr += dataStr + } + } + fmt.Fprintln(writer, lineStr) + } + writer.Flush() + }, + } + + sqlCmd.Flags().IntVarP(&numLine, "num-line", "n", 100, "Number of line to display") + rootCmd.AddCommand(sqlCmd) + } +} diff --git a/cmd/root.go b/cmd/root.go index a973475..618a6ea 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -84,4 +84,5 @@ func init() { initConsoleMkKind() initGatewayMkKind() initPrintKind(kinds) + initSql(kinds) } diff --git a/docker/initializer.json b/docker/initializer.json index 5a5a135..90a14b2 100644 --- a/docker/initializer.json +++ b/docker/initializer.json @@ -248,5 +248,28 @@ ] } } + }, + { + "httpRequest": { + "method": "POST", + "path": "/api/public/sql/v1/execute", + "queryStringParameters": { + "maxLine": ["100"] + }, + "headers": { + "Authorization": "Bearer yo" + }, + "body": "select * from \"julien-cloud_sql_test\"" + }, + "httpResponse": { + "statusCode": 200, + "body": {"header": [], "row": []}, + "headers": { + "Content-Type": [ + "application/json" + ] + } + } } + ] \ No newline at end of file diff --git a/indexed_topic.yaml b/indexed_topic.yaml new file mode 100644 index 0000000..d34f0d2 --- /dev/null +++ b/indexed_topic.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: IndexedTopic +metadata: + cluster: julien-cloud + name: sql_test +spec: + retentionTimeInSecond: 360000 diff --git a/schema/console-default-schema.json b/schema/console-default-schema.json index f4e0894..215ddea 100644 --- a/schema/console-default-schema.json +++ b/schema/console-default-schema.json @@ -1 +1 @@ -{"Application":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application","Name":"Application","ParentPathParam":[],"ListQueryParamter":{},"Order":8}}},"ApplicationGroup":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-group","Name":"ApplicationGroup","ParentPathParam":[],"ListQueryParamter":{},"Order":11}}},"ApplicationInstance":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance","Name":"ApplicationInstance","ParentPathParam":[],"ListQueryParamter":{"application":{"FlagName":"application","Required":false,"Type":"string"}},"Order":9}}},"ApplicationInstancePermission":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance-permission","Name":"ApplicationInstancePermission","ParentPathParam":[],"ListQueryParamter":{"filterByApplication":{"FlagName":"application","Required":false,"Type":"string"},"filterByApplicationInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"filterByGrantedTo":{"FlagName":"granted-to","Required":false,"Type":"string"}},"Order":10}}},"Group":{"Versions":{"2":{"ListPath":"/public/iam/v2/group","Name":"Group","ParentPathParam":[],"ListQueryParamter":{},"Order":1}}},"KafkaCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/kafka-cluster","Name":"KafkaCluster","ParentPathParam":[],"ListQueryParamter":{},"Order":2}}},"KafkaConnectCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/kafka-connect","Name":"KafkaConnectCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":3}}},"KsqlDBCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/ksqldb","Name":"KsqlDBCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":4}}},"Subject":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/subject","Name":"Subject","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":6}}},"Topic":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/topic","Name":"Topic","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":5}}},"TopicPolicy":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/topic-policy","Name":"TopicPolicy","ParentPathParam":[],"ListQueryParamter":{"app-instance":{"FlagName":"application-instance","Required":false,"Type":"string"}},"Order":7}}},"User":{"Versions":{"2":{"ListPath":"/public/iam/v2/user","Name":"User","ParentPathParam":[],"ListQueryParamter":{},"Order":0}}}} \ No newline at end of file +{"Alert":{"Versions":{"2":{"ListPath":"/public/monitoring/v2/cluster/{cluster}/alert","Name":"Alert","ParentPathParam":["cluster"],"ListQueryParamter":{"connect":{"FlagName":"connect","Required":false,"Type":"string"},"connector":{"FlagName":"connector","Required":false,"Type":"string"}},"Order":14}}},"Application":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application","Name":"Application","ParentPathParam":[],"ListQueryParamter":{},"Order":10}}},"ApplicationGroup":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-group","Name":"ApplicationGroup","ParentPathParam":[],"ListQueryParamter":{},"Order":13}}},"ApplicationInstance":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance","Name":"ApplicationInstance","ParentPathParam":[],"ListQueryParamter":{"application":{"FlagName":"application","Required":false,"Type":"string"}},"Order":11}}},"ApplicationInstancePermission":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/application-instance-permission","Name":"ApplicationInstancePermission","ParentPathParam":[],"ListQueryParamter":{"filterByApplication":{"FlagName":"application","Required":false,"Type":"string"},"filterByApplicationInstance":{"FlagName":"application-instance","Required":false,"Type":"string"},"filterByGrantedTo":{"FlagName":"granted-to","Required":false,"Type":"string"}},"Order":12}}},"Connector":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/connect/{connectCluster}/connector","Name":"Connector","ParentPathParam":["cluster","connectCluster"],"ListQueryParamter":{},"Order":7}}},"Group":{"Versions":{"2":{"ListPath":"/public/iam/v2/group","Name":"Group","ParentPathParam":[],"ListQueryParamter":{},"Order":1}}},"IndexedTopic":{"Versions":{"1":{"ListPath":"/public/sql/v1/cluster/{cluster}/indexed_topic","Name":"IndexedTopic","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":8}}},"KafkaCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/kafka-cluster","Name":"KafkaCluster","ParentPathParam":[],"ListQueryParamter":{},"Order":2}}},"KafkaConnectCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/kafka-connect","Name":"KafkaConnectCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":3}}},"KsqlDBCluster":{"Versions":{"2":{"ListPath":"/public/console/v2/cluster/{cluster}/ksqldb","Name":"KsqlDBCluster","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":4}}},"Subject":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/subject","Name":"Subject","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":6}}},"Topic":{"Versions":{"2":{"ListPath":"/public/kafka/v2/cluster/{cluster}/topic","Name":"Topic","ParentPathParam":["cluster"],"ListQueryParamter":{},"Order":5}}},"TopicPolicy":{"Versions":{"1":{"ListPath":"/public/self-serve/v1/topic-policy","Name":"TopicPolicy","ParentPathParam":[],"ListQueryParamter":{"app-instance":{"FlagName":"application-instance","Required":false,"Type":"string"}},"Order":9}}},"User":{"Versions":{"2":{"ListPath":"/public/iam/v2/user","Name":"User","ParentPathParam":[],"ListQueryParamter":{},"Order":0}}}} \ No newline at end of file diff --git a/test_final_exec.sh b/test_final_exec.sh index ab71b91..67abfef 100755 --- a/test_final_exec.sh +++ b/test_final_exec.sh @@ -33,6 +33,7 @@ main() { run conduktor token create admin a_admin_token run conduktor token create application-instance -i=my_app_instance a_admin_token run conduktor token delete 0-0-0-0-0 + run conduktor sql 'select * from "julien-cloud_sql_test"' -n 100 # Gateway run conduktor apply -f /test_resource_gw.yml