-
Notifications
You must be signed in to change notification settings - Fork 359
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add resource identity_user_membership_v3
Add support for new resources indentity_user_membership_v3. The resources is used to add users to groups.
- Loading branch information
1 parent
d612600
commit d8bbcf3
Showing
5 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
openstack/resource_openstack_identity_user_membership_v3.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package openstack | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/gophercloud/gophercloud/openstack/identity/v3/users" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
func resourceIdentityUserMembershipV3() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceIdentityUserMembershipV3Create, | ||
Read: resourceIdentityUserMembershipV3Read, | ||
Delete: resourceIdentityUserMembershipV3Delete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"region": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
"user_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"group_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceIdentityUserMembershipV3Create(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
identityClient, err := config.IdentityV3Client(GetRegion(d, config)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack identity client: %s", err) | ||
} | ||
|
||
userID := d.Get("user_id").(string) | ||
groupID := d.Get("group_id").(string) | ||
|
||
if err := users.AddToGroup(identityClient, groupID, userID).ExtractErr(); err != nil { | ||
return fmt.Errorf("Error adding user %s to group %s: %s", userID, groupID, err) | ||
} | ||
|
||
id := fmt.Sprintf("%s/%s", userID, groupID) | ||
d.SetId(id) | ||
|
||
return resourceIdentityUserMembershipV3Read(d, meta) | ||
} | ||
|
||
func resourceIdentityUserMembershipV3Read(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
identityClient, err := config.IdentityV3Client(GetRegion(d, config)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack identity client: %s", err) | ||
} | ||
|
||
userID, groupID, err := parseUserMembershipID(d.Id()) | ||
if err != nil { | ||
return CheckDeleted(d, err, "Error parsing user membership ID") | ||
} | ||
|
||
userMembership, err := users.IsMemberOfGroup(identityClient, groupID, userID).Extract() | ||
if err != nil { | ||
return CheckDeleted(d, err, "Error getting user membership") | ||
} | ||
|
||
if !userMembership { | ||
return fmt.Errorf("Error user membership %s to group %s does not exist", userID, groupID) | ||
} | ||
|
||
d.Set("region", GetRegion(d, config)) | ||
d.Set("user_id", userID) | ||
d.Set("group_id", groupID) | ||
|
||
return nil | ||
} | ||
|
||
func resourceIdentityUserMembershipV3Delete(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
identityClient, err := config.IdentityV3Client(GetRegion(d, config)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack identity client: %s", err) | ||
} | ||
|
||
userID, groupID, err := parseUserMembershipID(d.Id()) | ||
if err != nil { | ||
return CheckDeleted(d, err, "Error parsing user membership ID") | ||
} | ||
|
||
if err := users.RemoveFromGroup(identityClient, groupID, userID).ExtractErr(); err != nil { | ||
return CheckDeleted(d, err, fmt.Sprintf("Error removing user %s membership from group %s", userID, groupID)) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func parseUserMembershipID(id string) (string, string, error) { | ||
idParts := strings.Split(id, "/") | ||
if len(idParts) < 2 { | ||
return "", "", fmt.Errorf("Unable to determine user membership ID") | ||
} | ||
|
||
userID := idParts[0] | ||
groupID := idParts[1] | ||
|
||
return userID, groupID, nil | ||
} |
118 changes: 118 additions & 0 deletions
118
openstack/resource_openstack_identity_user_membership_v3_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package openstack | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/terraform" | ||
|
||
"github.com/gophercloud/gophercloud/openstack/identity/v3/groups" | ||
"github.com/gophercloud/gophercloud/openstack/identity/v3/users" | ||
) | ||
|
||
func TestAccIdentityV3UserMembership_basic(t *testing.T) { | ||
var group groups.Group | ||
var groupName = fmt.Sprintf("ACCPTTEST-%s", acctest.RandString(5)) | ||
|
||
var user users.User | ||
var userName = fmt.Sprintf("ACCPTTEST-%s", acctest.RandString(5)) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { | ||
testAccPreCheck(t) | ||
testAccPreCheckAdminOnly(t) | ||
}, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckIdentityV3UserMembershipDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccIdentityV3UserMembershipBasic(groupName, userName), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckIdentityV3UserExists("openstack_identity_user_v3.user_1", &user), | ||
testAccCheckIdentityV3GroupExists("openstack_identity_group_v3.group_1", &group), | ||
testAccCheckIdentityV3UserMembershipExists("openstack_identity_user_membership_v3.user_membership_1"), | ||
resource.TestCheckResourceAttrPtr( | ||
"openstack_identity_user_membership_v3.user_membership_1", "user_id", &user.ID), | ||
resource.TestCheckResourceAttrPtr( | ||
"openstack_identity_user_membership_v3.user_membership_1", "group_id", &group.ID), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckIdentityV3UserMembershipDestroy(s *terraform.State) error { | ||
config := testAccProvider.Meta().(*Config) | ||
identityClient, err := config.IdentityV3Client(osRegionName) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack identity client: %s", err) | ||
} | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "openstack_identity_user_membership_v3" { | ||
continue | ||
} | ||
|
||
uid, gid, err := parseUserMembershipID(rs.Primary.ID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
um, err := users.IsMemberOfGroup(identityClient, gid, uid).Extract() | ||
if err == nil && um { | ||
return fmt.Errorf("User membership still exists") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccCheckIdentityV3UserMembershipExists(n string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No ID is set") | ||
} | ||
|
||
config := testAccProvider.Meta().(*Config) | ||
identityClient, err := config.IdentityV3Client(osRegionName) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack identity client: %s", err) | ||
} | ||
|
||
uid, gid, err := parseUserMembershipID(rs.Primary.ID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
um, err := users.IsMemberOfGroup(identityClient, gid, uid).Extract() | ||
if err != nil || !um { | ||
return fmt.Errorf("User membership not found") | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccIdentityV3UserMembershipBasic(groupName, userName string) string { | ||
return fmt.Sprintf(` | ||
resource "openstack_identity_group_v3" "group_1" { | ||
name = "%s" | ||
} | ||
resource "openstack_identity_user_v3" "user_1" { | ||
name = "%s" | ||
} | ||
resource "openstack_identity_user_membership_v3" "user_membership_1" { | ||
user_id = "${openstack_identity_user_v3.user_1.id}" | ||
group_id = "${openstack_identity_group_v3.group_1.id}" | ||
} | ||
`, groupName, userName) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
--- | ||
layout: "openstack" | ||
page_title: "OpenStack: openstack_identity_user_membership_v3" | ||
sidebar_current: "docs-openstack-resource-identity-user-membership-v3" | ||
description: |- | ||
Manages a user membership to group V3 resource within OpenStack. | ||
--- | ||
|
||
# openstack\_identity\_user\_membership_v3 | ||
|
||
Manages a user membership to group V3 resource within OpenStack. | ||
|
||
Note: You _must_ have admin privileges in your OpenStack cloud to use | ||
this resource. | ||
|
||
--- | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "openstack_identity_project_v3" "project_1" { | ||
name = "project_1" | ||
} | ||
resource "openstack_identity_user_v3" "user_1" { | ||
name = "user_1" | ||
default_project_id = "${openstack_identity_project_v3.project_1.id}" | ||
} | ||
resource "openstack_identity_group_v3" "group_1" { | ||
name = "group_1" | ||
description = "group 1" | ||
} | ||
resource "openstack_identity_role_v3" "role_1" { | ||
name = "role_1" | ||
} | ||
resource "openstack_identity_user_membership_v3" "user_membership_1" { | ||
user_id = "${openstack_identity_user_v3.user_1.id}" | ||
group_id = "${openstack_identity_group_v3.group_1.id}" | ||
} | ||
resource "openstack_identity_role_assignment_v3" "role_assignment_1" { | ||
group_id = "${openstack_identity_group_v3.group_1.id}" | ||
project_id = "${openstack_identity_project_v3.project_1.id}" | ||
role_id = "${openstack_identity_role_v3.role_1.id}" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `region` - (Optional) The region in which to obtain the V3 Identity client. | ||
If omitted, the `region` argument of the provider is used. | ||
Changing this creates a new user membership. | ||
|
||
* `user_id` - (Required) The UUID of user to use. Changing this creates a new user membership. | ||
|
||
* `group_id` - (Required) The UUID of group to which the user will be added. | ||
Changing this creates a new user membership. | ||
|
||
## Attributes Reference | ||
|
||
The following attributes are exported: | ||
|
||
* `region` - See Argument Reference above. | ||
* `user_id` - See Argument Reference above. | ||
* `group_id` - See Argument Reference above. | ||
|
||
## Import | ||
|
||
This resource can be imported by specifying all two arguments, separated | ||
by a forward slash: | ||
|
||
``` | ||
$ terraform import openstack_identity_user_membership_v3.user_membership_1 <user_id>/<group_id> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters