Skip to content
This repository has been archived by the owner on Nov 14, 2020. It is now read-only.

Commit

Permalink
Merge pull request #48 from justinbaur/feature/add-shovel-resource
Browse files Browse the repository at this point in the history
Feature/add shovel resource
  • Loading branch information
cyrilgdn authored Jul 17, 2020
2 parents a87cddc + b012021 commit fdcca45
Show file tree
Hide file tree
Showing 6 changed files with 481 additions and 2 deletions.
1 change: 1 addition & 0 deletions rabbitmq/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func Provider() terraform.ResourceProvider {
"rabbitmq_queue": resourceQueue(),
"rabbitmq_user": resourceUser(),
"rabbitmq_vhost": resourceVhost(),
"rabbitmq_shovel": resourceShovel(),
},

ConfigureFunc: providerConfigure,
Expand Down
240 changes: 240 additions & 0 deletions rabbitmq/resource_shovel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package rabbitmq

import (
"fmt"
"log"
"strings"

rabbithole "github.com/michaelklishin/rabbit-hole/v2"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func resourceShovel() *schema.Resource {
return &schema.Resource{
Create: CreateShovel,
Read: ReadShovel,
Delete: DeleteShovel,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vhost": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"info": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"source_uri": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
},
"source_exchange": {
Type: schema.TypeString,
Optional: true,
Default: nil,
},
"source_exchange_key": {
Type: schema.TypeString,
Optional: true,
Default: nil,
},
"source_queue": {
Type: schema.TypeString,
Optional: true,
Default: nil,
},
"destination_uri": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
},
"destination_exchange": {
Type: schema.TypeString,
Optional: true,
Default: nil,
},
"destination_exchange_key": {
Type: schema.TypeString,
Optional: true,
Default: nil,
},
"destination_queue": {
Type: schema.TypeString,
Optional: true,
Default: nil,
},
"prefetch_count": {
Type: schema.TypeInt,
Optional: true,
Default: 1000,
},
"reconnect_delay": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
},
"add_forward_headers": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"ack_mode": {
Type: schema.TypeString,
Optional: true,
Default: "on-confirm",
},
"delete_after": {
Type: schema.TypeString,
Optional: true,
Default: "never",
},
},
},
},
},
}
}

func CreateShovel(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

vhost := d.Get("vhost").(string)
shovelName := d.Get("name").(string)
shovelInfo := d.Get("info").([]interface{})

shovelMap, ok := shovelInfo[0].(map[string]interface{})
if !ok {
return fmt.Errorf("Unable to parse shovel info")
}

shovelDefinition := setShovelDefinition(shovelMap).(rabbithole.ShovelDefinition)

log.Printf("[DEBUG] RabbitMQ: Attempting to declare shovel %s in vhost %s", shovelName, vhost)
resp, err := rmqc.DeclareShovel(vhost, shovelName, shovelDefinition)
log.Printf("[DEBUG] RabbitMQ: shovel declartion response: %#v", resp)
if err != nil {
return err
}

shovelId := fmt.Sprintf("%s@%s", shovelName, vhost)

d.SetId(shovelId)

return ReadShovel(d, meta)
}

func ReadShovel(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

shovelId := strings.Split(d.Id(), "@")

name := shovelId[0]
vhost := shovelId[1]

shovelInfo, err := rmqc.GetShovel(vhost, name)
if err != nil {
return checkDeleted(d, err)
}

log.Printf("[DEBUG] RabbitMQ: Shovel retrieved: Vhost: %#v, Name: %#v", vhost, name)

d.Set("name", shovelInfo.Name)
d.Set("vhost", shovelInfo.Vhost)

return nil
}

func DeleteShovel(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

shovelId := strings.Split(d.Id(), "@")

name := shovelId[0]
vhost := shovelId[1]

log.Printf("[DEBUG] RabbitMQ: Attempting to delete shovel %s", d.Id())

resp, err := rmqc.DeleteShovel(vhost, name)
log.Printf("[DEBUG] RabbitMQ: shovel deletion response: %#v", resp)
if err != nil {
return err
}

if resp.StatusCode >= 400 {
return fmt.Errorf("Error deleting RabbitMQ shovel: %s", resp.Status)
}

return nil
}

func setShovelDefinition(shovelMap map[string]interface{}) interface{} {
shovelDefinition := &rabbithole.ShovelDefinition{}

if v, ok := shovelMap["source_uri"].(string); ok {
shovelDefinition.SourceURI = v
}

if v, ok := shovelMap["source_exchange"].(string); ok {
shovelDefinition.SourceExchange = v
}

if v, ok := shovelMap["source_exchange_key"].(string); ok {
shovelDefinition.SourceExchangeKey = v
}

if v, ok := shovelMap["source_queue"].(string); ok {
shovelDefinition.SourceQueue = v
}

if v, ok := shovelMap["destination_uri"].(string); ok {
shovelDefinition.DestinationURI = v
}

if v, ok := shovelMap["destination_exchange"].(string); ok {
shovelDefinition.DestinationExchange = v
}

if v, ok := shovelMap["destination_exchange_key"].(string); ok {
shovelDefinition.DestinationExchangeKey = v
}

if v, ok := shovelMap["destination_queue"].(string); ok {
shovelDefinition.DestinationQueue = v
}

if v, ok := shovelMap["prefetch_count"].(int); ok {
shovelDefinition.PrefetchCount = v
}

if v, ok := shovelMap["reconnect_delay"].(int); ok {
shovelDefinition.ReconnectDelay = v
}

if v, ok := shovelMap["add_forward_headers"].(bool); ok {
shovelDefinition.AddForwardHeaders = v
}

if v, ok := shovelMap["ack_mode"].(string); ok {
shovelDefinition.AckMode = v
}

if v, ok := shovelMap["delete_after"].(string); ok {
shovelDefinition.DeleteAfter = v
}

return *shovelDefinition
}
124 changes: 124 additions & 0 deletions rabbitmq/resource_shovel_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package rabbitmq

import (
"fmt"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
rabbithole "github.com/michaelklishin/rabbit-hole/v2"
)

func TestAccShovel(t *testing.T) {
var shovelInfo rabbithole.ShovelInfo

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccShovelCheckDestroy(&shovelInfo),
Steps: []resource.TestStep{
{
Config: testAccShovelConfig_basic,
Check: testAccShovelCheck(
"rabbitmq_shovel.shovelTest", &shovelInfo,
),
},
},
})
}

func testAccShovelCheck(rn string, shovelInfo *rabbithole.ShovelInfo) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[rn]
if !ok {
return fmt.Errorf("resource not found: %s", rn)
}

if rs.Primary.ID == "" {
return fmt.Errorf("shovel id not set")
}

rmqc := testAccProvider.Meta().(*rabbithole.Client)
shovelParts := strings.Split(rs.Primary.ID, "@")

shovelInfos, err := rmqc.ListShovels()
if err != nil {
return fmt.Errorf("Error retrieving shovels: %s", err)
}

for _, info := range shovelInfos {
if info.Name == shovelParts[0] && info.Vhost == shovelParts[1] {
shovelInfo = &info
return nil
}
}

return fmt.Errorf("Unable to find shovel %s", rn)
}
}

func testAccShovelCheckDestroy(shovelInfo *rabbithole.ShovelInfo) resource.TestCheckFunc {
return func(s *terraform.State) error {
rmqc := testAccProvider.Meta().(*rabbithole.Client)

shovelInfos, err := rmqc.ListShovels()
if err != nil {
return fmt.Errorf("Error retrieving shovels: %s", err)
}

for _, info := range shovelInfos {
if info.Name == shovelInfo.Name && info.Vhost == shovelInfo.Vhost {
return fmt.Errorf("shovel still exists: %v", info)
}
}

return nil
}
}

const testAccShovelConfig_basic = `
resource "rabbitmq_vhost" "test" {
name = "test"
}
resource "rabbitmq_permissions" "guest" {
user = "guest"
vhost = "${rabbitmq_vhost.test.name}"
permissions {
configure = ".*"
write = ".*"
read = ".*"
}
}
resource "rabbitmq_exchange" "test" {
name = "test_exchange"
vhost = "${rabbitmq_permissions.guest.vhost}"
settings {
type = "fanout"
durable = false
auto_delete = true
}
}
resource "rabbitmq_queue" "test" {
name = "test_queue"
vhost = "${rabbitmq_exchange.test.vhost}"
settings {
durable = false
auto_delete = true
}
}
resource "rabbitmq_shovel" "shovelTest" {
name = "shovelTest"
vhost = "${rabbitmq_queue.test.vhost}"
info {
source_uri = "amqp:///test"
source_exchange = "${rabbitmq_exchange.test.name}"
source_exchange_key = "test"
destination_uri = "amqp:///test"
destination_queue = "${rabbitmq_queue.test.name}"
}
}`
2 changes: 1 addition & 1 deletion scripts/enabled_plugins
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[rabbitmq_management,rabbitmq_federation,rabbitmq_federation_management].
[rabbitmq_management,rabbitmq_federation,rabbitmq_federation_management,rabbitmq_shovel,rabbitmq_shovel_management].
Loading

0 comments on commit fdcca45

Please sign in to comment.