Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into iam_federations
Browse files Browse the repository at this point in the history
shlykov authored Aug 6, 2024
2 parents e6e8b37 + ed53490 commit bf7e591
Showing 12 changed files with 809 additions and 14 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ require (
github.com/selectel/domains-go v1.0.2
github.com/selectel/go-selvpcclient/v3 v3.1.1
github.com/selectel/iam-go v0.4.1
github.com/selectel/mks-go v0.14.0
github.com/selectel/mks-go v0.15.0
github.com/selectel/secretsmanager-go v0.2.1
github.com/stretchr/testify v1.8.4
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -172,8 +172,8 @@ github.com/selectel/go-selvpcclient/v3 v3.1.1 h1:C1q2LqqosiapoLpnGITGmysg0YCSQYD
github.com/selectel/go-selvpcclient/v3 v3.1.1/go.mod h1:NM7IXhh1IzqZ88DOw1Qc5Ez3tULLViXo95l5+rKPuyQ=
github.com/selectel/iam-go v0.4.1 h1:grncCGkPVCM6nwqSTk+q15M5ZO6S/Pe0AIbbmKtm6gU=
github.com/selectel/iam-go v0.4.1/go.mod h1:OIAkW7MZK97YUm+uvUgYbgDhkI9SdzTCxwd4yZoOR1o=
github.com/selectel/mks-go v0.14.0 h1:huNq/oTutPc3ezB8HRqlGN9WJubTDETpNKuIVqcZOn0=
github.com/selectel/mks-go v0.14.0/go.mod h1:VxtV3dzwgOEzZc+9VMQb9DvxfSlej2ZQ8jnT8kqIGgU=
github.com/selectel/mks-go v0.15.0 h1:0ytV5DiQAgbojKA0ukBjtwfWBSQh658nF3mhjZTrWj8=
github.com/selectel/mks-go v0.15.0/go.mod h1:VxtV3dzwgOEzZc+9VMQb9DvxfSlej2ZQ8jnT8kqIGgU=
github.com/selectel/secretsmanager-go v0.2.1 h1:OSBrA/07lm/Ecpwg59IJHFAoUHZR29oyfwUgTpr/dos=
github.com/selectel/secretsmanager-go v0.2.1/go.mod h1:DUPexhiJWLTyZEvse7grJWdcA8p8TEI93gNu1dDu7Yg=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
4 changes: 4 additions & 0 deletions selectel/provider.go
Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@ const (
objectS3Credentials = "s3 credentials"
objectSAMLFederation = "saml federation"
objectSAMLFederationCertificate = "saml federation certificate"
objectGroup = "group"
objectGroupMembership = "group-membership"
objectCluster = "cluster"
objectKubeConfig = "kubeconfig"
objectKubeVersions = "kube-versions"
@@ -139,6 +141,8 @@ func Provider() *schema.Provider {
"selectel_iam_s3_credentials_v1": resourceIAMS3CredentialsV1(),
"selectel_iam_saml_federation_v1": resourceIAMSAMLFederationV1(),
"selectel_iam_saml_federation_certificate_v1": resourceIAMSAMLFederationCertificateV1(),
"selectel_iam_group_v1": resourceIAMGroupV1(),
"selectel_iam_group_membership_v1": resourceIAMGroupMembershipV1(),
"selectel_vpc_vrrp_subnet_v2": resourceVPCVRRPSubnetV2(), // DEPRECATED
"selectel_vpc_crossregion_subnet_v2": resourceVPCCrossRegionSubnetV2(), // DEPRECATED
"selectel_mks_cluster_v1": resourceMKSClusterV1(),
178 changes: 178 additions & 0 deletions selectel/resource_selectel_iam_group_membership_v1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package selectel

import (
"context"
"fmt"
"log"

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

func resourceIAMGroupMembershipV1() *schema.Resource {
return &schema.Resource{
CreateContext: resourceIAMGroupMembershipV1Create,
ReadContext: resourceIAMGroupMembershipV1Read,
UpdateContext: resourceIAMGroupMembershipV1Update,
DeleteContext: resourceIAMGroupMembershipV1Delete,
Schema: map[string]*schema.Schema{
"group_id": {
Type: schema.TypeString,
Required: true,
},
"user_ids": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func resourceIAMGroupMembershipV1Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
iamClient, diagErr := getIAMClient(meta)
if diagErr != nil {
return diagErr
}

userIDsInterface := d.Get("user_ids").([]interface{})
userIDs := make([]string, len(userIDsInterface))
for i, v := range userIDsInterface {
userIDs[i] = v.(string)
}
log.Print(msgCreate(objectGroupMembership, userIDs))

if len(userIDs) == 0 {
createErr := fmt.Errorf("error creating group membership: no user ids specified")
return diag.FromErr(errCreatingObject(objectGroupMembership, createErr))
}
err := iamClient.Groups.AddUsers(ctx, d.Get("group_id").(string), userIDs)
if err != nil {
return diag.FromErr(errCreatingObject(objectGroupMembership, err))
}

d.SetId(d.Get("group_id").(string))

return resourceIAMGroupMembershipV1Read(ctx, d, meta)
}

func resourceIAMGroupMembershipV1Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
iamClient, diagErr := getIAMClient(meta)
if diagErr != nil {
return diagErr
}

groupID := d.Id()

userIDsInterface := d.Get("user_ids").([]interface{})
userIDs := make([]string, len(userIDsInterface))
for i, v := range userIDsInterface {
userIDs[i] = v.(string)
}

response, err := iamClient.Groups.Get(ctx, groupID)
if err != nil {
return diag.FromErr(errGettingObject(objectGroupMembership, d.Id(), err))
}

responseUserIDs := make([]string, 0)
for _, user := range response.Users {
responseUserIDs = append(responseUserIDs, user.KeystoneID)
}

responseServiceUserIDs := make([]string, 0)
for _, serviceUser := range response.ServiceUsers {
responseServiceUserIDs = append(responseServiceUserIDs, serviceUser.ID)
}

d.Set("group_id", groupID)
d.Set("user_ids", append(responseUserIDs, responseServiceUserIDs...))

return nil
}

func resourceIAMGroupMembershipV1Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
iamClient, diagErr := getIAMClient(meta)
if diagErr != nil {
return diagErr
}

groupID := d.Id()

oldValue, newValue := d.GetChange("user_ids")

oldUserIDs := make(map[string]struct{})
for _, v := range oldValue.([]interface{}) {
oldUserIDs[v.(string)] = struct{}{}
}

newUserIDs := make(map[string]struct{})
for _, v := range newValue.([]interface{}) {
newUserIDs[v.(string)] = struct{}{}
}

usersToAdd, usersToRemove := diffUsers(oldUserIDs, newUserIDs)

if len(usersToAdd) > 0 {
err := iamClient.Groups.AddUsers(ctx, groupID, usersToAdd)
if err != nil {
return diag.FromErr(err)
}
}

if len(usersToRemove) > 0 {
err := iamClient.Groups.DeleteUsers(ctx, groupID, usersToRemove)
if err != nil {
return diag.FromErr(err)
}
}

d.SetId(groupID)

return resourceIAMGroupMembershipV1Read(ctx, d, meta)
}

func resourceIAMGroupMembershipV1Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
iamClient, diagErr := getIAMClient(meta)
if diagErr != nil {
return diagErr
}

groupID := d.Id()

userIDsInterface := d.Get("user_ids").([]interface{})
userIDs := make([]string, len(userIDsInterface))
for i, v := range userIDsInterface {
userIDs[i] = v.(string)
}

err := iamClient.Groups.DeleteUsers(ctx, groupID, userIDs)
if err != nil {
return diag.FromErr(errDeletingObject(objectGroupMembership, d.Id(), err))
}

d.SetId("")

return nil
}

func diffUsers(oldUsers, newUsers map[string]struct{}) ([]string, []string) {
usersToAdd := make([]string, 0)
usersToRemove := make([]string, 0)

for id := range newUsers {
if _, ok := oldUsers[id]; !ok {
usersToAdd = append(usersToAdd, id)
}
}

for id := range oldUsers {
if _, ok := newUsers[id]; !ok {
usersToRemove = append(usersToRemove, id)
}
}

return usersToAdd, usersToRemove
}
136 changes: 136 additions & 0 deletions selectel/resource_selectel_iam_group_membership_v1_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package selectel

import (
"testing"

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

func TestAccIAMV1GroupMembershipBasic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccSelectelPreCheck(t) },
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccIAMV1GroupMembershipBasic(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "group_id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "user_ids.0"),
),
},
},
})
}

func TestAccIAMV1GroupUpdate(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccSelectelPreCheck(t) },
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccIAMV1GroupMembershipBasic(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "group_id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "user_ids.0"),
),
},
{
Config: testAccIAMV1GroupMembershipUpdate(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "group_id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "user_ids.0"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "user_ids.1"),
),
},
{
Config: testAccIAMV1GroupMembershipBasic(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "group_id"),
resource.TestCheckResourceAttrSet("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "user_ids.0"),
resource.TestCheckNoResourceAttr("selectel_iam_group_membership_v1.membership_tf_acc_test_1", "user_ids.1"),
),
},
},
})
}

func testAccIAMV1GroupMembershipBasic() string {
return `
resource "selectel_iam_serviceuser_v1" "serviceuser_tf_acc_test_1" {
name = "test-service-user-1"
password = "Qazwsxedc123"
role {
role_name = "reader"
scope = "account"
}
}
resource "selectel_iam_serviceuser_v1" "serviceuser_tf_acc_test_2" {
name = "test-service-user-2"
password = "Qazwsxedc123"
role {
role_name = "reader"
scope = "account"
}
}
resource "selectel_iam_group_v1" "group_tf_acc_test_1" {
name = "test-group"
role {
role_name = "reader"
scope = "account"
}
}
resource "selectel_iam_group_membership_v1" "membership_tf_acc_test_1" {
group_id = selectel_iam_group_v1.group_tf_acc_test_1.id
user_ids = [
selectel_iam_serviceuser_v1.serviceuser_tf_acc_test_1.id
]
}
`
}

func testAccIAMV1GroupMembershipUpdate() string {
return `
resource "selectel_iam_serviceuser_v1" "serviceuser_tf_acc_test_1" {
name = "test-service-user-1"
password = "Qazwsxedc123"
role {
role_name = "reader"
scope = "account"
}
}
resource "selectel_iam_serviceuser_v1" "serviceuser_tf_acc_test_2" {
name = "test-service-user-2"
password = "Qazwsxedc123"
role {
role_name = "reader"
scope = "account"
}
}
resource "selectel_iam_group_v1" "group_tf_acc_test_1" {
name = "test-group"
role {
role_name = "reader"
scope = "account"
}
}
resource "selectel_iam_group_membership_v1" "membership_tf_acc_test_1" {
group_id = selectel_iam_group_v1.group_tf_acc_test_1.id
user_ids = [
selectel_iam_serviceuser_v1.serviceuser_tf_acc_test_1.id,
selectel_iam_serviceuser_v1.serviceuser_tf_acc_test_2.id
]
}
`
}
Loading

0 comments on commit bf7e591

Please sign in to comment.