Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ A command line interface for the CloudAMQP API that provides complete management
- **Unified API**: Single API key manages all operations through the customer API
- **Simple Configuration**: Plain text API key storage in `~/.cloudamqprc`
- **Flag-Based Commands**: Clean command structure with `--id` flags for instance operations
- **Copy Settings**: Clone configuration from existing instances (metrics, firewall, alarms, etc.)
- **User-Friendly**: Clear help messages, examples, and safety confirmations
- **Error Handling**: Proper API error extraction and display

Expand Down Expand Up @@ -57,6 +58,10 @@ Manage CloudAMQP instances using your main API key.
# Create a new instance
cloudamqp instance create --name=my-instance --plan=bunny-1 --region=amazon-web-services::us-east-1

# Create instance with copy_settings (dedicated instances only)
cloudamqp instance create --name=my-copy --plan=bunny-1 --region=amazon-web-services::us-east-1 \
--copy-from-id=1234 --copy-settings=metrics,firewall,config

# List all instances
cloudamqp instance list

Expand Down Expand Up @@ -221,6 +226,33 @@ cloudamqp instance restart-rabbitmq --id 1234
cloudamqp instance upgrade-all --id 1234
```

### Copy Settings Between Instances

Copy configuration from an existing dedicated instance to a new one:

```bash
# 1. Create original instance
cloudamqp instance create --name=production --plan=bunny-1 --region=amazon-web-services::us-east-1

# 2. Configure the original instance (alarms, metrics, firewall, etc.)
# ... perform your configuration ...

# 3. Create a new instance copying specific settings
cloudamqp instance create --name=staging --plan=bunny-1 --region=amazon-web-services::us-east-1 \
--copy-from-id=1234 --copy-settings=metrics,firewall,config

# Available settings to copy:
# - alarms: Copy alarm configurations and recipients
# - metrics: Copy metrics configuration
# - logs: Copy log settings
# - firewall: Copy firewall rules
# - config: Copy RabbitMQ configuration
# - definitions: Copy RabbitMQ definitions (queues, exchanges, etc.)
# - plugins: Copy plugin configurations

# Note: Only works between dedicated instances (not shared plans)
```

### Team Setup

```bash
Expand Down
56 changes: 36 additions & 20 deletions client/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ type Instance struct {
HostnameInternal string `json:"hostname_internal"`
}

type CopySettings struct {
SubscriptionID int `json:"subscription_id"`
Settings []string `json:"settings"`
}

type InstanceCreateRequest struct {
Name string `json:"name"`
Plan string `json:"plan"`
Region string `json:"region"`
Tags []string `json:"tags,omitempty"`
VPCSubnet string `json:"vpc_subnet,omitempty"`
VPCID *int `json:"vpc_id,omitempty"`
Name string `json:"name"`
Plan string `json:"plan"`
Region string `json:"region"`
Tags []string `json:"tags,omitempty"`
VPCSubnet string `json:"vpc_subnet,omitempty"`
VPCID *int `json:"vpc_id,omitempty"`
CopySettings *CopySettings `json:"copy_settings,omitempty"`
}

type InstanceCreateResponse struct {
Expand Down Expand Up @@ -73,26 +79,36 @@ func (c *Client) GetInstance(id int) (*Instance, error) {
}

func (c *Client) CreateInstance(req *InstanceCreateRequest) (*InstanceCreateResponse, error) {
formData := url.Values{}
formData.Set("name", req.Name)
formData.Set("plan", req.Plan)
formData.Set("region", req.Region)
var body any

// Use JSON format when copy_settings is present (required by API)
if req.CopySettings != nil {
body = req
} else {
// Use form encoding for backward compatibility
formData := url.Values{}
formData.Set("name", req.Name)
formData.Set("plan", req.Plan)
formData.Set("region", req.Region)

if len(req.Tags) > 0 {
for _, tag := range req.Tags {
formData.Add("tags[]", tag)
if len(req.Tags) > 0 {
for _, tag := range req.Tags {
formData.Add("tags[]", tag)
}
}
}

if req.VPCSubnet != "" {
formData.Set("vpc_subnet", req.VPCSubnet)
}
if req.VPCSubnet != "" {
formData.Set("vpc_subnet", req.VPCSubnet)
}

if req.VPCID != nil {
formData.Set("vpc_id", strconv.Itoa(*req.VPCID))
}

if req.VPCID != nil {
formData.Set("vpc_id", strconv.Itoa(*req.VPCID))
body = formData
}

respBody, err := c.makeRequest("POST", "/instances", formData)
respBody, err := c.makeRequest("POST", "/instances", body)
if err != nil {
return nil, err
}
Expand Down
34 changes: 26 additions & 8 deletions cmd/instance_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import (
)

var (
instanceName string
instancePlan string
instanceRegion string
instanceTags []string
instanceVPCSubnet string
instanceVPCID string
instanceName string
instancePlan string
instanceRegion string
instanceTags []string
instanceVPCSubnet string
instanceVPCID string
instanceCopyFromID string
instanceCopySettings []string
)

var instanceCreateCmd = &cobra.Command{
Expand All @@ -31,9 +33,12 @@ Required flags:
Optional flags:
--tags: Instance tags (can be specified multiple times)
--vpc-subnet: VPC subnet for dedicated VPC
--vpc-id: ID of existing VPC to add instance to`,
--vpc-id: ID of existing VPC to add instance to
--copy-from-id: Instance ID to copy settings from (dedicated instances only)
--copy-settings: Settings to copy (alarms, metrics, logs, firewall, config)`,
Example: ` cloudamqp instance create --name=my-instance --plan=bunny-1 --region=amazon-web-services::us-east-1
cloudamqp instance create --name=my-instance --plan=bunny-1 --region=amazon-web-services::us-east-1 --tags=production --tags=web-app`,
cloudamqp instance create --name=my-instance --plan=bunny-1 --region=amazon-web-services::us-east-1 --tags=production --tags=web-app
cloudamqp instance create --name=my-copy --plan=bunny-1 --region=amazon-web-services::us-east-1 --copy-from-id=12345 --copy-settings=metrics,firewall`,
RunE: func(cmd *cobra.Command, args []string) error {
var err error
apiKey, err = getAPIKey()
Expand Down Expand Up @@ -62,6 +67,17 @@ Optional flags:
req.VPCID = &vpcID
}

if instanceCopyFromID != "" {
copyFromID, err := strconv.Atoi(instanceCopyFromID)
if err != nil {
return fmt.Errorf("invalid copy-from-id: %v", err)
}
req.CopySettings = &client.CopySettings{
SubscriptionID: copyFromID,
Settings: instanceCopySettings,
}
}

resp, err := c.CreateInstance(req)
if err != nil {
fmt.Printf("Error creating instance: %v\n", err)
Expand All @@ -85,6 +101,8 @@ func init() {
instanceCreateCmd.Flags().StringSliceVar(&instanceTags, "tags", []string{}, "Instance tags")
instanceCreateCmd.Flags().StringVar(&instanceVPCSubnet, "vpc-subnet", "", "VPC subnet")
instanceCreateCmd.Flags().StringVar(&instanceVPCID, "vpc-id", "", "VPC ID")
instanceCreateCmd.Flags().StringVar(&instanceCopyFromID, "copy-from-id", "", "Instance ID to copy settings from")
instanceCreateCmd.Flags().StringSliceVar(&instanceCopySettings, "copy-settings", []string{}, "Settings to copy (alarms, metrics, logs, firewall, config)")

instanceCreateCmd.MarkFlagRequired("name")
instanceCreateCmd.MarkFlagRequired("plan")
Expand Down