From 9fea702e998e763c65e3aa28415f97bf803b76c9 Mon Sep 17 00:00:00 2001 From: Joe Topjian Date: Tue, 19 Jul 2016 05:34:48 +0000 Subject: [PATCH] provider/rabbitmq: rabbitmq_user resource --- .../providers/rabbitmq/import_user_test.go | 33 ++++ builtin/providers/rabbitmq/provider.go | 1 + builtin/providers/rabbitmq/resource_user.go | 174 ++++++++++++++++++ .../providers/rabbitmq/resource_user_test.go | 94 ++++++++++ 4 files changed, 302 insertions(+) create mode 100644 builtin/providers/rabbitmq/import_user_test.go create mode 100644 builtin/providers/rabbitmq/resource_user.go create mode 100644 builtin/providers/rabbitmq/resource_user_test.go diff --git a/builtin/providers/rabbitmq/import_user_test.go b/builtin/providers/rabbitmq/import_user_test.go new file mode 100644 index 0000000000..f33eb7e8e2 --- /dev/null +++ b/builtin/providers/rabbitmq/import_user_test.go @@ -0,0 +1,33 @@ +package rabbitmq + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccUser_importBasic(t *testing.T) { + resourceName := "rabbitmq_user.test" + var user string + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccUserCheckDestroy(user), + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccUserConfig_basic, + Check: testAccUserCheck( + resourceName, &user, + ), + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"password"}, + }, + }, + }) +} diff --git a/builtin/providers/rabbitmq/provider.go b/builtin/providers/rabbitmq/provider.go index 4f270bdce5..7838a5f801 100644 --- a/builtin/providers/rabbitmq/provider.go +++ b/builtin/providers/rabbitmq/provider.go @@ -72,6 +72,7 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ + "rabbitmq_user": resourceUser(), "rabbitmq_vhost": resourceVhost(), }, diff --git a/builtin/providers/rabbitmq/resource_user.go b/builtin/providers/rabbitmq/resource_user.go new file mode 100644 index 0000000000..2177182efe --- /dev/null +++ b/builtin/providers/rabbitmq/resource_user.go @@ -0,0 +1,174 @@ +package rabbitmq + +import ( + "fmt" + "log" + "strings" + + "github.com/michaelklishin/rabbit-hole" + + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceUser() *schema.Resource { + return &schema.Resource{ + Create: CreateUser, + Update: UpdateUser, + Read: ReadUser, + Delete: DeleteUser, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "password": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + + "tags": &schema.Schema{ + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func CreateUser(d *schema.ResourceData, meta interface{}) error { + rmqc := meta.(*rabbithole.Client) + + name := d.Get("name").(string) + + var tagList []string + for _, v := range d.Get("tags").([]interface{}) { + tagList = append(tagList, v.(string)) + } + tags := strings.Join(tagList, ",") + + userSettings := rabbithole.UserSettings{ + Password: d.Get("password").(string), + Tags: tags, + } + + log.Printf("[DEBUG] RabbitMQ: Attempting to create user %s", name) + + resp, err := rmqc.PutUser(name, userSettings) + log.Printf("[DEBUG] RabbitMQ: user creation response: %#v", resp) + if err != nil { + return err + } + + if resp.StatusCode >= 400 { + return fmt.Errorf("Error creating RabbitMQ user: %s", resp.Status) + } + + d.SetId(name) + + return ReadUser(d, meta) +} + +func ReadUser(d *schema.ResourceData, meta interface{}) error { + rmqc := meta.(*rabbithole.Client) + + user, err := rmqc.GetUser(d.Id()) + if err != nil { + return checkDeleted(d, err) + } + + log.Printf("[DEBUG] RabbitMQ: User retrieved: %#v", user) + + d.Set("name", user.Name) + + tags := strings.Split(user.Tags, ",") + d.Set("tags", tags) + + return nil +} + +func UpdateUser(d *schema.ResourceData, meta interface{}) error { + rmqc := meta.(*rabbithole.Client) + + name := d.Id() + + if d.HasChange("password") { + _, newPassword := d.GetChange("password") + + userSettings := rabbithole.UserSettings{ + Password: newPassword.(string), + } + + log.Printf("[DEBUG] RabbitMQ: Attempting to update password for %s", name) + + resp, err := rmqc.PutUser(name, userSettings) + log.Printf("[DEBUG] RabbitMQ: Password update response: %#v", resp) + if err != nil { + return err + } + + if resp.StatusCode >= 400 { + return fmt.Errorf("Error updating RabbitMQ user: %s", resp.Status) + } + + } + + if d.HasChange("tags") { + _, newTags := d.GetChange("tags") + + var tagList []string + for _, v := range newTags.([]interface{}) { + tagList = append(tagList, v.(string)) + } + tags := strings.Join(tagList, ",") + + userSettings := rabbithole.UserSettings{ + Tags: tags, + } + + log.Printf("[DEBUG] RabbitMQ: Attempting to update tags for %s", name) + + resp, err := rmqc.PutUser(name, userSettings) + log.Printf("[DEBUG] RabbitMQ: Tags update response: %#v", resp) + if err != nil { + return err + } + + if resp.StatusCode >= 400 { + return fmt.Errorf("Error updating RabbitMQ user: %s", resp.Status) + } + + } + + return ReadUser(d, meta) +} + +func DeleteUser(d *schema.ResourceData, meta interface{}) error { + rmqc := meta.(*rabbithole.Client) + + name := d.Id() + log.Printf("[DEBUG] RabbitMQ: Attempting to delete user %s", name) + + resp, err := rmqc.DeleteUser(name) + log.Printf("[DEBUG] RabbitMQ: User delete response: %#v", resp) + if err != nil { + return err + } + + if resp.StatusCode == 404 { + // the user was automatically deleted + return nil + } + + if resp.StatusCode >= 400 { + return fmt.Errorf("Error deleting RabbitMQ user: %s", resp.Status) + } + + return nil +} diff --git a/builtin/providers/rabbitmq/resource_user_test.go b/builtin/providers/rabbitmq/resource_user_test.go new file mode 100644 index 0000000000..6876134bff --- /dev/null +++ b/builtin/providers/rabbitmq/resource_user_test.go @@ -0,0 +1,94 @@ +package rabbitmq + +import ( + "fmt" + "testing" + + "github.com/michaelklishin/rabbit-hole" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccUser(t *testing.T) { + var user string + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccUserCheckDestroy(user), + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccUserConfig_basic, + Check: testAccUserCheck( + "rabbitmq_user.test", &user, + ), + }, + resource.TestStep{ + Config: testAccUserConfig_update, + Check: testAccUserCheck( + "rabbitmq_user.test", &user, + ), + }, + }, + }) +} + +func testAccUserCheck(rn string, name *string) 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("user id not set") + } + + rmqc := testAccProvider.Meta().(*rabbithole.Client) + users, err := rmqc.ListUsers() + if err != nil { + return fmt.Errorf("Error retrieving users: %s", err) + } + + for _, user := range users { + if user.Name == rs.Primary.ID { + *name = rs.Primary.ID + return nil + } + } + + return fmt.Errorf("Unable to find user %s", rn) + } +} + +func testAccUserCheckDestroy(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rmqc := testAccProvider.Meta().(*rabbithole.Client) + users, err := rmqc.ListUsers() + if err != nil { + return fmt.Errorf("Error retrieving users: %s", err) + } + + for _, user := range users { + if user.Name == name { + return fmt.Errorf("user still exists: %s", name) + } + } + + return nil + } +} + +const testAccUserConfig_basic = ` +resource "rabbitmq_user" "test" { + name = "mctest" + password = "foobar" + tags = ["administrator", "management"] +}` + +const testAccUserConfig_update = ` +resource "rabbitmq_user" "test" { + name = "mctest" + password = "foobarry" + tags = ["management"] +}`