Skip to content

Commit f39ead0

Browse files
committed
feat: #80 Add support for import URLs by import-url command
Signed-off-by: Harsh4902 <[email protected]>
1 parent ced8532 commit f39ead0

5 files changed

Lines changed: 190 additions & 1 deletion

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313

1414
# Ouput of the build-binaries script
1515
build/_output
16+
17+
# .DS_Store file of MacOS
18+
.DS_Store

cmd/help.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func (c *helpCommand) Execute() {
4040
fmt.Println(" help display this help message")
4141
fmt.Println(" test launch new test on Microcks server")
4242
fmt.Println(" import import API artifacts on Microcks server")
43+
fmt.Println(" import-url import API artifacts from URL on Microcks server")
4344
fmt.Println("")
4445
fmt.Println("Use: microcks-cli test <apiName:apiVersion> <testEndpoint> <runner> \\")
4546
fmt.Println(" --microcksURL=<> --waitFor=5sec \\")

cmd/importURL.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package cmd
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
"strconv"
8+
"strings"
9+
10+
"github.com/microcks/microcks-cli/pkg/config"
11+
"github.com/microcks/microcks-cli/pkg/connectors"
12+
)
13+
14+
type importURLCommand struct {
15+
}
16+
17+
func NewImportURLCommand() Command {
18+
return new(importURLCommand)
19+
}
20+
21+
func (c *importURLCommand) Execute() {
22+
// Parse subcommand args first.
23+
if len(os.Args) < 2 {
24+
fmt.Println("import-url command require <specificationFile1URL[:primary],specificationFile2URL[:primary]> args")
25+
os.Exit(1)
26+
}
27+
28+
specificationFiles := os.Args[2]
29+
30+
// Then parse flags.
31+
importCmd := flag.NewFlagSet("import-url", flag.ExitOnError)
32+
33+
var microcksURL string
34+
var keycloakURL string
35+
var keycloakClientID string
36+
var keycloakClientSecret string
37+
var insecureTLS bool
38+
var caCertPaths string
39+
var verbose bool
40+
41+
importCmd.StringVar(&microcksURL, "microcksURL", "", "Microcks API URL")
42+
importCmd.StringVar(&keycloakClientID, "keycloakClientId", "", "Keycloak Realm Service Account ClientId")
43+
importCmd.StringVar(&keycloakClientSecret, "keycloakClientSecret", "", "Keycloak Realm Service Account ClientSecret")
44+
importCmd.BoolVar(&insecureTLS, "insecure", false, "Whether to accept insecure HTTPS connection")
45+
importCmd.StringVar(&caCertPaths, "caCerts", "", "Comma separated paths of CRT files to add to Root CAs")
46+
importCmd.BoolVar(&verbose, "verbose", false, "Produce dumps of HTTP exchanges")
47+
importCmd.Parse(os.Args[3:])
48+
49+
// Validate presence and values of flags.
50+
if len(microcksURL) == 0 {
51+
fmt.Println("--microcksURL flag is mandatory. Check Usage.")
52+
os.Exit(1)
53+
}
54+
if len(keycloakClientID) == 0 {
55+
fmt.Println("--keycloakClientId flag is mandatory. Check Usage.")
56+
os.Exit(1)
57+
}
58+
if len(keycloakClientSecret) == 0 {
59+
fmt.Println("--keycloakClientSecret flag is mandatory. Check Usage.")
60+
os.Exit(1)
61+
}
62+
63+
// Collect optional HTTPS transport flags.
64+
if insecureTLS {
65+
config.InsecureTLS = true
66+
}
67+
if len(caCertPaths) > 0 {
68+
config.CaCertPaths = caCertPaths
69+
}
70+
if verbose {
71+
config.Verbose = true
72+
}
73+
74+
// Now we seems to be good ...
75+
// First - retrieve the Keycloak URL from Microcks configuration.
76+
mc := connectors.NewMicrocksClient(microcksURL)
77+
keycloakURL, err := mc.GetKeycloakURL()
78+
if err != nil {
79+
fmt.Printf("Got error when invoking Microcks client retrieving config: %s", err)
80+
os.Exit(1)
81+
}
82+
83+
var oauthToken string = "unauthentifed-token"
84+
if keycloakURL != "null" {
85+
// If Keycloak is enabled, retrieve an OAuth token using Keycloak Client.
86+
kc := connectors.NewKeycloakClient(keycloakURL, keycloakClientID, keycloakClientSecret)
87+
88+
oauthToken, err = kc.ConnectAndGetToken()
89+
if err != nil {
90+
fmt.Printf("Got error when invoking Keycloack client: %s", err)
91+
os.Exit(1)
92+
}
93+
}
94+
95+
// Then - for each specificationFile, upload the artifact on Microcks Server.
96+
mc.SetOAuthToken(oauthToken)
97+
98+
sepSpecificationFiles := strings.Split(specificationFiles, ",")
99+
for _, f := range sepSpecificationFiles {
100+
mainArtifact := true
101+
secret := ""
102+
103+
// Check if URL starts with https or http
104+
if strings.HasPrefix(f, "https://") || strings.HasPrefix(f, "http://") {
105+
urlAndMainAtrifactAndSecretName := strings.Split(f, ":")
106+
n := len(urlAndMainAtrifactAndSecretName)
107+
f = urlAndMainAtrifactAndSecretName[0] + ":" + urlAndMainAtrifactAndSecretName[1]
108+
if n > 2 {
109+
val, err := strconv.ParseBool(urlAndMainAtrifactAndSecretName[2])
110+
if err != nil {
111+
fmt.Println(err)
112+
}
113+
mainArtifact = val
114+
}
115+
if n > 3 {
116+
secret = urlAndMainAtrifactAndSecretName[3]
117+
}
118+
}
119+
120+
// Try downloading the artifcat
121+
msg, err := mc.DownloadArtifact(f, mainArtifact, secret)
122+
if err != nil {
123+
fmt.Printf("Got error when invoking Microcks client importing Artifact: %s", err)
124+
os.Exit(1)
125+
}
126+
fmt.Printf("Microcks has discovered '%s'\n", msg)
127+
}
128+
}

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ func main() {
2323
c = cmd.NewTestCommand()
2424
case "import":
2525
c = cmd.NewImportCommand()
26+
case "import-url":
27+
c = cmd.NewImportURLCommand()
2628
default:
2729
cmd.NewHelpCommand().Execute()
2830
os.Exit(1)

pkg/connectors/microcks_client.go

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type MicrocksClient interface {
4444
CreateTestResult(serviceID string, testEndpoint string, runnerType string, secretName string, timeout int64, filteredOperations string, operationsHeaders string, oAuth2Context string) (string, error)
4545
GetTestResult(testResultID string) (*TestResultSummary, error)
4646
UploadArtifact(specificationFilePath string, mainArtifact bool) (string, error)
47+
DownloadArtifact(artifactURL string, mainArtifact bool, secret string) (string, error)
4748
}
4849

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

311-
respBody, err := ioutil.ReadAll(resp.Body)
312+
respBody, err := io.ReadAll(resp.Body)
313+
if err != nil {
314+
panic(err.Error())
315+
}
316+
317+
// Raise exception if not created.
318+
if resp.StatusCode != 201 {
319+
return "", errors.New(string(respBody))
320+
}
321+
322+
return string(respBody), err
323+
}
324+
325+
func (c *microcksClient) DownloadArtifact(artifactURL string, mainArtifact bool, secret string) (string, error) {
326+
327+
// create Multipart Form to add fields
328+
body := &bytes.Buffer{}
329+
writer := multipart.NewWriter(body)
330+
331+
// Add all the form fields
332+
writer.WriteField("url", artifactURL)
333+
writer.WriteField("mainArtifact", strconv.FormatBool(mainArtifact))
334+
if secret != "" {
335+
writer.WriteField("secret", secret)
336+
}
337+
338+
err := writer.Close()
339+
if err != nil {
340+
return "", err
341+
}
342+
343+
// Ensure we have a correct URL.
344+
rel := &url.URL{Path: "artifact/download"}
345+
u := c.APIURL.ResolveReference(rel)
346+
347+
req, err := http.NewRequest("POST", u.String(), body)
348+
if err != nil {
349+
return "", err
350+
}
351+
req.Header.Set("Content-Type", writer.FormDataContentType())
352+
req.Header.Set("Authorization", "Bearer "+c.OAuthToken)
353+
354+
// Dump request if verbose required.
355+
config.DumpRequestIfRequired("Microcks for uploading artifact", req, true)
356+
357+
resp, err := c.httpClient.Do(req)
358+
if err != nil {
359+
return "", err
360+
}
361+
defer resp.Body.Close()
362+
363+
// Dump response if verbose required.
364+
config.DumpResponseIfRequired("Microcks for uploading artifact", resp, true)
365+
366+
respBody, err := io.ReadAll(req.Body)
312367
if err != nil {
313368
panic(err.Error())
314369
}

0 commit comments

Comments
 (0)