Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@

# Ouput of the build-binaries script
build/_output

# .DS_Store file of MacOS
.DS_Store
1 change: 1 addition & 0 deletions cmd/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (c *helpCommand) Execute() {
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 <apiName:apiVersion> <testEndpoint> <runner> \\")
fmt.Println(" --microcksURL=<> --waitFor=5sec \\")
Expand Down
128 changes: 128 additions & 0 deletions cmd/importURL.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package cmd

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() Command {
return new(importURLCommand)
}

func (c *importURLCommand) Execute() {
// Parse subcommand args first.
if len(os.Args) < 2 {
fmt.Println("import-url command require <specificationFile1URL[:primary],specificationFile2URL[:primary]> args")
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(&microcksURL, "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
}

// 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)
}
}

// 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]
}
}

// 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)
}
}
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ func main() {
c = cmd.NewTestCommand()
case "import":
c = cmd.NewImportCommand()
case "import-url":
c = cmd.NewImportURLCommand()
default:
cmd.NewHelpCommand().Execute()
os.Exit(1)
Expand Down
57 changes: 56 additions & 1 deletion pkg/connectors/microcks_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type MicrocksClient interface {
CreateTestResult(serviceID string, testEndpoint string, runnerType string, secretName string, timeout int64, filteredOperations string, operationsHeaders string, oAuth2Context string) (string, error)
GetTestResult(testResultID string) (*TestResultSummary, error)
UploadArtifact(specificationFilePath string, mainArtifact bool) (string, error)
DownloadArtifact(artifactURL string, mainArtifact bool, secret string) (string, error)
}

// TestResultSummary represents a simple view on Microcks TestResult
Expand Down Expand Up @@ -308,7 +309,61 @@ func (c *microcksClient) UploadArtifact(specificationFilePath string, mainArtifa
// Dump response if verbose required.
config.DumpResponseIfRequired("Microcks for uploading artifact", resp, true)

respBody, err := ioutil.ReadAll(resp.Body)
respBody, err := io.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
}

// Raise exception if not created.
if resp.StatusCode != 201 {
return "", errors.New(string(respBody))
}

return string(respBody), err
}

func (c *microcksClient) DownloadArtifact(artifactURL string, mainArtifact bool, secret string) (string, error) {

// create Multipart Form to add fields
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

// Add all the form fields
writer.WriteField("url", artifactURL)
writer.WriteField("mainArtifact", strconv.FormatBool(mainArtifact))
if secret != "" {
writer.WriteField("secret", secret)
}

err := writer.Close()
if err != nil {
return "", err
}

// Ensure we have a correct URL.
rel := &url.URL{Path: "artifact/download"}
u := c.APIURL.ResolveReference(rel)

req, err := http.NewRequest("POST", u.String(), body)
if err != nil {
return "", err
}
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Authorization", "Bearer "+c.OAuthToken)

// Dump request if verbose required.
config.DumpRequestIfRequired("Microcks for uploading artifact", req, true)

resp, err := c.httpClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()

// Dump response if verbose required.
config.DumpResponseIfRequired("Microcks for uploading artifact", resp, true)

respBody, err := io.ReadAll(req.Body)
if err != nil {
panic(err.Error())
}
Expand Down