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

Topic permissions support #49

Merged
merged 6 commits into from
Jan 27, 2020
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
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ module github.com/terraform-providers/terraform-provider-rabbitmq

require (
github.com/hashicorp/terraform-plugin-sdk v1.0.0
github.com/michaelklishin/rabbit-hole v1.5.0
github.com/streadway/amqp v0.0.0-20190214183023-884228600bc9 // indirect
github.com/michaelklishin/rabbit-hole v0.0.0-20191008194146-93d9988f0cd5
)

go 1.13
189 changes: 189 additions & 0 deletions go.sum

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions rabbitmq/import_topic_permissions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package rabbitmq

import (
"os"
"regexp"
"testing"

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

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

func TestAccTopicPermissions_importBasic(t *testing.T) {
resourceName := "rabbitmq_topic_permissions.test"
var topicPermissionInfo rabbithole.TopicPermissionInfo
var expectErr0 *regexp.Regexp
var expectErr1 *regexp.Regexp
checkDestroy := testAccTopicPermissionsCheckDestroy(&topicPermissionInfo)
if os.Getenv("RABBITMQ_VERSION") == "3.6" {
expectErr0, _ = regexp.Compile("^errors during apply: Topic permissions were adding in RabbitMQ 3.7, connected to 3.6.*$")
expectErr1, _ = regexp.Compile("^Resource specified by ResourceName couldn't be found: rabbitmq_topic_permissions.test$")
checkDestroy = nil
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: checkDestroy,
Steps: []resource.TestStep{
{
Config: testAccTopicPermissionsConfigBasic,
Check: testAccTopicPermissionsCheck(
resourceName, &topicPermissionInfo,
),
ExpectError: expectErr0,
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ExpectError: expectErr1,
},
},
})
}
17 changes: 9 additions & 8 deletions rabbitmq/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"io/ioutil"
"net/http"

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

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
Expand Down Expand Up @@ -72,13 +72,14 @@ func Provider() terraform.ResourceProvider {
},

ResourcesMap: map[string]*schema.Resource{
"rabbitmq_binding": resourceBinding(),
"rabbitmq_exchange": resourceExchange(),
"rabbitmq_permissions": resourcePermissions(),
"rabbitmq_policy": resourcePolicy(),
"rabbitmq_queue": resourceQueue(),
"rabbitmq_user": resourceUser(),
"rabbitmq_vhost": resourceVhost(),
"rabbitmq_binding": resourceBinding(),
"rabbitmq_exchange": resourceExchange(),
"rabbitmq_permissions": resourcePermissions(),
"rabbitmq_topic_permissions": resourceTopicPermissions(),
"rabbitmq_policy": resourcePolicy(),
"rabbitmq_queue": resourceQueue(),
"rabbitmq_user": resourceUser(),
"rabbitmq_vhost": resourceVhost(),
},

ConfigureFunc: providerConfigure,
Expand Down
28 changes: 15 additions & 13 deletions rabbitmq/resource_permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"log"
"strings"

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

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
Expand Down Expand Up @@ -118,14 +118,11 @@ func ReadPermissions(d *schema.ResourceData, meta interface{}) error {
func UpdatePermissions(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

permissionId := strings.Split(d.Id(), "@")
if len(permissionId) < 2 {
return fmt.Errorf("Unable to determine Permission ID")
user, vhost, err := parseID(d)
if err != nil {
return err
}

user := permissionId[0]
vhost := permissionId[1]

if d.HasChange("permissions") {
_, newPerms := d.GetChange("permissions")

Expand All @@ -146,14 +143,11 @@ func UpdatePermissions(d *schema.ResourceData, meta interface{}) error {
func DeletePermissions(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

permissionId := strings.Split(d.Id(), "@")
if len(permissionId) < 2 {
return fmt.Errorf("Unable to determine Permission ID")
user, vhost, err := parseID(d)
if err != nil {
return err
}

user := permissionId[0]
vhost := permissionId[1]

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

resp, err := rmqc.ClearPermissionsIn(vhost, user)
Expand Down Expand Up @@ -203,3 +197,11 @@ func setPermissionsIn(rmqc *rabbithole.Client, vhost string, user string, permsM

return nil
}

func parseID(d *schema.ResourceData) (string, string, error) {
ID := strings.Split(d.Id(), "@")
if len(ID) < 2 {
return "", "", fmt.Errorf("Unable to determine Permission ID")
}
return ID[0], ID[1], nil
}
226 changes: 226 additions & 0 deletions rabbitmq/resource_topic_permissions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package rabbitmq

import (
"fmt"
"log"
"strconv"

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

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

func resourceTopicPermissions() *schema.Resource {
return &schema.Resource{
Create: CreateTopicPermissions,
Update: UpdateTopicPermissions,
Read: ReadTopicPermissions,
Delete: DeleteTopicPermissions,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"user": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"vhost": {
Type: schema.TypeString,
Optional: true,
Default: "/",
ForceNew: true,
},

"permissions": {
Type: schema.TypeSet,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"exchange": {
Type: schema.TypeString,
Required: true,
},

"write": {
Type: schema.TypeString,
Required: true,
},

"read": {
Type: schema.TypeString,
Required: true,
},
},
},
},
},
}
}

// CreateTopicPermissions for given exchanges
func CreateTopicPermissions(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

user := d.Get("user").(string)
vhost := d.Get("vhost").(string)
permsSet := d.Get("permissions").(*schema.Set)

for _, exchange := range permsSet.List() {

permsMap, ok := exchange.(map[string]interface{})
if !ok {
return fmt.Errorf("Unable to parse permissions")
}

if err := setTopicPermissionsIn(rmqc, vhost, user, permsMap); err != nil {
return err
}
}

id := fmt.Sprintf("%s@%s", user, vhost)
d.SetId(id)

return ReadTopicPermissions(d, meta)
}

// ReadTopicPermissions for the given ID
func ReadTopicPermissions(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

user, vhost, err := parseID(d)
if err != nil {
return err
}

userPerms, err := rmqc.GetTopicPermissionsIn(vhost, user)
if err != nil {
return checkDeleted(d, err)
}

log.Printf("[DEBUG] RabbitMQ: Topic permission retrieved for %s: %#v", d.Id(), userPerms)

d.Set("user", userPerms[0].User)
d.Set("vhost", userPerms[0].Vhost)

perms := make([]map[string]interface{}, len(userPerms))
for i, perm := range userPerms {
p := make(map[string]interface{})
p["exchange"] = perm.Exchange
p["write"] = perm.Write
p["read"] = perm.Read
perms[i] = p
}
d.Set("permissions", perms)

return nil
}

// UpdateTopicPermissions for given ID
func UpdateTopicPermissions(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

user, vhost, err := parseID(d)
if err != nil {
return err
}

if d.HasChange("permissions") {
err = DeleteTopicPermissions(d, meta)
if err != nil {
return err
}
_, newPerms := d.GetChange("permissions")
newPermsSet := newPerms.(*schema.Set)
for _, exchange := range newPermsSet.List() {
permsMap, ok := exchange.(map[string]interface{})
if !ok {
return fmt.Errorf("Unable to parse permissions")
}

if err := setTopicPermissionsIn(rmqc, vhost, user, permsMap); err != nil {
return err
}
}
}

return ReadTopicPermissions(d, meta)
}

// DeleteTopicPermissions for given ID
func DeleteTopicPermissions(d *schema.ResourceData, meta interface{}) error {
rmqc := meta.(*rabbithole.Client)

user, vhost, err := parseID(d)
if err != nil {
return err
}

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

resp, err := rmqc.ClearTopicPermissionsIn(vhost, user)
log.Printf("[DEBUG] RabbitMQ: Topic permission delete response: %#v", resp)
if err != nil {
return err
}

if resp.StatusCode == 404 {
// The permissions were already deleted
return nil
}

if resp.StatusCode >= 400 {
verErr := checkVersion(rmqc)
if verErr != nil {
return verErr
}
return fmt.Errorf("Error deleting RabbitMQ topic permission: %s", resp.Status)
}

return nil
}

func setTopicPermissionsIn(rmqc *rabbithole.Client, vhost string, user string, permsMap map[string]interface{}) error {
perms := rabbithole.TopicPermissions{}

if v, ok := permsMap["exchange"].(string); ok {
perms.Exchange = v
}

if v, ok := permsMap["write"].(string); ok {
perms.Write = v
}

if v, ok := permsMap["read"].(string); ok {
perms.Read = v
}

log.Printf("[DEBUG] RabbitMQ: Attempting to set topic permissions for %s@%s: %#v", user, vhost, perms)

resp, err := rmqc.UpdateTopicPermissionsIn(vhost, user, perms)
log.Printf("[DEBUG] RabbitMQ: Permission response: %#v", resp)
if err != nil {
return err
}

if resp.StatusCode >= 400 {
verErr := checkVersion(rmqc)
if verErr != nil {
return verErr
}
return fmt.Errorf("Error setting topic permissions: %s", resp.Status)
}

return nil
}

func checkVersion(rmqc *rabbithole.Client) error {
overview, _ := rmqc.Overview()
ver, _ := strconv.ParseFloat(overview.RabbitMQVersion, 32)
if ver < 3.7 {
return fmt.Errorf("Topic permissions were adding in RabbitMQ 3.7, connected to %s", overview.RabbitMQVersion)
}
return nil
}
Loading