From 659d7bf02f05877774fec6675f686dd760e15965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Eckerstr=C3=B6m?= Date: Thu, 13 Nov 2025 17:11:53 +0100 Subject: [PATCH] Copy settings --- README.md | 32 ++++++++++++++++++++++++ client/instances.go | 56 +++++++++++++++++++++++++++--------------- cmd/instance_create.go | 34 +++++++++++++++++++------ 3 files changed, 94 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 543ab55..b220d44 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 @@ -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 diff --git a/client/instances.go b/client/instances.go index 21308c9..3b6c7bf 100644 --- a/client/instances.go +++ b/client/instances.go @@ -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 { @@ -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 } diff --git a/cmd/instance_create.go b/cmd/instance_create.go index 036d0a3..9a24ede 100644 --- a/cmd/instance_create.go +++ b/cmd/instance_create.go @@ -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{ @@ -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() @@ -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) @@ -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")