Skip to content

Commit

Permalink
Add resource identity_user_membership_v3
Browse files Browse the repository at this point in the history
Add support for new resources indentity_user_membership_v3.
The resources is used to add users to groups.
  • Loading branch information
nikParasyr committed Jan 29, 2021
1 parent d612600 commit d8bbcf3
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
1 change: 1 addition & 0 deletions openstack/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ func Provider() terraform.ResourceProvider {
"openstack_identity_role_assignment_v3": resourceIdentityRoleAssignmentV3(),
"openstack_identity_service_v3": resourceIdentityServiceV3(),
"openstack_identity_user_v3": resourceIdentityUserV3(),
"openstack_identity_user_membership_v3": resourceIdentityUserMembershipV3(),
"openstack_identity_group_v3": resourceIdentityGroupV3(),
"openstack_identity_application_credential_v3": resourceIdentityApplicationCredentialV3(),
"openstack_identity_ec2_credential_v3": resourceIdentityEc2CredentialV3(),
Expand Down
118 changes: 118 additions & 0 deletions openstack/resource_openstack_identity_user_membership_v3.go
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 openstack/resource_openstack_identity_user_membership_v3_test.go
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)
}
79 changes: 79 additions & 0 deletions website/docs/r/identity_user_membership_v3.html.markdown
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>
```
3 changes: 3 additions & 0 deletions website/openstack.erb
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@
<li<%= sidebar_current("docs-openstack-resource-identity-user-v3") %>>
<a href="/docs/providers/openstack/r/identity_user_v3.html">openstack_identity_user_v3</a>
</li>
<li<%= sidebar_current("docs-openstack-resource-identity-user-membership-v3") %>>
<a href="/docs/providers/openstack/r/identity_user_membership_v3.html">openstack_identity_user_membership_v3</a>
</li>
<li<%= sidebar_current("docs-openstack-resource-identity-service-v3") %>>
<a href="/docs/providers/openstack/r/identity_service_v3.html">openstack_identity_service_v3</a>
</li>
Expand Down

0 comments on commit d8bbcf3

Please sign in to comment.