Skip to content

Commit

Permalink
Add run command
Browse files Browse the repository at this point in the history
  • Loading branch information
weikanglim committed Nov 10, 2023
1 parent c783805 commit 23e937b
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 36 deletions.
33 changes: 33 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cmd

import (
"errors"

"github.com/weikanglim/ksd/internal/ksd"
)

func GetCredentialOptionsFromFlags() (ksd.CredentialOptions, error) {
opts := ksd.CredentialOptions{}
if clientId != "" {
if clientSecret == "" {
return opts, errors.New("`--client-secret` must be set when `--client-id` is provided")
}

if tenantId == "" {
return opts, errors.New("`--tenant-id` must be set when `--client-id` is provided")
}

opts.ClientId = clientId
opts.ClientSecret = clientSecret
opts.TenantId = tenantId
} else {
if clientSecret != "" {
return opts, errors.New("`--client-id` must be set when `--client-secret` is provided")
}

if tenantId != "" {
return opts, errors.New("`--client-id` must be set when `--tenant-id` is provided")
}
}
return opts, nil
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func NewRootCmd() *cobra.Command {

root.AddCommand(NewBuildCommand())
root.AddCommand(NewSyncCommand())
root.AddCommand(NewRunCmd())

return root
}
60 changes: 60 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cmd

import (
"errors"
"fmt"
"net/http"
"os"

"github.com/MakeNowJust/heredoc/v2"
"github.com/spf13/cobra"
"github.com/weikanglim/ksd/internal/ksd"
)

func NewRunCmd() *cobra.Command {
var script string

var runCmd = &cobra.Command{
Use: "run <file>",
Short: "Runs a script file.",
Args: cobra.MaximumNArgs(1),
Long: heredoc.Doc(`
Run executes the script file against a Kusto database.
`),
Example: heredoc.Doc(`
# Run a script file
$ ksd run ./script.ksl
`),
RunE: func(cmd *cobra.Command, args []string) error {
if endpoint == "" {
return errors.New("missing `--endpoint`. Set this to a Azure Data Explorer database endpoint, i.e. https://samples.kusto.windows.net/MyDatabase")
}

file := args[0]
_, err := os.Stat(file)
if errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("script file %s does not exist", file)
}
if err != nil {
return fmt.Errorf("reading %s: %w", file, err)
}

credOptions, err := GetCredentialOptionsFromFlags()
if err != nil {
return err
}

return ksd.Run(file, endpoint, credOptions, http.DefaultClient)
},
}

runCmd.Flags().StringVar(&script, "script", "", "The script file to run.")

// Connection flags
runCmd.Flags().StringVar(&endpoint, "endpoint", "", "The endpoint to the Azure Data Explorer database")
runCmd.Flags().StringVar(&clientId, "client-id", "", "The ID of the application to authenticate with")
runCmd.Flags().StringVar(&clientSecret, "client-secret", "", "The secret of the application to authenticate with")
runCmd.Flags().StringVar(&tenantId, "tenant-id", "", "The tenant ID of the application to authenticate with")

return runCmd
}
34 changes: 8 additions & 26 deletions cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import (
"github.com/weikanglim/ksd/internal/ksd"
)

var clientId string
var clientSecret string
var tenantId string
var endpoint string

func NewSyncCommand() *cobra.Command {
var fromOut string
var clientId string
var clientSecret string
var tenantId string
var endpoint string

var syncCmd = &cobra.Command{
Use: "sync <directory>",
Short: "Syncs Kusto function and table declarations to a targeted Azure Data Explorer database",
Expand Down Expand Up @@ -67,27 +67,9 @@ func NewSyncCommand() *cobra.Command {
return errors.New("missing `--endpoint`. Set this to a Azure Data Explorer database endpoint, i.e. https://samples.kusto.windows.net/MyDatabase")
}

credOptions := ksd.CredentialOptions{}
if clientId != "" {
if clientSecret == "" {
return errors.New("`--client-secret` must be set when `--client-id` is provided")
}

if tenantId == "" {
return errors.New("`--tenant-id` must be set when `--client-id` is provided")
}

credOptions.ClientId = clientId
credOptions.ClientSecret = clientSecret
credOptions.TenantId = tenantId
} else {
if clientSecret != "" {
return errors.New("`--client-id` must be set when `--client-secret` is provided")
}

if tenantId != "" {
return errors.New("`--client-id` must be set when `--tenant-id` is provided")
}
credOptions, err := GetCredentialOptionsFromFlags()
if err != nil {
return err
}

var outRoot string
Expand Down
50 changes: 50 additions & 0 deletions internal/ksd/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ksd

import (
"context"
"fmt"
"net/http"
"os"

"github.com/Azure/azure-kusto-go/kusto/kql"
)

// Run executes a Kusto script.
func Run(
file string,
endpoint string,
cred CredentialOptions,
httpClient *http.Client) error {
conn, err := parseEndpoint(endpoint)
if err != nil {
return err
}
client, err := newKustoClient(conn.endpoint, cred, httpClient)
if err != nil {
return err
}
defer func() error {
err = client.Close()
if err != nil {
return fmt.Errorf("closing client: %w", err)
}
return nil
}()

ctx := context.Background()
cmdScript, err := os.ReadFile(file)
if err != nil {
return fmt.Errorf("reading file %s: %w", file, err)
}
query := kql.New("")
query.AddUnsafe(string(cmdScript))
_, err = client.Mgmt(
ctx,
conn.db,
query)
if err != nil {
return fmt.Errorf("running command: %w", err)
}

return nil
}
42 changes: 42 additions & 0 deletions test/run_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package test

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func TestRun_Live(t *testing.T) {
cfg, err := getLiveConfig()
if err != nil {
t.Skip(err.Error())
}

runArgs := []string{"run"}
runArgs = append(runArgs, argsFromConfig(cfg)...)

tests := []struct {
name string
args []string
chdir string
expect func(t *testing.T, r cmdResult)
}{
{
"File",
append(runArgs, filepath.Join("scripts", "show.csl")),
"testdata",
nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.chdir != "" {
Chdir(t, tt.chdir)
}

res := executeCmd(tt.args)
require.NoError(t, res.Err)
})
}
}
20 changes: 10 additions & 10 deletions test/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func TestSync_Live(t *testing.T) {
}
}

func argsFromConfig(cfg syncConfig) []string {
func argsFromConfig(cfg clientConfig) []string {
if cfg.defaultAuth {
return []string{
"--endpoint",
Expand All @@ -141,7 +141,7 @@ func argsFromConfig(cfg syncConfig) []string {
}
}

type syncConfig struct {
type clientConfig struct {
// if true, the default auth flags are passed
defaultAuth bool

Expand All @@ -151,15 +151,15 @@ type syncConfig struct {
endpoint string
}

func getLiveConfig() (syncConfig, error) {
func getLiveConfig() (clientConfig, error) {
endpoint := os.Getenv("KSD_TEST_ENDPOINT")

if os.Getenv("KSD_TEST_DEFAULT_AUTH") != "" {
if endpoint == "" {
return syncConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_ENDPOINT")
return clientConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_ENDPOINT")
}

return syncConfig{
return clientConfig{
defaultAuth: true,
endpoint: endpoint,
}, nil
Expand All @@ -169,22 +169,22 @@ func getLiveConfig() (syncConfig, error) {
tenantId := os.Getenv("KSD_TEST_TENANT_ID")

if clientId == "" {
return syncConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_CLIENT_ID")
return clientConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_CLIENT_ID")
}

if clientSecret == "" {
return syncConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_CLIENT_SECRET")
return clientConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_CLIENT_SECRET")
}

if tenantId == "" {
return syncConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_TENANT_ID")
return clientConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_TENANT_ID")
}

if endpoint == "" {
return syncConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_ENDPOINT")
return clientConfig{}, fmt.Errorf("skipped due to missing KSD_TEST_ENDPOINT")
}

return syncConfig{
return clientConfig{
clientId: clientId,
clientSecret: clientSecret,
tenantId: tenantId,
Expand Down
1 change: 1 addition & 0 deletions test/testdata/scripts/show.csl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.show functions

0 comments on commit 23e937b

Please sign in to comment.