Skip to content

Commit

Permalink
Fix minio_iam_user_policy_attachment error: Provider produced inconsi…
Browse files Browse the repository at this point in the history
…stent result after apply (#495)

Signed-off-by: Adphi <[email protected]>
  • Loading branch information
Adphi authored Jul 29, 2023
1 parent 6cdd43c commit 39e7b92
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 6 deletions.
22 changes: 19 additions & 3 deletions minio/resource_minio_iam_group_policy_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/minio/madmin-go"
)

var groupPolicyAttachmentLock = NewMutexKV()

func resourceMinioIAMGroupPolicyAttachment() *schema.Resource {
return &schema.Resource{
CreateContext: minioCreateGroupPolicyAttachment,
Expand Down Expand Up @@ -44,6 +46,9 @@ func minioCreateGroupPolicyAttachment(ctx context.Context, d *schema.ResourceDat
var groupName = d.Get("group_name").(string)
var policyName = d.Get("policy_name").(string)

groupPolicyAttachmentLock.Lock(groupName)
defer groupPolicyAttachmentLock.Unlock(groupName)

policies, err := minioReadGroupPolicies(ctx, minioAdmin, groupName)
if err != nil {
return err
Expand All @@ -59,15 +64,20 @@ func minioCreateGroupPolicyAttachment(ctx context.Context, d *schema.ResourceDat

d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%s-", groupName)))

return minioReadGroupPolicyAttachment(ctx, d, meta)
return doMinioReadGroupPolicyAttachment(ctx, d, meta, groupName, policyName)
}

func minioReadGroupPolicyAttachment(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
minioAdmin := meta.(*S3MinioClient).S3Admin

var groupName = d.Get("group_name").(string)
var policyName = d.Get("policy_name").(string)

groupPolicyAttachmentLock.Lock(groupName)
defer groupPolicyAttachmentLock.Unlock(groupName)

return doMinioReadGroupPolicyAttachment(ctx, d, meta, groupName, policyName)
}
func doMinioReadGroupPolicyAttachment(ctx context.Context, d *schema.ResourceData, meta interface{}, groupName, policyName string) diag.Diagnostics {
minioAdmin := meta.(*S3MinioClient).S3Admin
policies, err := minioReadGroupPolicies(ctx, minioAdmin, groupName)
if err != nil {
return err
Expand All @@ -91,6 +101,9 @@ func minioDeleteGroupPolicyAttachment(ctx context.Context, d *schema.ResourceDat
var groupName = d.Get("group_name").(string)
var policyName = d.Get("policy_name").(string)

groupPolicyAttachmentLock.Lock(groupName)
defer groupPolicyAttachmentLock.Unlock(groupName)

policies, err := minioReadGroupPolicies(ctx, minioAdmin, groupName)
if err != nil {
return err
Expand Down Expand Up @@ -135,5 +148,8 @@ func minioReadGroupPolicies(ctx context.Context, minioAdmin *madmin.AdminClient,
if errGroup != nil {
return nil, NewResourceError("failed to load group infos", groupName, errGroup)
}
if groupInfo.Policy == "" {
return nil, nil
}
return strings.Split(groupInfo.Policy, ","), nil
}
25 changes: 22 additions & 3 deletions minio/resource_minio_iam_user_policy_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/minio/madmin-go"
)

var userPolicyAttachmentLock = NewMutexKV()

func resourceMinioIAMUserPolicyAttachment() *schema.Resource {
return &schema.Resource{
CreateContext: minioCreateUserPolicyAttachment,
Expand Down Expand Up @@ -44,12 +46,16 @@ func minioCreateUserPolicyAttachment(ctx context.Context, d *schema.ResourceData
var policyName = d.Get("policy_name").(string)
minioAdmin := meta.(*S3MinioClient).S3Admin

userPolicyAttachmentLock.Lock(userName)
defer userPolicyAttachmentLock.Unlock(userName)

policies, err := minioReadUserPolicies(ctx, minioAdmin, userName)
if err != nil {
return err
}
if !Contains(policies, policyName) {
policies = append(policies, policyName)
log.Printf("[DEBUG] Attaching policy %s to user: %s (%v)", policyName, userName, policies)
err := minioAdmin.SetPolicy(ctx, strings.Join(policies, ","), userName, false)
if err != nil {
return NewResourceError("unable to Set User policy", userName+" "+policyName, err)
Expand All @@ -58,14 +64,20 @@ func minioCreateUserPolicyAttachment(ctx context.Context, d *schema.ResourceData

d.SetId(id.PrefixedUniqueId(fmt.Sprintf("%s-", userName)))

return minioReadUserPolicyAttachment(ctx, d, meta)
return doMinioReadUserPolicyAttachment(ctx, d, meta, userName, policyName)
}

func minioReadUserPolicyAttachment(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
minioAdmin := meta.(*S3MinioClient).S3Admin
var userName = d.Get("user_name").(string)
var policyName = d.Get("policy_name").(string)

userPolicyAttachmentLock.Lock(userName)
defer userPolicyAttachmentLock.Unlock(userName)

return doMinioReadUserPolicyAttachment(ctx, d, meta, userName, policyName)
}
func doMinioReadUserPolicyAttachment(ctx context.Context, d *schema.ResourceData, meta interface{}, userName, policyName string) diag.Diagnostics {
minioAdmin := meta.(*S3MinioClient).S3Admin

policies, errUser := minioReadUserPolicies(ctx, minioAdmin, userName)
if errUser != nil {
return errUser
Expand All @@ -90,6 +102,9 @@ func minioDeleteUserPolicyAttachment(ctx context.Context, d *schema.ResourceData
var userName = d.Get("user_name").(string)
var policyName = d.Get("policy_name").(string)

userPolicyAttachmentLock.Lock(userName)
defer userPolicyAttachmentLock.Unlock(userName)

policies, err := minioReadUserPolicies(ctx, minioAdmin, userName)
if err != nil {
return err
Expand All @@ -100,6 +115,7 @@ func minioDeleteUserPolicyAttachment(ctx context.Context, d *schema.ResourceData
return nil
}

log.Printf("[DEBUG] Detaching policy %s from user: %s (%v)", policyName, userName, newPolicies)
errIam := minioAdmin.SetPolicy(ctx, strings.Join(newPolicies, ","), userName, false)
if errIam != nil {
return NewResourceError("unable to delete user policy", userName, errIam)
Expand Down Expand Up @@ -144,5 +160,8 @@ func minioReadUserPolicies(ctx context.Context, minioAdmin *madmin.AdminClient,
return nil, NewResourceError("failed to load user Infos", userName, errUser)
}
}
if userInfo.PolicyName == "" {
return nil, nil
}
return strings.Split(userInfo.PolicyName, ","), nil
}
47 changes: 47 additions & 0 deletions minio/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/base64"
"errors"
"hash/crc32"
"log"
"sync"

"github.com/aws/aws-sdk-go/aws"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -88,3 +90,48 @@ func HashcodeString(s string) int {
// v == MinInt
return 0
}

// MutexKV is a simple key/value store for arbitrary mutexes. It can be used to
// serialize changes across arbitrary collaborators that share knowledge of the
// keys they must serialize on.
//
// The initial use case is to let aws_security_group_rule resources serialize
// their access to individual security groups based on SG ID.
type MutexKV struct {
lock sync.Mutex
store map[string]*sync.Mutex
}

// Locks the mutex for the given key. Caller is responsible for calling Unlock
// for the same key
func (m *MutexKV) Lock(key string) {
log.Printf("[DEBUG] Locking %q", key)
m.get(key).Lock()
log.Printf("[DEBUG] Locked %q", key)
}

// Unlock the mutex for the given key. Caller must have called Lock for the same key first
func (m *MutexKV) Unlock(key string) {
log.Printf("[DEBUG] Unlocking %q", key)
m.get(key).Unlock()
log.Printf("[DEBUG] Unlocked %q", key)
}

// Returns a mutex for the given key, no guarantee of its lock status
func (m *MutexKV) get(key string) *sync.Mutex {
m.lock.Lock()
defer m.lock.Unlock()
mutex, ok := m.store[key]
if !ok {
mutex = &sync.Mutex{}
m.store[key] = mutex
}
return mutex
}

// Returns a properly initialized MutexKV
func NewMutexKV() *MutexKV {
return &MutexKV{
store: make(map[string]*sync.Mutex),
}
}

0 comments on commit 39e7b92

Please sign in to comment.