You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2021/11/29 10:17:23 UTC

[cloudstack-go] branch main updated: Support 4.x compatibility (#23)

This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 71cd5ea  Support 4.x compatibility (#23)
71cd5ea is described below

commit 71cd5eaae8765e278a9b3e5c4dd25ada65986f42
Author: davidjumani <dj...@gmail.com>
AuthorDate: Mon Nov 29 15:47:17 2021 +0530

    Support 4.x compatibility (#23)
    
    * handle type compatibilty for 4.x baseline
    
    * fix CSLong to be more permissive and add unit test
    
    * Rename CSLong to UUID
    
    Co-authored-by: Xavier MARCELET <xa...@orange.com>
---
 cloudstack/HostService.go      | 18 +++++++++---------
 cloudstack/HostService_test.go |  2 ++
 cloudstack/cloudstack.go       | 21 +++++++++++++++++++++
 cloudstack/cloudstack_test.go  | 32 ++++++++++++++++++++++++++++++++
 generate/generate.go           | 35 +++++++++++++++++++++++++++++++++++
 5 files changed, 99 insertions(+), 9 deletions(-)

diff --git a/cloudstack/HostService.go b/cloudstack/HostService.go
index 3412c9a..b241677 100644
--- a/cloudstack/HostService.go
+++ b/cloudstack/HostService.go
@@ -356,7 +356,7 @@ type AddBaremetalHostResponse struct {
 	Jobstatus                        int                                `json:"jobstatus"`
 	Lastannotated                    string                             `json:"lastannotated"`
 	Lastpinged                       string                             `json:"lastpinged"`
-	Managementserverid               string                             `json:"managementserverid"`
+	Managementserverid               UUID                               `json:"managementserverid"`
 	Memoryallocated                  int64                              `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                              `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string                             `json:"memoryallocatedpercentage"`
@@ -789,7 +789,7 @@ type AddHostResponse struct {
 	Jobstatus                        int                         `json:"jobstatus"`
 	Lastannotated                    string                      `json:"lastannotated"`
 	Lastpinged                       string                      `json:"lastpinged"`
-	Managementserverid               string                      `json:"managementserverid"`
+	Managementserverid               UUID                        `json:"managementserverid"`
 	Memoryallocated                  int64                       `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                       `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string                      `json:"memoryallocatedpercentage"`
@@ -1032,7 +1032,7 @@ type CancelHostMaintenanceResponse struct {
 	Jobstatus                        int                                     `json:"jobstatus"`
 	Lastannotated                    string                                  `json:"lastannotated"`
 	Lastpinged                       string                                  `json:"lastpinged"`
-	Managementserverid               string                                  `json:"managementserverid"`
+	Managementserverid               UUID                                    `json:"managementserverid"`
 	Memoryallocated                  int64                                   `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                                   `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string                                  `json:"memoryallocatedpercentage"`
@@ -1830,7 +1830,7 @@ type FindHostsForMigrationResponse struct {
 	JobID                            string `json:"jobid"`
 	Jobstatus                        int    `json:"jobstatus"`
 	Lastpinged                       string `json:"lastpinged"`
-	Managementserverid               int64  `json:"managementserverid"`
+	Managementserverid               UUID   `json:"managementserverid"`
 	Memoryallocated                  string `json:"memoryallocated"`
 	Memoryallocatedbytes             int64  `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string `json:"memoryallocatedpercentage"`
@@ -2645,7 +2645,7 @@ type Host struct {
 	Jobstatus                        int                         `json:"jobstatus"`
 	Lastannotated                    string                      `json:"lastannotated"`
 	Lastpinged                       string                      `json:"lastpinged"`
-	Managementserverid               string                      `json:"managementserverid"`
+	Managementserverid               UUID                        `json:"managementserverid"`
 	Memoryallocated                  int64                       `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                       `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string                      `json:"memoryallocatedpercentage"`
@@ -3167,7 +3167,7 @@ type HostsMetric struct {
 	Jobstatus                        int                         `json:"jobstatus"`
 	Lastannotated                    string                      `json:"lastannotated"`
 	Lastpinged                       string                      `json:"lastpinged"`
-	Managementserverid               string                      `json:"managementserverid"`
+	Managementserverid               UUID                        `json:"managementserverid"`
 	Memoryallocated                  int64                       `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                       `json:"memoryallocatedbytes"`
 	Memoryallocateddisablethreshold  bool                        `json:"memoryallocateddisablethreshold"`
@@ -3331,7 +3331,7 @@ type PrepareHostForMaintenanceResponse struct {
 	Jobstatus                        int                                         `json:"jobstatus"`
 	Lastannotated                    string                                      `json:"lastannotated"`
 	Lastpinged                       string                                      `json:"lastpinged"`
-	Managementserverid               string                                      `json:"managementserverid"`
+	Managementserverid               UUID                                        `json:"managementserverid"`
 	Memoryallocated                  int64                                       `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                                       `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string                                      `json:"memoryallocatedpercentage"`
@@ -3485,7 +3485,7 @@ type ReconnectHostResponse struct {
 	Jobstatus                        int                             `json:"jobstatus"`
 	Lastannotated                    string                          `json:"lastannotated"`
 	Lastpinged                       string                          `json:"lastpinged"`
-	Managementserverid               string                          `json:"managementserverid"`
+	Managementserverid               UUID                            `json:"managementserverid"`
 	Memoryallocated                  int64                           `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                           `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string                          `json:"memoryallocatedpercentage"`
@@ -3880,7 +3880,7 @@ type UpdateHostResponse struct {
 	Jobstatus                        int                          `json:"jobstatus"`
 	Lastannotated                    string                       `json:"lastannotated"`
 	Lastpinged                       string                       `json:"lastpinged"`
-	Managementserverid               string                       `json:"managementserverid"`
+	Managementserverid               UUID                         `json:"managementserverid"`
 	Memoryallocated                  int64                        `json:"memoryallocated"`
 	Memoryallocatedbytes             int64                        `json:"memoryallocatedbytes"`
 	Memoryallocatedpercentage        string                       `json:"memoryallocatedpercentage"`
diff --git a/cloudstack/HostService_test.go b/cloudstack/HostService_test.go
index 9d529f3..6d4acc2 100644
--- a/cloudstack/HostService_test.go
+++ b/cloudstack/HostService_test.go
@@ -88,6 +88,7 @@ func TestHostService_PrepareHostForMaintenance(t *testing.T) {
 	resp, err := client.Host.PrepareHostForMaintenance(params)
 	if err != nil {
 		t.Errorf("Failed to prepare host for maintenance due to: %v", err)
+		return
 	}
 	if resp.Resourcestate != "PrepareForMaintenance" {
 		t.Errorf("Failed to prepare host for maintenance")
@@ -109,6 +110,7 @@ func TestHostService_CancelHostForMaintenance(t *testing.T) {
 	resp, err := client.Host.CancelHostMaintenance(params)
 	if err != nil {
 		t.Errorf("Failed to cancel host for maintenance due to: %v", err)
+		return
 	}
 	if resp.Resourcestate != "Enabled" {
 		t.Errorf("Failed to cancel host for maintenance")
diff --git a/cloudstack/cloudstack.go b/cloudstack/cloudstack.go
index 0b6896a..4933845 100644
--- a/cloudstack/cloudstack.go
+++ b/cloudstack/cloudstack.go
@@ -35,6 +35,7 @@ import (
 	"net/url"
 	"regexp"
 	"sort"
+	"strconv"
 	"strings"
 	"time"
 
@@ -67,6 +68,26 @@ func (e *CSError) Error() error {
 	return fmt.Errorf("CloudStack API error %d (CSExceptionErrorCode: %d): %s", e.ErrorCode, e.CSErrorCode, e.ErrorText)
 }
 
+type UUID string
+
+func (c UUID) MarshalJSON() ([]byte, error) {
+	return json.Marshal(string(c))
+}
+
+func (c *UUID) UnmarshalJSON(data []byte) error {
+	value := strings.Trim(string(data), "\"")
+	if strings.HasPrefix(string(data), "\"") {
+		*c = UUID(value)
+		return nil
+	}
+	_, err := strconv.ParseInt(value, 10, 64)
+	if err != nil {
+		return err
+	}
+	*c = UUID(value)
+	return nil
+}
+
 type CloudStackClient struct {
 	HTTPGETOnly bool // If `true` only use HTTP GET calls
 
diff --git a/cloudstack/cloudstack_test.go b/cloudstack/cloudstack_test.go
index 8f0b246..23f0f8c 100644
--- a/cloudstack/cloudstack_test.go
+++ b/cloudstack/cloudstack_test.go
@@ -87,3 +87,35 @@ func TestCreateSyncClient(t *testing.T) {
 		t.Errorf("Failed to create Cloudstack Client")
 	}
 }
+
+type UUIDStruct struct {
+	Value UUID `json:"value"`
+}
+
+func TestUUID(t *testing.T) {
+	valLong := `{"value": 4801878}`
+	valString := `{"value": "994801878"}`
+	valBool := `{"value": false}`
+	res := UUIDStruct{}
+
+	res.Value = ""
+	if err := json.Unmarshal([]byte(valLong), &res); err != nil {
+		t.Errorf("could not unserialize long into UUID: %s", err)
+	}
+	if res.Value != "4801878" {
+		t.Errorf("unepected value '%s', expecting 4801878", res.Value)
+	}
+
+	res.Value = ""
+	if err := json.Unmarshal([]byte(valString), &res); err != nil {
+		t.Errorf("could not unserialize string into UUID: %s", err)
+	}
+	if res.Value != "994801878" {
+		t.Errorf("unepected value '%s', expecting 994801878", res.Value)
+	}
+
+	res.Value = ""
+	if err := json.Unmarshal([]byte(valBool), &res); err == nil {
+		t.Errorf("missing expected error when serializing bool into UUID")
+	}
+}
diff --git a/generate/generate.go b/generate/generate.go
index b82a030..a349c82 100644
--- a/generate/generate.go
+++ b/generate/generate.go
@@ -71,6 +71,14 @@ var nestedResponse = map[string]string{
 	"getUploadParamsForVolume":   "getuploadparams",
 }
 
+// longToStringConvertedParams is a prefilled map with the list of
+// response fields that migrated from long to string within
+// the current major baseline. This fields will be parsed from
+// json as string and then fallback on long.
+var longToStringConvertedParams = map[string]bool{
+	"managementserverid": true,
+}
+
 // We prefill this one value to make sure it is not
 // created twice, as this is also a top level type.
 var typeNames = map[string]bool{"Nic": true}
@@ -301,6 +309,27 @@ func (as *allServices) GeneralCode() ([]byte, error) {
 	pn("	return fmt.Errorf(\"CloudStack API error %%d (CSExceptionErrorCode: %%d): %%s\", e.ErrorCode, e.CSErrorCode, e.ErrorText)")
 	pn("}")
 	pn("")
+
+	pn("type UUID string")
+	pn("")
+	pn("func (c UUID) MarshalJSON() ([]byte, error) {")
+	pn("	return json.Marshal(string(c))")
+	pn("}")
+	pn("")
+	pn("func (c *UUID) UnmarshalJSON(data []byte) error {")
+	pn("	value := strings.Trim(string(data), \"\\\"\")")
+	pn("	if strings.HasPrefix(string(data), \"\\\"\") {")
+	pn("		*c = UUID(value)")
+	pn("	  return nil")
+	pn("	}")
+	pn("	_, err := strconv.ParseInt(value, 10, 64)")
+	pn("	if err != nil {")
+	pn("		return err")
+	pn("	}")
+	pn("	*c = UUID(value)")
+	pn("	return nil")
+	pn("}")
+
 	pn("type CloudStackClient struct {")
 	pn("	HTTPGETOnly bool // If `true` only use HTTP GET calls")
 	pn("")
@@ -1802,7 +1831,13 @@ func sourceDir() (string, error) {
 }
 
 func mapType(aName string, pName string, pType string) string {
+	if _, ok := longToStringConvertedParams[pName]; ok {
+		pType = "UUID"
+	}
+
 	switch pType {
+	case "UUID":
+		return "UUID"
 	case "boolean":
 		return "bool"
 	case "short", "int", "integer":