Skip to content

Commit

Permalink
Merge pull request hashicorp#19693 from DrFaust92/r/transfer_server_u…
Browse files Browse the repository at this point in the history
…ser_efs

r/transfer_user - add support for `posix_profile`
  • Loading branch information
ewbankkit authored Jun 8, 2021
2 parents 05bd6a5 + 174d62e commit debac80
Show file tree
Hide file tree
Showing 7 changed files with 411 additions and 180 deletions.
3 changes: 3 additions & 0 deletions .changelog/19693.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_transfer_user: Add `posix_profile` argument.
```
29 changes: 29 additions & 0 deletions aws/internal/service/transfer/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,32 @@ func ServerByID(conn *transfer.Transfer, id string) (*transfer.DescribedServer,

return output.Server, nil
}

func UserByID(conn *transfer.Transfer, serverId, userName string) (*transfer.DescribeUserOutput, error) {
input := &transfer.DescribeUserInput{
ServerId: aws.String(serverId),
UserName: aws.String(userName),
}

output, err := conn.DescribeUser(input)

if tfawserr.ErrCodeEquals(err, transfer.ErrCodeResourceNotFoundException) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || output.User == nil {
return nil, &resource.NotFoundError{
Message: "Empty result",
LastRequest: input,
}
}

return output, nil
}
16 changes: 16 additions & 0 deletions aws/internal/service/transfer/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,19 @@ func ServerState(conn *transfer.Transfer, id string) resource.StateRefreshFunc {
return output, aws.StringValue(output.State), nil
}
}

func UserState(conn *transfer.Transfer, serverId, userName string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := finder.UserByID(conn, serverId, userName)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, "Available", nil
}
}
18 changes: 18 additions & 0 deletions aws/internal/service/transfer/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

const (
ServerDeletedTimeout = 10 * time.Minute
UserDeletedTimeout = 10 * time.Minute
)

func ServerCreated(conn *transfer.Transfer, id string, timeout time.Duration) (*transfer.DescribedServer, error) {
Expand Down Expand Up @@ -78,3 +79,20 @@ func ServerStopped(conn *transfer.Transfer, id string, timeout time.Duration) (*

return nil, err
}

func UserDeleted(conn *transfer.Transfer, serverId, userName string) (*transfer.DescribedUser, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{"Available"},
Target: []string{},
Refresh: UserState(conn, serverId, userName),
Timeout: UserDeletedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*transfer.DescribedUser); ok {
return output, err
}

return nil, err
}
153 changes: 93 additions & 60 deletions aws/resource_aws_transfer_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package aws
import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/transfer"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
tftransfer "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/transfer"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/transfer/finder"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/transfer/waiter"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

func resourceAwsTransferUser() *schema.Resource {
Expand Down Expand Up @@ -69,6 +70,28 @@ func resourceAwsTransferUser() *schema.Resource {
ValidateFunc: validateIAMPolicyJson,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},
"posix_profile": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"gid": {
Type: schema.TypeInt,
Required: true,
},
"uid": {
Type: schema.TypeInt,
Required: true,
},
"secondary_gids": {
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeInt},
Optional: true,
},
},
},
},

"role": {
Type: schema.TypeString,
Expand Down Expand Up @@ -124,6 +147,10 @@ func resourceAwsTransferUserCreate(d *schema.ResourceData, meta interface{}) err
createOpts.HomeDirectoryMappings = expandAwsTransferHomeDirectoryMappings(attr.([]interface{}))
}

if attr, ok := d.GetOk("posix_profile"); ok {
createOpts.PosixProfile = expandTransferUserPosixUser(attr.([]interface{}))
}

if attr, ok := d.GetOk("policy"); ok {
createOpts.Policy = aws.String(attr.(string))
}
Expand Down Expand Up @@ -154,36 +181,34 @@ func resourceAwsTransferUserRead(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("error parsing Transfer User ID: %s", err)
}

descOpts := &transfer.DescribeUserInput{
UserName: aws.String(userName),
ServerId: aws.String(serverID),
resp, err := finder.UserByID(conn, serverID, userName)
if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] Transfer User (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

log.Printf("[DEBUG] Describe Transfer User Option: %#v", descOpts)

resp, err := conn.DescribeUser(descOpts)
if err != nil {
if isAWSErr(err, transfer.ErrCodeResourceNotFoundException, "") {
log.Printf("[WARN] Transfer User (%s) for Server (%s) not found, removing from state", userName, serverID)
d.SetId("")
return nil
}
return fmt.Errorf("error reading Transfer User (%s): %s", d.Id(), err)
return fmt.Errorf("error reading Transfer User (%s): %w", d.Id(), err)
}

user := resp.User
d.Set("server_id", resp.ServerId)
d.Set("user_name", resp.User.UserName)
d.Set("arn", resp.User.Arn)
d.Set("home_directory", resp.User.HomeDirectory)
d.Set("home_directory_type", resp.User.HomeDirectoryType)
d.Set("policy", resp.User.Policy)
d.Set("role", resp.User.Role)
d.Set("user_name", user.UserName)
d.Set("arn", user.Arn)
d.Set("home_directory", user.HomeDirectory)
d.Set("home_directory_type", user.HomeDirectoryType)
d.Set("policy", user.Policy)
d.Set("role", user.Role)

if err := d.Set("home_directory_mappings", flattenAwsTransferHomeDirectoryMappings(resp.User.HomeDirectoryMappings)); err != nil {
return fmt.Errorf("Error setting home_directory_mappings: %s", err)
if err := d.Set("home_directory_mappings", flattenAwsTransferHomeDirectoryMappings(user.HomeDirectoryMappings)); err != nil {
return fmt.Errorf("Error setting home_directory_mappings: %w", err)
}

tags := keyvaluetags.TransferKeyValueTags(resp.User.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig)
if err := d.Set("posix_profile", flattenTransferUserPosixUser(user.PosixProfile)); err != nil {
return fmt.Errorf("Error setting posix_profile: %w", err)
}
tags := keyvaluetags.TransferKeyValueTags(user.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig)

//lintignore:AWSR002
if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
Expand Down Expand Up @@ -219,6 +244,11 @@ func resourceAwsTransferUserUpdate(d *schema.ResourceData, meta interface{}) err
updateFlag = true
}

if d.HasChange("posix_profile") {
updateOpts.PosixProfile = expandTransferUserPosixUser(d.Get("posix_profile").([]interface{}))
updateFlag = true
}

if d.HasChange("home_directory_type") {
updateOpts.HomeDirectoryType = aws.String(d.Get("home_directory_type").(string))
updateFlag = true
Expand All @@ -242,14 +272,14 @@ func resourceAwsTransferUserUpdate(d *schema.ResourceData, meta interface{}) err
d.SetId("")
return nil
}
return fmt.Errorf("error updating Transfer User (%s): %s", d.Id(), err)
return fmt.Errorf("error updating Transfer User (%s): %w", d.Id(), err)
}
}

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")
if err := keyvaluetags.TransferUpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
return fmt.Errorf("error updating tags: %s", err)
return fmt.Errorf("error updating tags: %w", err)
}
}

Expand All @@ -260,7 +290,7 @@ func resourceAwsTransferUserDelete(d *schema.ResourceData, meta interface{}) err
conn := meta.(*AWSClient).transferconn
serverID, userName, err := tftransfer.UserParseResourceID(d.Id())
if err != nil {
return fmt.Errorf("error parsing Transfer User ID: %s", err)
return fmt.Errorf("error parsing Transfer User ID: %w", err)
}

delOpts := &transfer.DeleteUserInput{
Expand All @@ -275,45 +305,15 @@ func resourceAwsTransferUserDelete(d *schema.ResourceData, meta interface{}) err
if isAWSErr(err, transfer.ErrCodeResourceNotFoundException, "") {
return nil
}
return fmt.Errorf("error deleting Transfer User (%s) for Server(%s): %s", userName, serverID, err)
return fmt.Errorf("error deleting Transfer User (%s) for Server(%s): %w", userName, serverID, err)
}

if err := waitForTransferUserDeletion(conn, serverID, userName); err != nil {
return fmt.Errorf("error waiting for Transfer User (%s) for Server (%s): %s", userName, serverID, err)
}

return nil
}
_, err = waiter.UserDeleted(conn, serverID, userName)

func waitForTransferUserDeletion(conn *transfer.Transfer, serverID, userName string) error {
params := &transfer.DescribeUserInput{
ServerId: aws.String(serverID),
UserName: aws.String(userName),
}

err := resource.Retry(10*time.Minute, func() *resource.RetryError {
_, err := conn.DescribeUser(params)

if isAWSErr(err, transfer.ErrCodeResourceNotFoundException, "") {
return nil
}

if err != nil {
return resource.NonRetryableError(err)
}

return resource.RetryableError(fmt.Errorf("Transfer User (%s) for Server (%s) still exists", userName, serverID))
})

if isResourceTimeoutError(err) {
_, err = conn.DescribeUser(params)
}
if isAWSErr(err, transfer.ErrCodeResourceNotFoundException, "") {
return nil
}
if err != nil {
return fmt.Errorf("Error decoding transfer user ID: %s", err)
return fmt.Errorf("error waiting for Transfer User (%s) delete: %w", d.Id(), err)
}

return nil
}

Expand Down Expand Up @@ -344,3 +344,36 @@ func flattenAwsTransferHomeDirectoryMappings(mappings []*transfer.HomeDirectoryM
}
return l
}

func expandTransferUserPosixUser(pUser []interface{}) *transfer.PosixProfile {
if len(pUser) < 1 || pUser[0] == nil {
return nil
}

m := pUser[0].(map[string]interface{})

posixUser := &transfer.PosixProfile{
Gid: aws.Int64(int64(m["gid"].(int))),
Uid: aws.Int64(int64(m["uid"].(int))),
}

if v, ok := m["secondary_gids"].(*schema.Set); ok && len(v.List()) > 0 {
posixUser.SecondaryGids = expandInt64Set(v)
}

return posixUser
}

func flattenTransferUserPosixUser(posixUser *transfer.PosixProfile) []interface{} {
if posixUser == nil {
return []interface{}{}
}

m := map[string]interface{}{
"gid": aws.Int64Value(posixUser.Gid),
"uid": aws.Int64Value(posixUser.Uid),
"secondary_gids": aws.Int64ValueSlice(posixUser.SecondaryGids),
}

return []interface{}{m}
}
Loading

0 comments on commit debac80

Please sign in to comment.