diff --git a/.gitignore b/.gitignore index ba6efc8..6e2bce3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bin/ -scalr \ No newline at end of file +scalr +.vscode/ \ No newline at end of file diff --git a/command.go b/command.go index 6ec2f2c..a790136 100644 --- a/command.go +++ b/command.go @@ -25,7 +25,7 @@ type Parameter struct { value *string } -//Rename flags with odd names that causes issues in some shells +// Rename flags with odd names that causes issues in some shells func renameFlag(name string) string { name = strings.ReplaceAll(name, "[", "-") name = strings.ReplaceAll(name, "]", "") @@ -88,7 +88,7 @@ func parseCommand(format string, verbose bool) { } //TODO: If code reaches here, means support for new field-type is needed! - fmt.Println("IGNORE UNSUPPORTED FIELD", parameter.Value.Name, parameter.Value.Schema.Value.Type) + fmt.Println("IGNORE UNSUPPORTED FIELD. PLEASE LET THE MAINTAINER KNOW!", parameter.Value.Name, parameter.Value.Schema.Value.Type) } @@ -253,9 +253,17 @@ func parseCommand(format string, verbose bool) { } else { - if len(missingBody) > 0 || len(missing) > 0 { - fmt.Printf("Missing required flag(s): %s\n", append(missing, missingBody...)) - os.Exit(1) + // FIXME: Disable required attributes for PATCH requests as the specs are incorrect + if method != "PATCH" { + if len(missingBody) > 0 || len(missing) > 0 { + fmt.Printf("Missing required flag(s): %s\n", append(missing, missingBody...)) + os.Exit(1) + } + } else { + if len(missing) > 0 { + fmt.Printf("Missing required flag(s): %s\n", missing) + os.Exit(1) + } } if action.RequestBody != nil { @@ -301,6 +309,8 @@ func parseCommand(format string, verbose bool) { if *flags[id].value != "" { required = true + } else { + required = false } } @@ -396,7 +406,7 @@ func parseCommand(format string, verbose bool) { os.Exit(1) } -//Helper function to shorter flag-names for convenience +// Helper function to shorter flag-names for convenience func shortenName(flagName string) string { //If this is an attribute, strip prefix to shorten flag-names @@ -413,7 +423,7 @@ func shortenName(flagName string) string { return flagName } -//Make a request to the Scalr API +// Make a request to the Scalr API func callAPI(method string, uri string, query url.Values, body string, contentType string, verbose bool, format string) { output := gabs.New() @@ -507,7 +517,7 @@ func callAPI(method string, uri string, query url.Values, body string, contentTy } -//Parse error response and show it to user +// Parse error response and show it to user func showError(resBody []byte) { jsonParsed, err := gabs.ParseJSON(resBody) @@ -520,7 +530,7 @@ func showError(resBody []byte) { os.Exit(1) } -//Data JSON:API data to make it easier to work with +// Data JSON:API data to make it easier to work with func parseData(response *gabs.Container) *gabs.Container { output := gabs.New() diff --git a/help.go b/help.go index 5cde35c..e967a8f 100644 --- a/help.go +++ b/help.go @@ -39,7 +39,7 @@ func printInfo() { } -//Prints CLI help +// Prints CLI help func printHelp() { //Help for specified command @@ -115,7 +115,7 @@ func printHelpCommand(command string) { doc := loadAPI() for _, path := range doc.Paths { - for _, object := range path.Operations() { + for method, object := range path.Operations() { if command != strings.ReplaceAll(object.OperationID, "_", "-") { continue @@ -170,7 +170,12 @@ func printHelpCommand(command string) { if object.RequestBody.Value.Content[contentType].Schema != nil { //Recursively collect all required fields - requiredFlags := collectRequired(object.RequestBody.Value.Content[contentType].Schema.Value) + requiredFlags := map[string]bool{} + + // FIXME: Disable required attributes for PATCH requests as the specs are incorrect + if method != "PATCH" { + requiredFlags = collectRequired(object.RequestBody.Value.Content[contentType].Schema.Value) + } relationshipDesc := make(map[string]string) diff --git a/main.go b/main.go index 728352e..a2277d3 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "os" @@ -143,7 +143,7 @@ func loadConfigScalr(hostname string, token string, account string) (string, str home = home + "/.scalr/" config := "scalr.conf" - content, err := ioutil.ReadFile(home + config) + content, err := os.ReadFile(home + config) if err != nil { return hostname, token, account } @@ -171,7 +171,7 @@ func loadConfigTerraform(hostname string, token string) (string, string) { home, err := os.UserHomeDir() checkErr(err) - content, err := ioutil.ReadFile(home + "/.terraform.d/credentials.tfrc.json") + content, err := os.ReadFile(home + "/.terraform.d/credentials.tfrc.json") if err != nil { return hostname, token } @@ -284,7 +284,7 @@ func downloadFile(URL string, fileName string) { checkErr(err) defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) checkErr(err) if resp.StatusCode != 200 { diff --git a/main_test.go b/main_test.go index 9254f38..d273b58 100644 --- a/main_test.go +++ b/main_test.go @@ -4,14 +4,16 @@ import ( "bytes" "os" "os/exec" + "strings" "testing" "github.com/Jeffail/gabs/v2" ) -//Run scalr binary and capture JSON output -func run_test(params ...string) (string, *gabs.Container, error) { +// Run scalr binary and capture JSON output +func run_test(t *testing.T, params ...string) (string, *gabs.Container, error) { + t.Log(strings.Join(params, " ")) cmd := exec.Command("./scalr", params...) var out bytes.Buffer @@ -84,9 +86,24 @@ func Test_Tags(t *testing.T) { account_id, _ := os.LookupEnv("SCALR_ACCOUNT") name := "test-tag" + t.Log("List all tags") + + _, output, err := run_test(t, "list-tags") + + if err != nil { + t.Fatalf(output.String()) + } + + for _, child := range output.Children() { + if child.Search("name").Data().(string) == name { + t.Log("Test-tag already exists, delete") + run_test(t, "delete-tag", "-tag="+child.Search("id").Data().(string)) + } + } + t.Log("Create tag") - _, output, err := run_test("create-tag", "-account-id="+account_id, "-name="+name) + _, output, err = run_test(t, "create-tag", "-account-id="+account_id, "-name="+name) if err != nil { t.Fatalf(output.String()) @@ -96,7 +113,7 @@ func Test_Tags(t *testing.T) { t.Log("Get tag") - message, output, err := run_test("get-tag", "-tag="+tag_id) + message, output, err := run_test(t, "get-tag", "-tag="+tag_id) if err != nil { t.Fatalf(message) @@ -108,7 +125,7 @@ func Test_Tags(t *testing.T) { t.Log("Update tag") - message, _, err = run_test("update-tag", "-tag="+tag_id, "-name="+name+"-2") + message, _, err = run_test(t, "update-tag", "-tag="+tag_id, "-name="+name+"-2") if err != nil { t.Fatalf(message) @@ -116,7 +133,7 @@ func Test_Tags(t *testing.T) { t.Log("Delete tag") - message, _, err = run_test("delete-tag", "-tag="+tag_id) + message, _, err = run_test(t, "delete-tag", "-tag="+tag_id) if err != nil { t.Fatalf(message) @@ -124,7 +141,7 @@ func Test_Tags(t *testing.T) { t.Log("Confirm tag deletion") - _, _, err = run_test("get-tag", "-tag="+tag_id) + _, _, err = run_test(t, "get-tag", "-tag="+tag_id) if err == nil { t.Fatalf("Tag still exists") @@ -139,9 +156,24 @@ func Test_Environment(t *testing.T) { account_id, _ := os.LookupEnv("SCALR_ACCOUNT") name := "automated-test" + t.Log("List all environments") + + _, output, err := run_test(t, "list-environments") + + if err != nil { + t.Fatalf(output.String()) + } + + for _, child := range output.Children() { + if child.Search("name").Data().(string) == name { + t.Log("Environment already exists, delete") + run_test(t, "delete-environment", "-environment="+child.Search("id").Data().(string)) + } + } + t.Log("Create environment") - _, output, err := run_test("create-environment", "-account-id="+account_id, "-name="+name) + _, output, err = run_test(t, "create-environment", "-account-id="+account_id, "-name="+name) if err != nil { t.Fatalf(output.String()) @@ -155,7 +187,7 @@ func Test_Environment(t *testing.T) { t.Log("Get environment") - message, output, err := run_test("get-environment", "-environment="+env_id) + message, output, err := run_test(t, "get-environment", "-environment="+env_id) if err != nil { t.Fatalf(message) @@ -167,7 +199,7 @@ func Test_Environment(t *testing.T) { t.Log("Update environment") - _, output, _ = run_test("update-environment", "-environment="+env_id, "-account-id="+account_id, "-name="+name+"-2", "-cost-estimation-enabled=false") + _, output, _ = run_test(t, "update-environment", "-environment="+env_id, "-account-id="+account_id, "-name="+name+"-2", "-cost-estimation-enabled=false") if output.Search("cost-estimation-enabled").Data() == true { t.Fatalf("Failed to update environment") @@ -181,7 +213,7 @@ func Test_Environment(t *testing.T) { t.Log("Delete environment") - message, _, err = run_test("delete-environment", "-environment="+env_id) + message, _, err = run_test(t, "delete-environment", "-environment="+env_id) if err != nil { t.Fatalf(message) @@ -189,7 +221,7 @@ func Test_Environment(t *testing.T) { t.Log("Confirm environment deletion") - _, _, err = run_test("get-environment", "-environment="+env_id) + _, _, err = run_test(t, "get-environment", "-environment="+env_id) if err == nil { t.Fatalf("Environment still exists") @@ -205,7 +237,7 @@ func Test_Workspace(t *testing.T) { t.Log("Create environment") - _, output, err := run_test("create-environment", "-account-id="+account_id, "-name="+environment_name) + _, output, err := run_test(t, "create-environment", "-account-id="+account_id, "-name="+environment_name) if err != nil { t.Fatalf(output.String()) @@ -219,7 +251,7 @@ func Test_Workspace(t *testing.T) { t.Log("Create workspace") - _, output, err = run_test("create-workspace", "-environment-id="+env_id, "-name="+workspace_name) + _, output, err = run_test(t, "create-workspace", "-environment-id="+env_id, "-name="+workspace_name) if err != nil { t.Fatalf(output.String()) @@ -233,7 +265,7 @@ func Test_Workspace(t *testing.T) { t.Log("Get workspace") - message, output, err := run_test("get-workspace", "-workspace="+workspace_id) + message, output, err := run_test(t, "get-workspace", "-workspace="+workspace_id) if err != nil { t.Fatalf(message) @@ -245,7 +277,7 @@ func Test_Workspace(t *testing.T) { t.Log("Update workspace") - _, output, err = run_test("update-workspace", "-workspace="+workspace_id, "-name="+workspace_name+"-2") + _, output, err = run_test(t, "update-workspace", "-workspace="+workspace_id, "-name="+workspace_name+"-2") if err != nil { t.Fatalf(output.String()) @@ -253,7 +285,7 @@ func Test_Workspace(t *testing.T) { t.Log("Lock workspace") - _, output, err = run_test("lock-workspace", "-workspace="+workspace_id) + _, output, err = run_test(t, "lock-workspace", "-workspace="+workspace_id) if err != nil { t.Fatalf(output.String()) @@ -261,7 +293,7 @@ func Test_Workspace(t *testing.T) { t.Log("Unlock workspace") - _, output, err = run_test("unlock-workspace", "-workspace="+workspace_id) + _, output, err = run_test(t, "unlock-workspace", "-workspace="+workspace_id) if err != nil { t.Fatalf(output.String()) @@ -273,7 +305,7 @@ func Test_Workspace(t *testing.T) { t.Log("Delete workspace") - message, _, err = run_test("delete-workspace", "-workspace="+workspace_id) + message, _, err = run_test(t, "delete-workspace", "-workspace="+workspace_id) if err != nil { t.Fatalf(message) @@ -281,7 +313,7 @@ func Test_Workspace(t *testing.T) { t.Log("Confirm workspace deletion") - _, _, err = run_test("get-workspace", "-workspace="+workspace_id) + _, _, err = run_test(t, "get-workspace", "-workspace="+workspace_id) if err == nil { t.Fatalf("workspace still exists") @@ -289,7 +321,7 @@ func Test_Workspace(t *testing.T) { t.Log("Delete environment") - message, _, err = run_test("delete-environment", "-environment="+env_id) + message, _, err = run_test(t, "delete-environment", "-environment="+env_id) if err != nil { t.Fatalf(message)