From 29ffc4ffd584374108a68562c2e7462a1c0d365f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Mon, 20 Nov 2023 15:16:25 +0100 Subject: [PATCH 1/6] Add status code check for 410 gone to avoid error --- api/instance.go | 41 +++++++++++++++++++++++++++++------------ api/vpc.go | 30 ++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/api/instance.go b/api/instance.go index 355142b..33f5aed 100644 --- a/api/instance.go +++ b/api/instance.go @@ -164,27 +164,39 @@ func (api *API) ReadInstance(instanceID string) (map[string]interface{}, error) if err != nil { return nil, err } - if response.StatusCode != 200 { - return nil, fmt.Errorf("ReadInstance failed, status: %v, message: %s", response.StatusCode, failed) - } - return data, nil + switch response.StatusCode { + case 200: + return data, nil + case 410: + log.Printf("[WARN] go-api::instance::read status: 410, message: Gone") + return nil, nil + default: + return nil, fmt.Errorf("ReadInstance failed, status: %v, message: %s", + response.StatusCode, failed) + } } func (api *API) ReadInstances() ([]map[string]interface{}, error) { var data []map[string]interface{} failed := make(map[string]interface{}) response, err := api.sling.New().Get("/api/instances").Receive(&data, &failed) - log.Printf("[DEBUG] go-api::instance::read data: %v", data) + log.Printf("[DEBUG] go-api::instance::list data: %v", data) if err != nil { return nil, err } - if response.StatusCode != 200 { - return nil, fmt.Errorf("ReadInstances failed, status: %v, message: %s", response.StatusCode, failed) - } - return data, nil + switch response.StatusCode { + case 200: + return data, nil + case 410: + log.Printf("[WARN] go-api::instance::list status: 410, message: Gone") + return nil, nil + default: + return nil, fmt.Errorf("ReadInstances failed, status: %v, message: %s", + response.StatusCode, failed) + } } func (api *API) UpdateInstance(instanceID string, params map[string]interface{}) error { @@ -212,11 +224,16 @@ func (api *API) DeleteInstance(instanceID string, keep_vpc bool) error { if err != nil { return err } - if response.StatusCode != 204 { + + switch response.StatusCode { + case 204: + return api.waitUntilDeletion(instanceID) + case 410: + log.Printf("[WARN] go-api::instance::delete status: 410, message: Gone") + return nil + default: return fmt.Errorf("DeleteInstance failed, status: %v, message: %s", response.StatusCode, failed) } - - return api.waitUntilDeletion(instanceID) } func (api *API) UrlInformation(url string) map[string]interface{} { diff --git a/api/vpc.go b/api/vpc.go index 6f8655f..d23a584 100644 --- a/api/vpc.go +++ b/api/vpc.go @@ -84,13 +84,18 @@ func (api *API) ReadVpcInstance(vpcID string) (map[string]interface{}, error) { if err != nil { return nil, err } - if response.StatusCode != 200 { - return nil, fmt.Errorf("ReadVpcInstance failed, status: %v, message: %v", response.StatusCode, failed) - } - data_temp, _ := api.readVpcName(vpcID) - data["vpc_name"] = data_temp["name"] - return data, nil + switch response.StatusCode { + case 200: + data_temp, _ := api.readVpcName(vpcID) + data["vpc_name"] = data_temp["name"] + return data, nil + case 410: + return nil, nil + default: + return nil, fmt.Errorf("ReadVpcInstance failed, status: %v, message: %v", + response.StatusCode, failed) + } } func (api *API) UpdateVpcInstance(vpcID string, params map[string]interface{}) error { @@ -114,13 +119,18 @@ func (api *API) DeleteVpcInstance(vpcID string) error { log.Printf("[DEBUG] go-api::vpc::delete vpc ID: %s", vpcID) path := fmt.Sprintf("api/vpcs/%s", vpcID) response, err := api.sling.New().Delete(path).Receive(nil, &failed) - + log.Printf("[DEBUG] go-api::vpc::delete vpc ID: %s, response: %v", vpcID, response.StatusCode) if err != nil { return err } - if response.StatusCode != 204 { + + switch response.StatusCode { + case 204: + return nil + case 410: + log.Printf("[WARN] go-api::vpc::delete status: 410, message: Gone") + return nil + default: return fmt.Errorf("DeleteVpcInstance failed, status: %v, message: %v", response.StatusCode, failed) } - - return nil } From 3858d00e478b0f3f2805c1b578663fa26acf2340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Wed, 29 Nov 2023 16:20:45 +0100 Subject: [PATCH 2/6] Handle 410 (gone) for update --- api/instance.go | 24 +++++++++++++++--------- api/vpc.go | 21 ++++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/api/instance.go b/api/instance.go index 33f5aed..93e3620 100644 --- a/api/instance.go +++ b/api/instance.go @@ -169,7 +169,7 @@ func (api *API) ReadInstance(instanceID string) (map[string]interface{}, error) case 200: return data, nil case 410: - log.Printf("[WARN] go-api::instance::read status: 410, message: Gone") + log.Printf("[WARN] go-api::instance::read status: 410, message: The instance has been deleted") return nil, nil default: return nil, fmt.Errorf("ReadInstance failed, status: %v, message: %s", @@ -191,7 +191,7 @@ func (api *API) ReadInstances() ([]map[string]interface{}, error) { case 200: return data, nil case 410: - log.Printf("[WARN] go-api::instance::list status: 410, message: Gone") + log.Printf("[WARN] go-api::instance::list status: 410, message: The instance has been deleted") return nil, nil default: return nil, fmt.Errorf("ReadInstances failed, status: %v, message: %s", @@ -204,15 +204,20 @@ func (api *API) UpdateInstance(instanceID string, params map[string]interface{}) log.Printf("[DEBUG] go-api::instance::update instance ID: %v, params: %v", instanceID, params) path := fmt.Sprintf("api/instances/%v", instanceID) response, err := api.sling.New().Put(path).BodyJSON(params).Receive(nil, &failed) - if err != nil { return err } - if response.StatusCode != 200 { - return fmt.Errorf("UpdateInstance failed, status: %v, message: %s", response.StatusCode, failed) - } - return api.waitUntilAllNodesReady(instanceID) + switch response.StatusCode { + case 200: + return api.waitUntilAllNodesReady(instanceID) + case 410: + log.Printf("[WARN] go-api::instance::update status: 410, message: The instance has been deleted") + return nil + default: + return fmt.Errorf("UpdateInstance failed, status: %v, message: %s", + response.StatusCode, failed) + } } func (api *API) DeleteInstance(instanceID string, keep_vpc bool) error { @@ -229,10 +234,11 @@ func (api *API) DeleteInstance(instanceID string, keep_vpc bool) error { case 204: return api.waitUntilDeletion(instanceID) case 410: - log.Printf("[WARN] go-api::instance::delete status: 410, message: Gone") + log.Printf("[WARN] go-api::instance::delete status: 410, message: The instance has been deleted") return nil default: - return fmt.Errorf("DeleteInstance failed, status: %v, message: %s", response.StatusCode, failed) + return fmt.Errorf("DeleteInstance failed, status: %v, message: %s", + response.StatusCode, failed) } } diff --git a/api/vpc.go b/api/vpc.go index d23a584..3c82c78 100644 --- a/api/vpc.go +++ b/api/vpc.go @@ -91,6 +91,7 @@ func (api *API) ReadVpcInstance(vpcID string) (map[string]interface{}, error) { data["vpc_name"] = data_temp["name"] return data, nil case 410: + log.Printf("[WARN] go-api::vpc::read status: 410, message: The VPC has been deleted") return nil, nil default: return nil, fmt.Errorf("ReadVpcInstance failed, status: %v, message: %v", @@ -103,15 +104,20 @@ func (api *API) UpdateVpcInstance(vpcID string, params map[string]interface{}) e log.Printf("[DEBUG] go-api::instance::update vpc ID: %s, params: %v", vpcID, params) path := fmt.Sprintf("api/vpcs/%s", vpcID) response, err := api.sling.New().Put(path).BodyJSON(params).Receive(nil, &failed) - if err != nil { return err } - if response.StatusCode != 200 { - return fmt.Errorf("UpdateInstance failed, status: %v, message: %v", response.StatusCode, failed) - } - return nil + switch response.StatusCode { + case 200: + return nil + case 410: + log.Printf("[WARN] go-api::vpc::update status: 410, message: The VPC has been deleted") + return nil + default: + return fmt.Errorf("UpdateInstance failed, status: %v, message: %v", + response.StatusCode, failed) + } } func (api *API) DeleteVpcInstance(vpcID string) error { @@ -128,9 +134,10 @@ func (api *API) DeleteVpcInstance(vpcID string) error { case 204: return nil case 410: - log.Printf("[WARN] go-api::vpc::delete status: 410, message: Gone") + log.Printf("[WARN] go-api::vpc::delete status: 410, message: The VPC has been deleted") return nil default: - return fmt.Errorf("DeleteVpcInstance failed, status: %v, message: %v", response.StatusCode, failed) + return fmt.Errorf("DeleteVpcInstance failed, status: %v, message: %v", + response.StatusCode, failed) } } From 8887588575dc29cad62cfcd9e2eb41500cbd934e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Wed, 29 Nov 2023 16:33:35 +0100 Subject: [PATCH 3/6] Clean up VPC code --- api/vpc.go | 118 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/api/vpc.go b/api/vpc.go index 3c82c78..258c505 100644 --- a/api/vpc.go +++ b/api/vpc.go @@ -1,7 +1,6 @@ package api import ( - "errors" "fmt" "log" "strconv" @@ -9,78 +8,92 @@ import ( ) func (api *API) waitUntilVpcReady(vpcID string) error { + var ( + data map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("api/vpcs/%s/vpc-peering/info", vpcID) + ) + log.Printf("[DEBUG] go-api::vpc::waitUntilVpcReady waiting") - data := make(map[string]interface{}) - failed := make(map[string]interface{}) for { - path := fmt.Sprintf("api/vpcs/%s/vpc-peering/info", vpcID) + time.Sleep(10 * time.Second) response, err := api.sling.New().Get(path).Receive(&data, &failed) - if err != nil { return err } - if response.StatusCode == 400 { - log.Printf("[WARN] go-api::vpc::waitUntilVpcReady status: %v, message: %s", response.StatusCode, failed) - } else if response.StatusCode != 200 { - return fmt.Errorf("waitUntilReady failed, status: %v, message: %s", response.StatusCode, failed) - } else if response.StatusCode == 200 { + + switch response.StatusCode { + case 200: return nil + case 400: + log.Printf("[WARN] go-api::vpc::waitUntilVpcReady status: %v, message: %s", + response.StatusCode, failed) + default: + return fmt.Errorf("waitUntilReady failed, status: %v, message: %s", + response.StatusCode, failed) } - - time.Sleep(10 * time.Second) } } func (api *API) readVpcName(vpcID string) (map[string]interface{}, error) { - data := make(map[string]interface{}) - failed := make(map[string]interface{}) - path := fmt.Sprintf("api/vpcs/%s/vpc-peering/info", vpcID) - response, err := api.sling.New().Get(path).Receive(&data, &failed) + var ( + data map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("api/vpcs/%s/vpc-peering/info", vpcID) + ) + response, err := api.sling.New().Get(path).Receive(&data, &failed) if err != nil { return nil, err } - if response.StatusCode != 200 { - return nil, fmt.Errorf("readVpcName failed, status: %v, message: %s", response.StatusCode, failed) + + switch response.StatusCode { + case 200: + return data, nil + default: + return nil, fmt.Errorf("readVpcName failed, status: %v, message: %s", + response.StatusCode, failed) } - return data, nil } func (api *API) CreateVpcInstance(params map[string]interface{}) (map[string]interface{}, error) { - data := make(map[string]interface{}) - failed := make(map[string]interface{}) - log.Printf("[DEBUG] go-api::vpc::create params: %v", params) - response, err := api.sling.New().Post("/api/vpcs").BodyJSON(params).Receive(&data, &failed) + var ( + data map[string]interface{} + failed map[string]interface{} + path = "/api/vpcs" + ) + log.Printf("[DEBUG] go-api::vpc::create params: %v", params) + response, err := api.sling.New().Post(path).BodyJSON(params).Receive(&data, &failed) if err != nil { return nil, err } - if response.StatusCode != 200 { - return nil, fmt.Errorf("CreateVpcInstance failed, status: %v, message: %s", response.StatusCode, failed) - } - if id, ok := data["id"]; ok { - data["id"] = strconv.FormatFloat(id.(float64), 'f', 0, 64) - log.Printf("[DEBUG] go-api::vpc::create id set: %v", data["id"]) - } else { - msg := fmt.Sprintf("go-api::vpc::create Invalid instance identifier: %v", data["id"]) - log.Printf("[ERROR] %s", msg) - return nil, errors.New(msg) + switch response.StatusCode { + case 200: + if id, ok := data["id"]; ok { + data["id"] = strconv.FormatFloat(id.(float64), 'f', 0, 64) + log.Printf("[DEBUG] go-api::vpc::create id set: %v", data["id"]) + } else { + return nil, fmt.Errorf("create VPC invalid instance identifier: %v", data["id"]) + } + api.waitUntilVpcReady(data["id"].(string)) + return data, nil + default: + return nil, fmt.Errorf("create VPC failed, status: %v, message: %s", + response.StatusCode, failed) } - - api.waitUntilVpcReady(data["id"].(string)) - return data, nil } func (api *API) ReadVpcInstance(vpcID string) (map[string]interface{}, error) { - data := make(map[string]interface{}) - failed := make(map[string]interface{}) - log.Printf("[DEBUG] go-api::vpc::read vpc ID: %s", vpcID) + var ( + data map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("/api/vpcs/%s", vpcID) + ) - path := fmt.Sprintf("/api/vpcs/%s", vpcID) + log.Printf("[DEBUG] go-api::vpc::read vpc ID: %s", vpcID) response, err := api.sling.New().Path(path).Receive(&data, &failed) - log.Printf("[DEBUG] go-api::vpc::read data: %v", data) - if err != nil { return nil, err } @@ -94,15 +107,18 @@ func (api *API) ReadVpcInstance(vpcID string) (map[string]interface{}, error) { log.Printf("[WARN] go-api::vpc::read status: 410, message: The VPC has been deleted") return nil, nil default: - return nil, fmt.Errorf("ReadVpcInstance failed, status: %v, message: %v", + return nil, fmt.Errorf("read VPC failed, status: %v, message: %v", response.StatusCode, failed) } } func (api *API) UpdateVpcInstance(vpcID string, params map[string]interface{}) error { - failed := make(map[string]interface{}) + var ( + failed map[string]interface{} + path = fmt.Sprintf("api/vpcs/%s", vpcID) + ) + log.Printf("[DEBUG] go-api::instance::update vpc ID: %s, params: %v", vpcID, params) - path := fmt.Sprintf("api/vpcs/%s", vpcID) response, err := api.sling.New().Put(path).BodyJSON(params).Receive(nil, &failed) if err != nil { return err @@ -115,17 +131,19 @@ func (api *API) UpdateVpcInstance(vpcID string, params map[string]interface{}) e log.Printf("[WARN] go-api::vpc::update status: 410, message: The VPC has been deleted") return nil default: - return fmt.Errorf("UpdateInstance failed, status: %v, message: %v", + return fmt.Errorf("update VPC failed, status: %v, message: %v", response.StatusCode, failed) } } func (api *API) DeleteVpcInstance(vpcID string) error { - failed := make(map[string]interface{}) + var ( + failed map[string]interface{} + path = fmt.Sprintf("api/vpcs/%s", vpcID) + ) + log.Printf("[DEBUG] go-api::vpc::delete vpc ID: %s", vpcID) - path := fmt.Sprintf("api/vpcs/%s", vpcID) response, err := api.sling.New().Delete(path).Receive(nil, &failed) - log.Printf("[DEBUG] go-api::vpc::delete vpc ID: %s, response: %v", vpcID, response.StatusCode) if err != nil { return err } @@ -137,7 +155,7 @@ func (api *API) DeleteVpcInstance(vpcID string) error { log.Printf("[WARN] go-api::vpc::delete status: 410, message: The VPC has been deleted") return nil default: - return fmt.Errorf("DeleteVpcInstance failed, status: %v, message: %v", + return fmt.Errorf("delete VPC failed, status: %v, message: %v", response.StatusCode, failed) } } From e62f4851ee30d750890b2cf0fff8bdab116c7089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Wed, 29 Nov 2023 16:59:12 +0100 Subject: [PATCH 4/6] Clean up Instance code --- api/instance.go | 171 +++++++++++++++++++++++++++++------------------- 1 file changed, 103 insertions(+), 68 deletions(-) diff --git a/api/instance.go b/api/instance.go index 93e3620..816961b 100644 --- a/api/instance.go +++ b/api/instance.go @@ -1,7 +1,6 @@ package api import ( - "errors" "fmt" "log" "regexp" @@ -10,53 +9,64 @@ import ( ) func (api *API) waitUntilReady(instanceID string) (map[string]interface{}, error) { + var ( + data map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("/api/instances/%s", instanceID) + ) + log.Printf("[DEBUG] go-api::instance::waitUntilReady waiting") - data := make(map[string]interface{}) - failed := make(map[string]interface{}) + for { time.Sleep(10 * time.Second) - response, err := api.sling.New().Path("/api/instances/").Get(instanceID).Receive(&data, &failed) - + response, err := api.sling.New().Path(path).Receive(&data, &failed) if err != nil { return nil, err } - if response.StatusCode != 200 { - return nil, fmt.Errorf("waitUntilReady failed, status: %v, message: %s", response.StatusCode, failed) - } - if data["ready"] == true { - data["id"] = instanceID - return data, nil + + switch response.StatusCode { + case 200: + if data["ready"] == true { + data["id"] = instanceID + return data, nil + } + default: + return nil, fmt.Errorf("waitUntilReady failed, status: %v, message: %s", + response.StatusCode, failed) } } } func (api *API) waitUntilAllNodesReady(instanceID string) error { - var data []map[string]interface{} - failed := make(map[string]interface{}) + var ( + data []map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("api/instances/%v/nodes", instanceID) + ) for { time.Sleep(15 * time.Second) - path := fmt.Sprintf("api/instances/%v/nodes", instanceID) _, err := api.sling.New().Path(path).Receive(&data, &failed) if err != nil { - log.Printf("[ERROR] go-api::instance::waitUntilAllNodesReady error: %v", err) return err } + log.Printf("[DEBUG] go-api::instance::waitUntilAllNodesReady numberOfNodes: %v", len(data)) - log.Printf("[DEBUG] go-api::instance::waitUntilAllNodesReady data: %v", data) ready := true for _, node := range data { - log.Printf("[DEBUG] go-api::instance::waitUntilAllNodesReady ready: %v, configured: %v", ready, node["configured"]) + log.Printf("[DEBUG] go-api::instance::waitUntilAllNodesReady ready: %v, configured: %v", + ready, node["configured"]) ready = ready && node["configured"].(bool) } - log.Printf("[DEBUG] go-api::instance::waitUntilAllNodesReady ready: %v", ready) if ready { return nil } } } -func (api *API) waitWithTimeoutUntilAllNodesConfigured(instanceID string, attempt, sleep, timeout int) error { +func (api *API) waitWithTimeoutUntilAllNodesConfigured(instanceID string, attempt, sleep, + timeout int) error { + var ( data []map[string]interface{} failed map[string]interface{} @@ -74,7 +84,8 @@ func (api *API) waitWithTimeoutUntilAllNodesConfigured(instanceID string, attemp ready := true for _, node := range data { - log.Printf("[DEBUG] go-api::instance::waitWithTimeoutUntilAllNodesConfigured ready: %v, configured: %v", ready, node["configured"]) + log.Printf("[DEBUG] go-api::instance::waitWithTimeoutUntilAllNodesConfigured ready: %v, configured: %v", + ready, node["configured"]) ready = ready && node["configured"].(bool) } log.Printf("[DEBUG] go-api::instance::waitWithTimeoutUntilAllNodesConfigured ready: %v", ready) @@ -87,17 +98,23 @@ func (api *API) waitWithTimeoutUntilAllNodesConfigured(instanceID string, attemp } func (api *API) waitUntilDeletion(instanceID string) error { + var ( + data map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("/api/instances/%s", instanceID) + ) + log.Printf("[DEBUG] go-api::instance::waitUntilDeletion waiting") - data := make(map[string]interface{}) - failed := make(map[string]interface{}) for { time.Sleep(10 * time.Second) - response, err := api.sling.New().Path("/api/instances/").Get(instanceID).Receive(&data, &failed) - + response, err := api.sling.New().Path(path).Receive(&data, &failed) if err != nil { log.Printf("[DEBUG] go-api::instance::waitUntilDeletion error: %v", err) return err } + + // TODO: Check how this works with the new API and will a change to 410 be an issue for + // older versions. if response.StatusCode == 404 { log.Print("[DEBUG] go-api::instance::waitUntilDeletion deleted") return nil @@ -106,61 +123,70 @@ func (api *API) waitUntilDeletion(instanceID string) error { } func (api *API) numberOfNodes(instanceID string) (int, error) { - data := make(map[string]interface{}) - failed := make(map[string]interface{}) - path := fmt.Sprintf("api/instances/%v/nodes", instanceID) + var ( + data map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("api/instances/%v/nodes", instanceID) + ) + response, err := api.sling.New().Path(path).Receive(&data, &failed) log.Printf("[DEBUG] go-api::instances::numberOfNodes data: %v", data) - if err != nil { - fmt.Errorf("go-api::instances::numberOfNodes error: %v", err) return -1, err } - if response.StatusCode != 200 { - return -1, fmt.Errorf("go-api::instances::numberOfNodes failed, status: %v, message: %v", response.StatusCode, failed) - } - if data["nodes"] == nil { - log.Printf("[ERROR] go-api::instances::numberOfNodes is nil") - return -1, fmt.Errorf("go-api::instances::numberOfNodes is nil") + switch response.StatusCode { + case 200: + if data["nodes"] == nil { + log.Printf("[ERROR] go-api::instances::numberOfNodes is nil") + return -1, fmt.Errorf("go-api::instances::numberOfNodes is nil") + } + nodes, _ := strconv.Atoi(data["nodes"].(string)) + return nodes, nil + default: + return -1, fmt.Errorf("go-api::instances::numberOfNodes failed, status: %v, message: %v", + response.StatusCode, failed) } - nodes, _ := strconv.Atoi(data["nodes"].(string)) - return nodes, nil } func (api *API) CreateInstance(params map[string]interface{}) (map[string]interface{}, error) { - data := make(map[string]interface{}) - failed := make(map[string]interface{}) + var ( + data map[string]interface{} + failed map[string]interface{} + ) + log.Printf("[DEBUG] go-api::instance::create params: %v", params) response, err := api.sling.New().Post("/api/instances").BodyJSON(params).Receive(&data, &failed) log.Printf("[DEBUG] go-api::instance::waitUntilReady data: %v", data) - if err != nil { return nil, err } - if response.StatusCode != 200 { - return nil, fmt.Errorf("CreateInstance failed, status: %v, message: %s", response.StatusCode, failed) - } - if id, ok := data["id"]; ok { - data["id"] = strconv.FormatFloat(id.(float64), 'f', 0, 64) - log.Printf("[DEBUG] go-api::instance::create id set: %v", data["id"]) - } else { - msg := fmt.Sprintf("go-api::instance::create Invalid instance identifier: %v", data["id"]) - log.Printf("[ERROR] %s", msg) - return nil, errors.New(msg) + switch response.StatusCode { + case 200: + if id, ok := data["id"]; ok { + data["id"] = strconv.FormatFloat(id.(float64), 'f', 0, 64) + log.Printf("[DEBUG] go-api::instance::create id set: %v", data["id"]) + } else { + return nil, fmt.Errorf("go-api::instance::create Invalid instance identifier: %v", data["id"]) + } + return api.waitUntilReady(data["id"].(string)) + default: + return nil, fmt.Errorf("create instance failed, status: %v, message: %s", + response.StatusCode, failed) } - - return api.waitUntilReady(data["id"].(string)) } func (api *API) ReadInstance(instanceID string) (map[string]interface{}, error) { - data := make(map[string]interface{}) - failed := make(map[string]interface{}) + var ( + data map[string]interface{} + failed map[string]interface{} + path = fmt.Sprintf("/api/instances/%s", instanceID) + ) + log.Printf("[DEBUG] go-api::instance::read instance ID: %v", instanceID) - response, err := api.sling.New().Path("/api/instances/").Get(instanceID).Receive(&data, &failed) + response, err := api.sling.New().Path(path).Receive(&data, &failed) log.Printf("[DEBUG] go-api::instance::read data: %v", data) - if err != nil { return nil, err } @@ -172,17 +198,20 @@ func (api *API) ReadInstance(instanceID string) (map[string]interface{}, error) log.Printf("[WARN] go-api::instance::read status: 410, message: The instance has been deleted") return nil, nil default: - return nil, fmt.Errorf("ReadInstance failed, status: %v, message: %s", + return nil, fmt.Errorf("read instance failed, status: %v, message: %s", response.StatusCode, failed) } } +// TODO: Rename to ListInstances func (api *API) ReadInstances() ([]map[string]interface{}, error) { - var data []map[string]interface{} - failed := make(map[string]interface{}) + var ( + data []map[string]interface{} + failed map[string]interface{} + ) + response, err := api.sling.New().Get("/api/instances").Receive(&data, &failed) log.Printf("[DEBUG] go-api::instance::list data: %v", data) - if err != nil { return nil, err } @@ -194,15 +223,18 @@ func (api *API) ReadInstances() ([]map[string]interface{}, error) { log.Printf("[WARN] go-api::instance::list status: 410, message: The instance has been deleted") return nil, nil default: - return nil, fmt.Errorf("ReadInstances failed, status: %v, message: %s", + return nil, fmt.Errorf("list instances failed, status: %v, message: %s", response.StatusCode, failed) } } func (api *API) UpdateInstance(instanceID string, params map[string]interface{}) error { - failed := make(map[string]interface{}) + var ( + failed map[string]interface{} + path = fmt.Sprintf("api/instances/%v", instanceID) + ) + log.Printf("[DEBUG] go-api::instance::update instance ID: %v, params: %v", instanceID, params) - path := fmt.Sprintf("api/instances/%v", instanceID) response, err := api.sling.New().Put(path).BodyJSON(params).Receive(nil, &failed) if err != nil { return err @@ -215,29 +247,32 @@ func (api *API) UpdateInstance(instanceID string, params map[string]interface{}) log.Printf("[WARN] go-api::instance::update status: 410, message: The instance has been deleted") return nil default: - return fmt.Errorf("UpdateInstance failed, status: %v, message: %s", + return fmt.Errorf("update instance failed, status: %v, message: %s", response.StatusCode, failed) } } func (api *API) DeleteInstance(instanceID string, keep_vpc bool) error { - failed := make(map[string]interface{}) + var ( + failed map[string]interface{} + path = fmt.Sprintf("api/instances/%s?keep_vpc=%v", instanceID, keep_vpc) + ) + log.Printf("[DEBUG] go-api::instance::delete instance ID: %v", instanceID) - path := fmt.Sprintf("api/instances/%s?keep_vpc=%v", instanceID, keep_vpc) response, err := api.sling.New().Delete(path).Receive(nil, &failed) - if err != nil { return err } switch response.StatusCode { case 204: + // TODO: Check how this are affected by the new API and will a change to 410 be an issue for older versions? return api.waitUntilDeletion(instanceID) case 410: log.Printf("[WARN] go-api::instance::delete status: 410, message: The instance has been deleted") return nil default: - return fmt.Errorf("DeleteInstance failed, status: %v, message: %s", + return fmt.Errorf("delete instance failed, status: %v, message: %s", response.StatusCode, failed) } } From b367e08dea0c68805860766b6c9fa3fc85984673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Wed, 29 Nov 2023 17:00:31 +0100 Subject: [PATCH 5/6] Remove function no longer in use --- api/instance.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/api/instance.go b/api/instance.go index 816961b..107a277 100644 --- a/api/instance.go +++ b/api/instance.go @@ -122,33 +122,6 @@ func (api *API) waitUntilDeletion(instanceID string) error { } } -func (api *API) numberOfNodes(instanceID string) (int, error) { - var ( - data map[string]interface{} - failed map[string]interface{} - path = fmt.Sprintf("api/instances/%v/nodes", instanceID) - ) - - response, err := api.sling.New().Path(path).Receive(&data, &failed) - log.Printf("[DEBUG] go-api::instances::numberOfNodes data: %v", data) - if err != nil { - return -1, err - } - - switch response.StatusCode { - case 200: - if data["nodes"] == nil { - log.Printf("[ERROR] go-api::instances::numberOfNodes is nil") - return -1, fmt.Errorf("go-api::instances::numberOfNodes is nil") - } - nodes, _ := strconv.Atoi(data["nodes"].(string)) - return nodes, nil - default: - return -1, fmt.Errorf("go-api::instances::numberOfNodes failed, status: %v, message: %v", - response.StatusCode, failed) - } -} - func (api *API) CreateInstance(params map[string]interface{}) (map[string]interface{}, error) { var ( data map[string]interface{} From 36d176b69059ddbbf0635e1c30f0164db9bd42fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Mon, 4 Dec 2023 14:51:25 +0100 Subject: [PATCH 6/6] Prepare to handle both 404/410 --- api/instance.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api/instance.go b/api/instance.go index 107a277..111fe3f 100644 --- a/api/instance.go +++ b/api/instance.go @@ -113,9 +113,11 @@ func (api *API) waitUntilDeletion(instanceID string) error { return err } - // TODO: Check how this works with the new API and will a change to 410 be an issue for - // older versions. - if response.StatusCode == 404 { + switch response.StatusCode { + case 404: + log.Print("[DEBUG] go-api::instance::waitUntilDeletion deleted") + return nil + case 410: log.Print("[DEBUG] go-api::instance::waitUntilDeletion deleted") return nil } @@ -239,7 +241,6 @@ func (api *API) DeleteInstance(instanceID string, keep_vpc bool) error { switch response.StatusCode { case 204: - // TODO: Check how this are affected by the new API and will a change to 410 be an issue for older versions? return api.waitUntilDeletion(instanceID) case 410: log.Printf("[WARN] go-api::instance::delete status: 410, message: The instance has been deleted")