Skip to content

Commit

Permalink
Merge pull request #6850 from kterada0509/feature/add-support-for-sft…
Browse files Browse the repository at this point in the history
…p-user

Add Transfer User Resource Support
  • Loading branch information
bflad authored Dec 19, 2018
2 parents af59dd2 + dc57355 commit b6a6494
Show file tree
Hide file tree
Showing 9 changed files with 977 additions and 20 deletions.
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ func Provider() terraform.ResourceProvider {
"aws_subnet": resourceAwsSubnet(),
"aws_swf_domain": resourceAwsSwfDomain(),
"aws_transfer_server": resourceAwsTransferServer(),
"aws_transfer_user": resourceAwsTransferUser(),
"aws_volume_attachment": resourceAwsVolumeAttachment(),
"aws_vpc_dhcp_options_association": resourceAwsVpcDhcpOptionsAssociation(),
"aws_default_vpc_dhcp_options": resourceAwsDefaultVpcDhcpOptions(),
Expand Down
6 changes: 3 additions & 3 deletions aws/resource_aws_transfer_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func resourceAwsTransferServer() *schema.Resource {

func resourceAwsTransferServerCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).transferconn
tags := tagsFromMapTransferServer(d.Get("tags").(map[string]interface{}))
tags := tagsFromMapTransfer(d.Get("tags").(map[string]interface{}))
createOpts := &transfer.CreateServerInput{}

if len(tags) != 0 {
Expand Down Expand Up @@ -141,7 +141,7 @@ func resourceAwsTransferServerRead(d *schema.ResourceData, meta interface{}) err
d.Set("identity_provider_type", resp.Server.IdentityProviderType)
d.Set("logging_role", resp.Server.LoggingRole)

if err := d.Set("tags", tagsToMapTransferServer(resp.Server.Tags)); err != nil {
if err := d.Set("tags", tagsToMapTransfer(resp.Server.Tags)); err != nil {
return fmt.Errorf("Error setting tags: %s", err)
}
return nil
Expand Down Expand Up @@ -184,7 +184,7 @@ func resourceAwsTransferServerUpdate(d *schema.ResourceData, meta interface{}) e
}
}

if err := setTagsTransferServer(conn, d); err != nil {
if err := setTagsTransfer(conn, d); err != nil {
return fmt.Errorf("Error update tags: %s", err)
}

Expand Down
247 changes: 247 additions & 0 deletions aws/resource_aws_transfer_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package aws

import (
"fmt"
"log"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/transfer"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)

func resourceAwsTransferUser() *schema.Resource {

return &schema.Resource{
Create: resourceAwsTransferUserCreate,
Read: resourceAwsTransferUserRead,
Update: resourceAwsTransferUserUpdate,
Delete: resourceAwsTransferUserDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{

"arn": {
Type: schema.TypeString,
Computed: true,
},

"home_directory": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(0, 1024),
},

"policy": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateIAMPolicyJson,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},

"role": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateArn,
},

"server_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateTransferServerID,
},

"tags": tagsSchema(),

"user_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateTransferUserName,
},
},
}
}

func resourceAwsTransferUserCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).transferconn
userName := d.Get("user_name").(string)
serverID := d.Get("server_id").(string)

createOpts := &transfer.CreateUserInput{
ServerId: aws.String(serverID),
UserName: aws.String(userName),
Role: aws.String(d.Get("role").(string)),
}

if attr, ok := d.GetOk("home_directory"); ok {
createOpts.HomeDirectory = aws.String(attr.(string))
}

if attr, ok := d.GetOk("policy"); ok {
createOpts.Policy = aws.String(attr.(string))
}

if attr, ok := d.GetOk("tags"); ok {
createOpts.Tags = tagsFromMapTransfer(attr.(map[string]interface{}))
}

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

_, err := conn.CreateUser(createOpts)
if err != nil {
return fmt.Errorf("error creating Transfer User: %s", err)
}

d.SetId(fmt.Sprintf("%s/%s", serverID, userName))

return resourceAwsTransferUserRead(d, meta)
}

func resourceAwsTransferUserRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).transferconn
serverID, userName, err := decodeTransferUserId(d.Id())
if err != nil {
return fmt.Errorf("error parsing Transfer User ID: %s", err)
}

descOpts := &transfer.DescribeUserInput{
UserName: aws.String(userName),
ServerId: aws.String(serverID),
}

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)
}

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("policy", resp.User.Policy)
d.Set("role", resp.User.Role)

if err := d.Set("tags", tagsToMapTransfer(resp.User.Tags)); err != nil {
return fmt.Errorf("Error setting tags: %s", err)
}
return nil
}

func resourceAwsTransferUserUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).transferconn
updateFlag := false
serverID, userName, err := decodeTransferUserId(d.Id())
if err != nil {
return fmt.Errorf("error parsing Transfer User ID: %s", err)
}

updateOpts := &transfer.UpdateUserInput{
UserName: aws.String(userName),
ServerId: aws.String(serverID),
}

if d.HasChange("home_directory") {
updateOpts.HomeDirectory = aws.String(d.Get("home_directory").(string))
updateFlag = true
}

if d.HasChange("policy") {
updateOpts.Policy = aws.String(d.Get("policy").(string))
updateFlag = true
}

if d.HasChange("role") {
updateOpts.Role = aws.String(d.Get("role").(string))
updateFlag = true
}

if updateFlag {
_, err := conn.UpdateUser(updateOpts)
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 updating Transfer User (%s): %s", d.Id(), err)
}
}

if err := setTagsTransfer(conn, d); err != nil {
return fmt.Errorf("Error update tags: %s", err)
}

return resourceAwsTransferUserRead(d, meta)
}

func resourceAwsTransferUserDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).transferconn
serverID, userName, err := decodeTransferUserId(d.Id())
if err != nil {
return fmt.Errorf("error parsing Transfer User ID: %s", err)
}

delOpts := &transfer.DeleteUserInput{
UserName: aws.String(userName),
ServerId: aws.String(serverID),
}

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

_, err = conn.DeleteUser(delOpts)
if err != nil {
if isAWSErr(err, transfer.ErrCodeResourceNotFoundException, "") {
return nil
}
return fmt.Errorf("error deleting Transfer User (%s) for Server(%s): %s", 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
}

func decodeTransferUserId(id string) (string, string, error) {
idParts := strings.SplitN(id, "/", 2)
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
return "", "", fmt.Errorf("unexpected format of ID (%s), expected SERVERID/USERNAME", id)
}
return idParts[0], idParts[1], nil
}

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

return 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))
})
}
Loading

0 comments on commit b6a6494

Please sign in to comment.