diff --git a/cmd/cmd.go b/cmd/cmd.go index 6929af1..2cb13b0 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -15,7 +15,35 @@ */ package cmd -// Command define single method interface -type Command interface { - Execute() +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "microcks-cli", + Short: "A CLI tool for Microcks", + Long: `microcks-cli is a CLI for interacting with Microcks server APIs. + It allows to launch tests or import API artifacts with minimal dependencies.`, + Run: func(cmd *cobra.Command, args []string) { + cmd.HelpFunc()(cmd, args) + }, + CompletionOptions: cobra.CompletionOptions{ + HiddenDefaultCmd: true, + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) + } +} + +func init() { + rootCmd.AddCommand(NewImportCommand()) + rootCmd.AddCommand(NewVersionCommand()) + rootCmd.AddCommand(NewTestCommand()) + rootCmd.AddCommand(NewImportURLCommand()) } diff --git a/cmd/help.go b/cmd/help.go deleted file mode 100644 index 65888e0..0000000 --- a/cmd/help.go +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The Microcks Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package cmd - -import "fmt" - -type helpCommand struct { -} - -// NewHelpCommand build a new HelpCommand implementation -func NewHelpCommand() Command { - return new(helpCommand) -} - -// Execute implementation on helpCommand structure -func (c *helpCommand) Execute() { - fmt.Println("") - fmt.Println("microcks-cli is a CLI for interacting with Microcks server APIs.") - fmt.Println("It allows to launch tests or import API artifacts with minimal dependencies") - fmt.Println("") - fmt.Println("") - fmt.Println("Usage:") - fmt.Println(" microcks-cli [command]") - fmt.Println("") - fmt.Println("Available Commands:") - fmt.Println(" version check this CLI version") - fmt.Println(" help display this help message") - fmt.Println(" test launch new test on Microcks server") - fmt.Println(" import import API artifacts on Microcks server") - fmt.Println(" import-url import API artifacts from URL on Microcks server") - fmt.Println("") - fmt.Println("Use: microcks-cli test \\") - fmt.Println(" --microcksURL=<> --waitFor=5sec \\") - fmt.Println(" --keycloakClientId=<> --keycloakClientSecret=<>") - fmt.Println("") - fmt.Println("Args: ") - fmt.Println(" Exemple: 'Beer Catalog API:0.9'") - fmt.Println(" URL where is deployed implementation to test") - fmt.Println(" Test strategy (one of: HTTP, SOAP, SOAP_UI, POSTMAN, OPEN_API_SCHEMA, ASYNC_API_SCHEMA, GRPC_PROTOBUF, GRAPHQL_SCHEMA)") - fmt.Println("") - fmt.Println("Flags: ") - fmt.Println(" --microcksURL Microcks API endpoint") - fmt.Println(" --waitFor Time to wait for test to finish (int + one of: milli, sec, min)") - fmt.Println(" --keycloakClientId Keycloak Realm Service Account ClientId") - fmt.Println(" --keycloakClientSecret Keycloak Realm Service Account ClientSecret") - fmt.Println("") - fmt.Println("") - fmt.Println("Use: microcks-cli import \\") - fmt.Println(" --microcksURL=<> \\") - fmt.Println(" --keycloakClientId=<> --keycloakClientSecret=<>") - fmt.Println("") - fmt.Println("Args: ") - fmt.Println(" Exemple: 'specs/my-openapi.yaml:true,specs/my-postmancollection.json:false'") - fmt.Println("") - fmt.Println("Flags: ") - fmt.Println(" --microcksURL Microcks API endpoint") - fmt.Println(" --keycloakClientId Keycloak Realm Service Account ClientId") - fmt.Println(" --keycloakClientSecret Keycloak Realm Service Account ClientSecret") - fmt.Println("") -} diff --git a/cmd/import.go b/cmd/import.go index 9d6041c..c5a98d5 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -16,7 +16,6 @@ package cmd import ( - "flag" "fmt" "os" "strconv" @@ -24,115 +23,110 @@ import ( "github.com/microcks/microcks-cli/pkg/config" "github.com/microcks/microcks-cli/pkg/connectors" + "github.com/spf13/cobra" ) -type importComamnd struct { -} - -// NewImportCommand build a new ImportCommand implementation -func NewImportCommand() Command { - return new(importComamnd) -} - -// Execute implementation of importComamnd structure -func (c *importComamnd) Execute() { - - // Parse subcommand args first. - if len(os.Args) < 2 { - fmt.Println("import command require args") - os.Exit(1) - } - - specificationFiles := os.Args[2] - - // Then parse flags. - importCmd := flag.NewFlagSet("import", flag.ExitOnError) - - var microcksURL string - var keycloakURL string - var keycloakClientID string - var keycloakClientSecret string - var insecureTLS bool - var caCertPaths string - var verbose bool - - importCmd.StringVar(µcksURL, "microcksURL", "", "Microcks API URL") - importCmd.StringVar(&keycloakClientID, "keycloakClientId", "", "Keycloak Realm Service Account ClientId") - importCmd.StringVar(&keycloakClientSecret, "keycloakClientSecret", "", "Keycloak Realm Service Account ClientSecret") - importCmd.BoolVar(&insecureTLS, "insecure", false, "Whether to accept insecure HTTPS connection") - importCmd.StringVar(&caCertPaths, "caCerts", "", "Comma separated paths of CRT files to add to Root CAs") - importCmd.BoolVar(&verbose, "verbose", false, "Produce dumps of HTTP exchanges") - importCmd.Parse(os.Args[3:]) - - // Validate presence and values of flags. - if len(microcksURL) == 0 { - fmt.Println("--microcksURL flag is mandatory. Check Usage.") - os.Exit(1) - } - if len(keycloakClientID) == 0 { - fmt.Println("--keycloakClientId flag is mandatory. Check Usage.") - os.Exit(1) - } - if len(keycloakClientSecret) == 0 { - fmt.Println("--keycloakClientSecret flag is mandatory. Check Usage.") - os.Exit(1) - } +func NewImportCommand() *cobra.Command { + var ( + microcksURL string + keycloakClientID string + keycloakClientSecret string + insecureTLS bool + caCertPaths string + verbose bool + ) + var importCmd = &cobra.Command{ + Use: "import", + Short: "import API artifacts on Microcks server", + Long: `import API artifacts on Microcks server`, + Run: func(cmd *cobra.Command, args []string) { + // Parse subcommand args first. + if len(os.Args) < 2 { + fmt.Println("import command require args") + os.Exit(1) + } - // Collect optional HTTPS transport flags. - if insecureTLS { - config.InsecureTLS = true - } - if len(caCertPaths) > 0 { - config.CaCertPaths = caCertPaths - } - if verbose { - config.Verbose = true - } + specificationFiles := os.Args[2] - // Now we seems to be good ... - // First - retrieve the Keycloak URL from Microcks configuration. - mc := connectors.NewMicrocksClient(microcksURL) - keycloakURL, err := mc.GetKeycloakURL() - if err != nil { - fmt.Printf("Got error when invoking Microcks client retrieving config: %s", err) - os.Exit(1) - } + // Validate presence and values of flags. + if len(microcksURL) == 0 { + fmt.Println("--microcksURL flag is mandatory. Check Usage.") + os.Exit(1) + } + if len(keycloakClientID) == 0 { + fmt.Println("--keycloakClientId flag is mandatory. Check Usage.") + os.Exit(1) + } + if len(keycloakClientSecret) == 0 { + fmt.Println("--keycloakClientSecret flag is mandatory. Check Usage.") + os.Exit(1) + } - var oauthToken string = "unauthentifed-token" - if keycloakURL != "null" { - // If Keycloak is enabled, retrieve an OAuth token using Keycloak Client. - kc := connectors.NewKeycloakClient(keycloakURL, keycloakClientID, keycloakClientSecret) + // Collect optional HTTPS transport flags. + if insecureTLS { + config.InsecureTLS = true + } + if len(caCertPaths) > 0 { + config.CaCertPaths = caCertPaths + } + if verbose { + config.Verbose = true + } - oauthToken, err = kc.ConnectAndGetToken() - if err != nil { - fmt.Printf("Got error when invoking Keycloack client: %s", err) - os.Exit(1) - } - } + // Now we seems to be good ... + // First - retrieve the Keycloak URL from Microcks configuration. + mc := connectors.NewMicrocksClient(microcksURL) + keycloakURL, err := mc.GetKeycloakURL() + if err != nil { + fmt.Printf("Got error when invoking Microcks client retrieving config: %s", err) + os.Exit(1) + } - // Then - for each specificationFile, upload the artifact on Microcks Server. - mc.SetOAuthToken(oauthToken) + var oauthToken string = "unauthentifed-token" + if keycloakURL != "null" { + // If Keycloak is enabled, retrieve an OAuth token using Keycloak Client. + kc := connectors.NewKeycloakClient(keycloakURL, keycloakClientID, keycloakClientSecret) - sepSpecificationFiles := strings.Split(specificationFiles, ",") - for _, f := range sepSpecificationFiles { - mainArtifact := true + oauthToken, err = kc.ConnectAndGetToken() + if err != nil { + fmt.Printf("Got error when invoking Keycloack client: %s", err) + os.Exit(1) + } + } - // Check if mainArtifact flag is provided. - if strings.Contains(f, ":") { - pathAndMainArtifact := strings.Split(f, ":") - f = pathAndMainArtifact[0] - mainArtifact, err = strconv.ParseBool(pathAndMainArtifact[1]) - if err != nil { - fmt.Printf("Cannot parse '%s' as Bool, default to true\n", pathAndMainArtifact[1]) + // Then - for each specificationFile, upload the artifact on Microcks Server. + mc.SetOAuthToken(oauthToken) + + sepSpecificationFiles := strings.Split(specificationFiles, ",") + for _, f := range sepSpecificationFiles { + mainArtifact := true + + // Check if mainArtifact flag is provided. + if strings.Contains(f, ":") { + pathAndMainArtifact := strings.Split(f, ":") + f = pathAndMainArtifact[0] + mainArtifact, err = strconv.ParseBool(pathAndMainArtifact[1]) + if err != nil { + fmt.Printf("Cannot parse '%s' as Bool, default to true\n", pathAndMainArtifact[1]) + } + } + + // Try uploading this artifact. + msg, err := mc.UploadArtifact(f, mainArtifact) + if err != nil { + fmt.Printf("Got error when invoking Microcks client importing Artifact: %s", err) + os.Exit(1) + } + fmt.Printf("Microcks has discovered '%s'\n", msg) } - } - // Try uploading this artifact. - msg, err := mc.UploadArtifact(f, mainArtifact) - if err != nil { - fmt.Printf("Got error when invoking Microcks client importing Artifact: %s", err) - os.Exit(1) - } - fmt.Printf("Microcks has discovered '%s'\n", msg) + }, } + importCmd.Flags().StringVar(µcksURL, "microcksURL", "", "Microcks API URL") + importCmd.Flags().StringVar(&keycloakClientID, "keycloakClientId", "", "Keycloak Realm Service Account ClientId") + importCmd.Flags().StringVar(&keycloakClientSecret, "keycloakClientSecret", "", "Keycloak Realm Service Account ClientSecret") + importCmd.Flags().BoolVar(&insecureTLS, "insecure", false, "Whether to accept insecure HTTPS connection") + importCmd.Flags().StringVar(&caCertPaths, "caCerts", "", "Comma separated paths of CRT files to add to Root CAs") + importCmd.Flags().BoolVar(&verbose, "verbose", false, "Produce dumps of HTTP exchanges") + return importCmd } diff --git a/cmd/importURL.go b/cmd/importURL.go index 7f41292..936df25 100644 --- a/cmd/importURL.go +++ b/cmd/importURL.go @@ -1,7 +1,22 @@ +/* + * Copyright The Microcks Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package cmd import ( - "flag" "fmt" "os" "strconv" @@ -9,120 +24,132 @@ import ( "github.com/microcks/microcks-cli/pkg/config" "github.com/microcks/microcks-cli/pkg/connectors" + "github.com/spf13/cobra" ) -type importURLCommand struct { -} +// import ( +// "flag" +// "fmt" +// "os" +// "strconv" +// "strings" + +// "github.com/microcks/microcks-cli/pkg/config" +// "github.com/microcks/microcks-cli/pkg/connectors" +// ) + +// type importURLCommand struct { +// } + +func NewImportURLCommand() *cobra.Command { + var ( + microcksURL string + keycloakClientID string + keycloakClientSecret string + insecureTLS bool + caCertPaths string + verbose bool + ) + var importURLCmd = &cobra.Command{ + Use: "import-url", + Short: "import API artifacts from URL on Microcks server", + Long: `import API artifacts from URL on Microcks server`, + Run: func(cmd *cobra.Command, args []string) { + // Parse subcommand args first. + if len(os.Args) < 2 { + fmt.Println("import-url command require args") + os.Exit(1) + } -func NewImportURLCommand() Command { - return new(importURLCommand) -} + specificationFiles := os.Args[2] -func (c *importURLCommand) Execute() { - // Parse subcommand args first. - if len(os.Args) < 2 { - fmt.Println("import-url command require args") - os.Exit(1) - } + // Validate presence and values of flags. + if len(microcksURL) == 0 { + fmt.Println("--microcksURL flag is mandatory. Check Usage.") + os.Exit(1) + } + if len(keycloakClientID) == 0 { + fmt.Println("--keycloakClientId flag is mandatory. Check Usage.") + os.Exit(1) + } + if len(keycloakClientSecret) == 0 { + fmt.Println("--keycloakClientSecret flag is mandatory. Check Usage.") + os.Exit(1) + } - specificationFiles := os.Args[2] - - // Then parse flags. - importCmd := flag.NewFlagSet("import-url", flag.ExitOnError) - - var microcksURL string - var keycloakURL string - var keycloakClientID string - var keycloakClientSecret string - var insecureTLS bool - var caCertPaths string - var verbose bool - - importCmd.StringVar(µcksURL, "microcksURL", "", "Microcks API URL") - importCmd.StringVar(&keycloakClientID, "keycloakClientId", "", "Keycloak Realm Service Account ClientId") - importCmd.StringVar(&keycloakClientSecret, "keycloakClientSecret", "", "Keycloak Realm Service Account ClientSecret") - importCmd.BoolVar(&insecureTLS, "insecure", false, "Whether to accept insecure HTTPS connection") - importCmd.StringVar(&caCertPaths, "caCerts", "", "Comma separated paths of CRT files to add to Root CAs") - importCmd.BoolVar(&verbose, "verbose", false, "Produce dumps of HTTP exchanges") - importCmd.Parse(os.Args[3:]) - - // Validate presence and values of flags. - if len(microcksURL) == 0 { - fmt.Println("--microcksURL flag is mandatory. Check Usage.") - os.Exit(1) - } - if len(keycloakClientID) == 0 { - fmt.Println("--keycloakClientId flag is mandatory. Check Usage.") - os.Exit(1) - } - if len(keycloakClientSecret) == 0 { - fmt.Println("--keycloakClientSecret flag is mandatory. Check Usage.") - os.Exit(1) - } + // Collect optional HTTPS transport flags. + if insecureTLS { + config.InsecureTLS = true + } + if len(caCertPaths) > 0 { + config.CaCertPaths = caCertPaths + } + if verbose { + config.Verbose = true + } - // Collect optional HTTPS transport flags. - if insecureTLS { - config.InsecureTLS = true - } - if len(caCertPaths) > 0 { - config.CaCertPaths = caCertPaths - } - if verbose { - config.Verbose = true - } + // Now we seems to be good ... + // First - retrieve the Keycloak URL from Microcks configuration. + mc := connectors.NewMicrocksClient(microcksURL) + keycloakURL, err := mc.GetKeycloakURL() + if err != nil { + fmt.Printf("Got error when invoking Microcks client retrieving config: %s", err) + os.Exit(1) + } - // Now we seems to be good ... - // First - retrieve the Keycloak URL from Microcks configuration. - mc := connectors.NewMicrocksClient(microcksURL) - keycloakURL, err := mc.GetKeycloakURL() - if err != nil { - fmt.Printf("Got error when invoking Microcks client retrieving config: %s", err) - os.Exit(1) - } + var oauthToken string = "unauthentifed-token" + if keycloakURL != "null" { + // If Keycloak is enabled, retrieve an OAuth token using Keycloak Client. + kc := connectors.NewKeycloakClient(keycloakURL, keycloakClientID, keycloakClientSecret) - var oauthToken string = "unauthentifed-token" - if keycloakURL != "null" { - // If Keycloak is enabled, retrieve an OAuth token using Keycloak Client. - kc := connectors.NewKeycloakClient(keycloakURL, keycloakClientID, keycloakClientSecret) + oauthToken, err = kc.ConnectAndGetToken() + if err != nil { + fmt.Printf("Got error when invoking Keycloack client: %s", err) + os.Exit(1) + } + } - oauthToken, err = kc.ConnectAndGetToken() - if err != nil { - fmt.Printf("Got error when invoking Keycloack client: %s", err) - os.Exit(1) - } - } + // Then - for each specificationFile, upload the artifact on Microcks Server. + mc.SetOAuthToken(oauthToken) + + sepSpecificationFiles := strings.Split(specificationFiles, ",") + for _, f := range sepSpecificationFiles { + mainArtifact := true + secret := "" + + // Check if URL starts with https or http + if strings.HasPrefix(f, "https://") || strings.HasPrefix(f, "http://") { + urlAndMainAtrifactAndSecretName := strings.Split(f, ":") + n := len(urlAndMainAtrifactAndSecretName) + f = urlAndMainAtrifactAndSecretName[0] + ":" + urlAndMainAtrifactAndSecretName[1] + if n > 2 { + val, err := strconv.ParseBool(urlAndMainAtrifactAndSecretName[2]) + if err != nil { + fmt.Println(err) + } + mainArtifact = val + } + if n > 3 { + secret = urlAndMainAtrifactAndSecretName[3] + } + } - // Then - for each specificationFile, upload the artifact on Microcks Server. - mc.SetOAuthToken(oauthToken) - - sepSpecificationFiles := strings.Split(specificationFiles, ",") - for _, f := range sepSpecificationFiles { - mainArtifact := true - secret := "" - - // Check if URL starts with https or http - if strings.HasPrefix(f, "https://") || strings.HasPrefix(f, "http://") { - urlAndMainAtrifactAndSecretName := strings.Split(f, ":") - n := len(urlAndMainAtrifactAndSecretName) - f = urlAndMainAtrifactAndSecretName[0] + ":" + urlAndMainAtrifactAndSecretName[1] - if n > 2 { - val, err := strconv.ParseBool(urlAndMainAtrifactAndSecretName[2]) + // Try downloading the artifcat + msg, err := mc.DownloadArtifact(f, mainArtifact, secret) if err != nil { - fmt.Println(err) + fmt.Printf("Got error when invoking Microcks client importing Artifact: %s", err) + os.Exit(1) } - mainArtifact = val - } - if n > 3 { - secret = urlAndMainAtrifactAndSecretName[3] + fmt.Printf("Microcks has discovered '%s'\n", msg) } - } - - // Try downloading the artifcat - msg, err := mc.DownloadArtifact(f, mainArtifact, secret) - if err != nil { - fmt.Printf("Got error when invoking Microcks client importing Artifact: %s", err) - os.Exit(1) - } - fmt.Printf("Microcks has discovered '%s'\n", msg) + }, } + importURLCmd.Flags().StringVar(µcksURL, "microcksURL", "", "Microcks API URL") + importURLCmd.Flags().StringVar(&keycloakClientID, "keycloakClientId", "", "Keycloak Realm Service Account ClientId") + importURLCmd.Flags().StringVar(&keycloakClientSecret, "keycloakClientSecret", "", "Keycloak Realm Service Account ClientSecret") + importURLCmd.Flags().BoolVar(&insecureTLS, "insecure", false, "Whether to accept insecure HTTPS connection") + importURLCmd.Flags().StringVar(&caCertPaths, "caCerts", "", "Comma separated paths of CRT files to add to Root CAs") + importURLCmd.Flags().BoolVar(&verbose, "verbose", false, "Produce dumps of HTTP exchanges") + + return importURLCmd } diff --git a/cmd/test.go b/cmd/test.go index 748c39c..386e37a 100644 --- a/cmd/test.go +++ b/cmd/test.go @@ -16,7 +16,6 @@ package cmd import ( - "flag" "fmt" "os" "strconv" @@ -25,6 +24,7 @@ import ( "github.com/microcks/microcks-cli/pkg/config" "github.com/microcks/microcks-cli/pkg/connectors" + "github.com/spf13/cobra" ) var ( @@ -32,179 +32,175 @@ var ( timeUnitChoices = map[string]bool{"milli": true, "sec": true, "min": true} ) -type testComamnd struct { -} - -// NewTestCommand build a new TestCommand implementation -func NewTestCommand() Command { - return new(testComamnd) -} - -// Execute implementation of testCommand structure -func (c *testComamnd) Execute() { - - // Parse subcommand args first. - if len(os.Args) < 4 { - fmt.Println("test command require args") - os.Exit(1) - } - - serviceRef := os.Args[2] - testEndpoint := os.Args[3] - runnerType := os.Args[4] - - // Validate presence and values of args. - if &serviceRef == nil || strings.HasPrefix(serviceRef, "-") { - fmt.Println("test command require args") - os.Exit(1) - } - if &testEndpoint == nil || strings.HasPrefix(testEndpoint, "-") { - fmt.Println("test command require args") - os.Exit(1) - } - if &runnerType == nil || strings.HasPrefix(runnerType, "-") { - fmt.Println("test command require args") - os.Exit(1) - } - if _, validChoice := runnerChoices[runnerType]; !validChoice { - fmt.Println(" should be one of: HTTP, SOAP, SOAP_UI, POSTMAN, OPEN_API_SCHEMA, ASYNC_API_SCHEMA, GRPC_PROTOBUF, GRAPHQL_SCHEMA") - os.Exit(1) - } - - // Then parse flags. - testCmd := flag.NewFlagSet("test", flag.ExitOnError) - - var microcksURL string - var keycloakURL string - var keycloakClientID string - var keycloakClientSecret string - var waitFor string - var secretName string - var filteredOperations string - var operationsHeaders string - var oAuth2Context string - var insecureTLS bool - var caCertPaths string - var verbose bool - - testCmd.StringVar(µcksURL, "microcksURL", "", "Microcks API URL") - testCmd.StringVar(&keycloakClientID, "keycloakClientId", "", "Keycloak Realm Service Account ClientId") - testCmd.StringVar(&keycloakClientSecret, "keycloakClientSecret", "", "Keycloak Realm Service Account ClientSecret") - testCmd.StringVar(&waitFor, "waitFor", "5sec", "Time to wait for test to finish") - testCmd.StringVar(&secretName, "secretName", "", "Secret to use for connecting test endpoint") - testCmd.StringVar(&filteredOperations, "filteredOperations", "", "List of operations to launch a test for") - testCmd.StringVar(&operationsHeaders, "operationsHeaders", "", "Override of operations headers as JSON string") - testCmd.StringVar(&oAuth2Context, "oAuth2Context", "", "Spec of an OAuth2 client context as JSON string") - testCmd.BoolVar(&insecureTLS, "insecure", false, "Whether to accept insecure HTTPS connection") - testCmd.StringVar(&caCertPaths, "caCerts", "", "Comma separated paths of CRT files to add to Root CAs") - testCmd.BoolVar(&verbose, "verbose", false, "Produce dumps of HTTP exchanges") - testCmd.Parse(os.Args[5:]) - - // Validate presence and values of flags. - if len(microcksURL) == 0 { - fmt.Println("--microcksURL flag is mandatory. Check Usage.") - os.Exit(1) - } - if len(keycloakClientID) == 0 { - fmt.Println("--keycloakClientId flag is mandatory. Check Usage.") - os.Exit(1) - } - if len(keycloakClientSecret) == 0 { - fmt.Println("--keycloakClientSecret flag is mandatory. Check Usage.") - os.Exit(1) - } - if &waitFor == nil || (!strings.HasSuffix(waitFor, "milli") && !strings.HasSuffix(waitFor, "sec") && !strings.HasSuffix(waitFor, "min")) { - fmt.Println("--waitFor format is wrong. Applying default 5sec") - waitFor = "5sec" - } - - // Collect optional HTTPS transport flags. - if insecureTLS { - config.InsecureTLS = true - } - if len(caCertPaths) > 0 { - config.CaCertPaths = caCertPaths - } - if verbose { - config.Verbose = true - } - - // Compute time to wait in milliseconds. - var waitForMilliseconds int64 = 5000 - if strings.HasSuffix(waitFor, "milli") { - waitForMilliseconds, _ = strconv.ParseInt(waitFor[:len(waitFor)-5], 0, 64) - } else if strings.HasSuffix(waitFor, "sec") { - waitForMilliseconds, _ = strconv.ParseInt(waitFor[:len(waitFor)-3], 0, 64) - waitForMilliseconds = waitForMilliseconds * 1000 - } else if strings.HasSuffix(waitFor, "min") { - waitForMilliseconds, _ = strconv.ParseInt(waitFor[:len(waitFor)-3], 0, 64) - waitForMilliseconds = waitForMilliseconds * 60 * 1000 - } - - // Now we seems to be good ... - // First - retrieve the Keycloak URL from Microcks configuration. - mc := connectors.NewMicrocksClient(microcksURL) - keycloakURL, err := mc.GetKeycloakURL() - if err != nil { - fmt.Printf("Got error when invoking Microcks client retrieving config: %s", err) - os.Exit(1) - } - - var oauthToken string = "unauthentifed-token" - if keycloakURL != "null" { - // If Keycloak is enabled, retrieve an OAuth token using Keycloak Client. - kc := connectors.NewKeycloakClient(keycloakURL, keycloakClientID, keycloakClientSecret) - - oauthToken, err = kc.ConnectAndGetToken() - if err != nil { - fmt.Printf("Got error when invoking Keycloack client: %s", err) - os.Exit(1) - } - //fmt.Printf("Retrieve OAuthToken: %s", oauthToken) - } - - // Then - launch the test on Microcks Server. - mc.SetOAuthToken(oauthToken) - - var testResultID string - testResultID, err = mc.CreateTestResult(serviceRef, testEndpoint, runnerType, secretName, waitForMilliseconds, filteredOperations, operationsHeaders, oAuth2Context) - if err != nil { - fmt.Printf("Got error when invoking Microcks client creating Test: %s", err) - os.Exit(1) - } - //fmt.Printf("Retrieve TestResult ID: %s", testResultID) - - // Finally - wait before checking and loop for some time - time.Sleep(1 * time.Second) - - // Add 10.000ms to wait time as it's now representing the server timeout. - now := nowInMilliseconds() - future := now + waitForMilliseconds + 10000 - - var success = false - for nowInMilliseconds() < future { - testResultSummary, err := mc.GetTestResult(testResultID) - if err != nil { - fmt.Printf("Got error when invoking Microcks client check TestResult: %s", err) - os.Exit(1) - } - success = testResultSummary.Success - inProgress := testResultSummary.InProgress - fmt.Printf("MicrocksClient got status for test \"%s\" - success: %s, inProgress: %s \n", testResultID, fmt.Sprint(success), fmt.Sprint(inProgress)) - - if !inProgress { - break - } - - fmt.Println("MicrocksTester waiting for 2 seconds before checking again or exiting.") - time.Sleep(2 * time.Second) - } - - fmt.Printf("Full TestResult details are available here: %s/#/tests/%s \n", strings.Split(microcksURL, "/api")[0], testResultID) - - if !success { - os.Exit(1) - } +func NewTestCommand() *cobra.Command { + var ( + microcksURL string + keycloakClientID string + keycloakClientSecret string + waitFor string + secretName string + filteredOperations string + operationsHeaders string + oAuth2Context string + insecureTLS bool + caCertPaths string + verbose bool + ) + var testCmd = &cobra.Command{ + + Use: "test", + Short: "Run tests on Microcks", + Long: `Run tests on Microcks`, + Run: func(cmd *cobra.Command, args []string) { + // Parse subcommand args first. + if len(os.Args) < 4 { + fmt.Println("test command require args") + os.Exit(1) + } + + serviceRef := os.Args[2] + testEndpoint := os.Args[3] + runnerType := os.Args[4] + + // Validate presence and values of args. + if &serviceRef == nil || strings.HasPrefix(serviceRef, "-") { + fmt.Println("test command require args") + os.Exit(1) + } + if &testEndpoint == nil || strings.HasPrefix(testEndpoint, "-") { + fmt.Println("test command require args") + os.Exit(1) + } + if &runnerType == nil || strings.HasPrefix(runnerType, "-") { + fmt.Println("test command require args") + os.Exit(1) + } + if _, validChoice := runnerChoices[runnerType]; !validChoice { + fmt.Println(" should be one of: HTTP, SOAP, SOAP_UI, POSTMAN, OPEN_API_SCHEMA, ASYNC_API_SCHEMA, GRPC_PROTOBUF, GRAPHQL_SCHEMA") + os.Exit(1) + } + + // Validate presence and values of flags. + if len(microcksURL) == 0 { + fmt.Println("--microcksURL flag is mandatory. Check Usage.") + os.Exit(1) + } + if len(keycloakClientID) == 0 { + fmt.Println("--keycloakClientId flag is mandatory. Check Usage.") + os.Exit(1) + } + if len(keycloakClientSecret) == 0 { + fmt.Println("--keycloakClientSecret flag is mandatory. Check Usage.") + os.Exit(1) + } + if &waitFor == nil || (!strings.HasSuffix(waitFor, "milli") && !strings.HasSuffix(waitFor, "sec") && !strings.HasSuffix(waitFor, "min")) { + fmt.Println("--waitFor format is wrong. Applying default 5sec") + waitFor = "5sec" + } + + // Collect optional HTTPS transport flags. + if insecureTLS { + config.InsecureTLS = true + } + if len(caCertPaths) > 0 { + config.CaCertPaths = caCertPaths + } + if verbose { + config.Verbose = true + } + + // Compute time to wait in milliseconds. + var waitForMilliseconds int64 = 5000 + if strings.HasSuffix(waitFor, "milli") { + waitForMilliseconds, _ = strconv.ParseInt(waitFor[:len(waitFor)-5], 0, 64) + } else if strings.HasSuffix(waitFor, "sec") { + waitForMilliseconds, _ = strconv.ParseInt(waitFor[:len(waitFor)-3], 0, 64) + waitForMilliseconds = waitForMilliseconds * 1000 + } else if strings.HasSuffix(waitFor, "min") { + waitForMilliseconds, _ = strconv.ParseInt(waitFor[:len(waitFor)-3], 0, 64) + waitForMilliseconds = waitForMilliseconds * 60 * 1000 + } + + // Now we seems to be good ... + // First - retrieve the Keycloak URL from Microcks configuration. + mc := connectors.NewMicrocksClient(microcksURL) + keycloakURL, err := mc.GetKeycloakURL() + if err != nil { + fmt.Printf("Got error when invoking Microcks client retrieving config: %s", err) + os.Exit(1) + } + + var oauthToken string = "unauthentifed-token" + if keycloakURL != "null" { + // If Keycloak is enabled, retrieve an OAuth token using Keycloak Client. + kc := connectors.NewKeycloakClient(keycloakURL, keycloakClientID, keycloakClientSecret) + + oauthToken, err = kc.ConnectAndGetToken() + if err != nil { + fmt.Printf("Got error when invoking Keycloack client: %s", err) + os.Exit(1) + } + //fmt.Printf("Retrieve OAuthToken: %s", oauthToken) + } + + // Then - launch the test on Microcks Server. + mc.SetOAuthToken(oauthToken) + + var testResultID string + testResultID, err = mc.CreateTestResult(serviceRef, testEndpoint, runnerType, secretName, waitForMilliseconds, filteredOperations, operationsHeaders, oAuth2Context) + if err != nil { + fmt.Printf("Got error when invoking Microcks client creating Test: %s", err) + os.Exit(1) + } + //fmt.Printf("Retrieve TestResult ID: %s", testResultID) + + // Finally - wait before checking and loop for some time + time.Sleep(1 * time.Second) + + // Add 10.000ms to wait time as it's now representing the server timeout. + now := nowInMilliseconds() + future := now + waitForMilliseconds + 10000 + + var success = false + for nowInMilliseconds() < future { + testResultSummary, err := mc.GetTestResult(testResultID) + if err != nil { + fmt.Printf("Got error when invoking Microcks client check TestResult: %s", err) + os.Exit(1) + } + success = testResultSummary.Success + inProgress := testResultSummary.InProgress + fmt.Printf("MicrocksClient got status for test \"%s\" - success: %s, inProgress: %s \n", testResultID, fmt.Sprint(success), fmt.Sprint(inProgress)) + + if !inProgress { + break + } + + fmt.Println("MicrocksTester waiting for 2 seconds before checking again or exiting.") + time.Sleep(2 * time.Second) + } + + fmt.Printf("Full TestResult details are available here: %s/#/tests/%s \n", strings.Split(microcksURL, "/api")[0], testResultID) + + if !success { + os.Exit(1) + } + }, + } + + testCmd.Flags().StringVar(µcksURL, "microcksURL", "", "Microcks API URL") + testCmd.Flags().StringVar(&keycloakClientID, "keycloakClientId", "", "Keycloak Realm Service Account ClientId") + testCmd.Flags().StringVar(&keycloakClientSecret, "keycloakClientSecret", "", "Keycloak Realm Service Account ClientSecret") + testCmd.Flags().StringVar(&waitFor, "waitFor", "5sec", "Time to wait for test to finish") + testCmd.Flags().StringVar(&secretName, "secretName", "", "Secret to use for connecting test endpoint") + testCmd.Flags().StringVar(&filteredOperations, "filteredOperations", "", "List of operations to launch a test for") + testCmd.Flags().StringVar(&operationsHeaders, "operationsHeaders", "", "Override of operations headers as JSON string") + testCmd.Flags().StringVar(&oAuth2Context, "oAuth2Context", "", "Spec of an OAuth2 client context as JSON string") + testCmd.Flags().BoolVar(&insecureTLS, "insecure", false, "Whether to accept insecure HTTPS connection") + testCmd.Flags().StringVar(&caCertPaths, "caCerts", "", "Comma separated paths of CRT files to add to Root CAs") + testCmd.Flags().BoolVar(&verbose, "verbose", false, "Produce dumps of HTTP exchanges") + + return testCmd } func nowInMilliseconds() int64 { diff --git a/cmd/version.go b/cmd/version.go index 3a98514..6ce7163 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -19,17 +19,18 @@ import ( "fmt" "github.com/microcks/microcks-cli/version" + "github.com/spf13/cobra" ) -type versionCommand struct { -} - -// NewVersionCommand build a new VersionCommand implementation -func NewVersionCommand() Command { - return new(versionCommand) -} +func NewVersionCommand() *cobra.Command { + var command = &cobra.Command{ + Use: "version", + Short: "Print the version number of microkcs CLI", + Long: `Print the version number of microkcs CLI`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Microcks-CLI %s\n", version.Version) + }, + } -// Execute implementation on versionCommand structure -func (c *versionCommand) Execute() { - fmt.Println(version.Version) + return command } diff --git a/go.mod b/go.mod index 149f1f7..9ee032f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/microcks/microcks-cli go 1.12 + +require github.com/spf13/cobra v1.9.1 // indirect diff --git a/go.sum b/go.sum index e69de29..ffae55e 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 557c030..2b65ea6 100644 --- a/main.go +++ b/main.go @@ -1,35 +1,9 @@ package main import ( - "os" - "github.com/microcks/microcks-cli/cmd" ) func main() { - var c cmd.Command - - if len(os.Args) == 1 { - cmd.NewHelpCommand().Execute() - os.Exit(1) - } - - switch os.Args[1] { - case "version": - c = cmd.NewVersionCommand() - case "help": - c = cmd.NewHelpCommand() - case "test": - c = cmd.NewTestCommand() - case "import": - c = cmd.NewImportCommand() - case "import-url": - c = cmd.NewImportURLCommand() - default: - cmd.NewHelpCommand().Execute() - os.Exit(1) - } - - c.Execute() - return + cmd.Execute() }