Skip to content

Commit

Permalink
add upgrade_lavinmq resource
Browse files Browse the repository at this point in the history
  • Loading branch information
viktorerlingsson committed Aug 30, 2024
1 parent 535b96e commit 85c6a16
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 0 deletions.
116 changes: 116 additions & 0 deletions api/upgrade_lavinmq.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package api

import (
"fmt"
"log"
"time"
)

// ReadVersions - Read versions LavinMQ can upgrade to
func (api *API) ReadLavinMQVersions(instanceID int) (map[string]any, error) {
var (
data map[string]any
failed map[string]any
path = fmt.Sprintf("api/instances/%d/actions/new-lavinmq-versions", instanceID)
)

log.Printf("[DEBUG] api::upgrade_lavinmq#read_versions path: %s", path)
response, err := api.sling.New().Path(path).Receive(&data, &failed)
if err != nil {
return nil, err
}

switch response.StatusCode {
case 200:
return data, nil
default:
return nil, fmt.Errorf("ReadVersions failed, status: %d, message: %s",
response.StatusCode, failed)
}
}

// UpgradeLavinMQ - Upgrade to latest possible version or a specific available version
func (api *API) UpgradeLavinMQ(instanceID int, new_version string) (string, error) {
log.Printf("[DEBUG] api::upgrade_lavinmq#upgrade_lavinmq instanceID: %d"+
", new_version: %s", instanceID, new_version)

if new_version == "" {
return api.UpgradeToLatestLavinMQVersion(instanceID)
} else {
return api.UpgradeToSpecificLavinMQVersion(instanceID, new_version)
}
}

func (api *API) UpgradeToSpecificLavinMQVersion(instanceID int, version string) (string, error) {
var (
data map[string]any
failed map[string]any
path = fmt.Sprintf("api/instances/%d/actions/upgrade-lavinmq", instanceID)
params = make(map[string]any)
)

params["version"] = version
log.Printf("[DEBUG] api::upgrade_lavinmq#upgrade_to_specific_version path: %s, params: %v",
path, params)
response, err := api.sling.New().Post(path).BodyJSON(params).Receive(&data, &failed)
if err != nil {
return "", err
}

switch response.StatusCode {
case 200:
return api.waitUntilLavinMQUpgraded(instanceID)
default:
return "", fmt.Errorf("upgrade LavinMQ failed, status: %d, message: %s",
response.StatusCode, failed)
}
}

func (api *API) UpgradeToLatestLavinMQVersion(instanceID int) (string, error) {
var (
data map[string]any
failed map[string]any
path = fmt.Sprintf("api/instances/%d/actions/upgrade-lavinmq", instanceID)
)

log.Printf("[DEBUG] api::upgrade_lavinmq#upgrade_to_latest_version path: %s", path)
response, err := api.sling.New().Post(path).Receive(&data, &failed)
if err != nil {
return "", err
}

switch response.StatusCode {
case 200:
return "Already at highest possible version", nil
case 202:
return api.waitUntilLavinMQUpgraded(instanceID)
default:
return "", fmt.Errorf("upgrade LavinMQ failed, status: %d, message: %s",
response.StatusCode, failed)
}
}

func (api *API) waitUntilLavinMQUpgraded(instanceID int) (string, error) {
var (
data []map[string]any
failed map[string]any
path = fmt.Sprintf("api/instances/%d/nodes", instanceID)
)

for {
_, err := api.sling.New().Path(path).Receive(&data, &failed)
if err != nil {
return "", err
}

log.Printf("[DEBUG] api::upgrade_lavinmq#waitUntilUpgraded data: %v", data)
ready := true
for _, node := range data {
ready = ready && node["configured"].(bool)
}
if ready {
return "", nil
}
time.Sleep(10 * time.Second)
}
}
1 change: 1 addition & 0 deletions cloudamqp/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func Provider(v string, client *http.Client) *schema.Provider {
"cloudamqp_rabbitmq_configuration": resourceRabbitMqConfiguration(),
"cloudamqp_security_firewall": resourceSecurityFirewall(),
"cloudamqp_upgrade_rabbitmq": resourceUpgradeRabbitMQ(),
"cloudamqp_upgrade_lavinmq": resourceUpgradeLavinMQ(),
"cloudamqp_vpc_connect": resourceVpcConnect(),
"cloudamqp_vpc_gcp_peering": resourceVpcGcpPeering(),
"cloudamqp_vpc_peering": resourceVpcPeering(),
Expand Down
65 changes: 65 additions & 0 deletions cloudamqp/resource_cloudamqp_upgrade_lavinmq.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package cloudamqp

import (
"log"
"strconv"

"github.com/cloudamqp/terraform-provider-cloudamqp/api"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceUpgradeLavinMQ() *schema.Resource {
return &schema.Resource{
Create: resourceUpgradeLavinMQInvoke,
Read: resourceUpgradeLavinMQRead,
Update: resourceUpgradeLavinMQUpdate,
Delete: resourceUpgradeLavinMQRemove,
Schema: map[string]*schema.Schema{
"instance_id": {
Type: schema.TypeInt,
Required: true,
Description: "The CloudAMQP instance identifier",
},
"new_version": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
Description: "The new version to upgrade to",
},
},
}
}

func resourceUpgradeLavinMQInvoke(d *schema.ResourceData, meta interface{}) error {
var (
api = meta.(*api.API)
instanceID = d.Get("instance_id").(int)
new_version = d.Get("new_version").(string)
)

log.Printf("[DEBUG] - Upgrading LavinMQ instance %d to version %s", instanceID, new_version)
response, err := api.UpgradeLavinMQ(instanceID, new_version)
if err != nil {
return err
}

d.SetId(strconv.Itoa(instanceID))

if len(response) > 0 {
log.Printf("[INFO] - " + response)
}

return nil
}

func resourceUpgradeLavinMQRead(d *schema.ResourceData, meta interface{}) error {
return nil
}

func resourceUpgradeLavinMQUpdate(d *schema.ResourceData, meta interface{}) error {
return nil
}

func resourceUpgradeLavinMQRemove(d *schema.ResourceData, meta interface{}) error {
return nil
}
92 changes: 92 additions & 0 deletions docs/resources/upgrade_lavinmq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
layout: "cloudamqp"
page_title: "CloudAMQP: cloudamqp_upgrade_lavinmq"
description: |-
Invoke upgrade to latest possible upgradable versions for LavinMQ.
---

# cloudamqp_upgrade_lavinmq

This resource allows you to upgrade LavinMQ version.

There is two different ways to trigger the version upgrade

> - Specify LavinMQ version to upgrade to
> - Upgrade to latest LavinMQ version
See, below example usage for the difference.

Only available for dedicated subscription plans running ***LavinMQ***.

## Example Usage

<details>
<summary>
<b>
<i>Specify version upgrade, from v1.31.0</i>
</b>
</summary>

Specify the version to upgrade to. List available upgradable versions, use [CloudAMQP API](https://docs.cloudamqp.com/cloudamqp_api.html#get-available-versions).
After the upgrade finished, there can still be newer versions available.

```hcl
resource "cloudamqp_instance" "instance" {
name = "lavinmq-version-upgrade-test"
plan = "lynx-1"
region = "amazon-web-services::us-west-1"
}
resource "cloudamqp_upgrade_lavinmq" "upgrade" {
instance_id = cloudamqp_instance.instance.id
new_version = "1.3.1"
}
```

</details>

<details>
<summary>
<b>
<i>Upgrade to latest possible version, from v1.31.0</i>
</b>
</summary>

This will upgrade LavinMQ to the latest possible version detected by the data source `cloudamqp_upgradable_versions`.

```hcl
resource "cloudamqp_instance" "instance" {
name = "lavinmq-version-upgrade-test"
plan = "lynx-1"
region = "amazon-web-services::us-west-1"
}
data "cloudamqp_upgradable_versions" "upgradable_versions" {
instance_id = cloudamqp_instance.instance.id
}
resource "cloudamqp_upgrade_lavinmq" "upgrade" {
instance_id = cloudamqp_instance.instance.id
current_version = cloudamqp_instance.instance.rmq_version
new_version = data.cloudamqp_upgradable_versions.upgradable_versions.new_lavinmq_version
}
```

</details>


## Argument Reference

The following arguments are supported:

* `instance_id` - (Required) The CloudAMQP instance identifier
* `new_version` - (Optional/ForceNew) The new version to upgrade to

## Import

Not possible to import this resource.

## Important Upgrade Information

> - All single node upgrades will require some downtime since LavinMQ needs a restart.
> - Auto delete queues (queues that are marked AD) will be deleted during the update.

0 comments on commit 85c6a16

Please sign in to comment.