diff --git a/aws/resource_aws_transfer_server.go b/aws/resource_aws_transfer_server.go index d07873a7c54..8048a92af62 100644 --- a/aws/resource_aws_transfer_server.go +++ b/aws/resource_aws_transfer_server.go @@ -3,10 +3,10 @@ package aws import ( "fmt" "log" - "regexp" "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" "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" @@ -41,6 +41,7 @@ func resourceAwsTransferServer() *schema.Resource { Default: transfer.EndpointTypePublic, ValidateFunc: validation.StringInSlice([]string{ transfer.EndpointTypePublic, + transfer.EndpointTypeVpc, transfer.EndpointTypeVpcEndpoint, }, false), }, @@ -52,18 +53,30 @@ func resourceAwsTransferServer() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "vpc_endpoint_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - validNamePattern := "^vpce-[0-9a-f]{17}$" - validName, nameMatchErr := regexp.MatchString(validNamePattern, value) - if !validName || nameMatchErr != nil { - errors = append(errors, fmt.Errorf( - "%q must match regex '%v'", k, validNamePattern)) - } - return - }, + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"endpoint_details.0.address_allocation_ids", "endpoint_details.0.subnet_ids", "endpoint_details.0.vpc_id"}, + Computed: true, + }, + "address_allocation_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + ConflictsWith: []string{"endpoint_details.0.vpc_endpoint_id"}, + }, + "subnet_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + ConflictsWith: []string{"endpoint_details.0.vpc_endpoint_id"}, + }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.NoZeroValues, + ConflictsWith: []string{"endpoint_details.0.vpc_endpoint_id"}, }, }, }, @@ -121,6 +134,7 @@ func resourceAwsTransferServer() *schema.Resource { } func resourceAwsTransferServerCreate(d *schema.ResourceData, meta interface{}) error { + updateAfterCreate := false conn := meta.(*AWSClient).transferconn tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().TransferTags() createOpts := &transfer.CreateServerInput{} @@ -156,6 +170,11 @@ func resourceAwsTransferServerCreate(d *schema.ResourceData, meta interface{}) e if attr, ok := d.GetOk("endpoint_details"); ok { createOpts.EndpointDetails = expandTransferServerEndpointDetails(attr.([]interface{})) + + if createOpts.EndpointDetails.AddressAllocationIds != nil { + createOpts.EndpointDetails.AddressAllocationIds = nil + updateAfterCreate = true + } } if attr, ok := d.GetOk("host_key"); ok { @@ -171,6 +190,17 @@ func resourceAwsTransferServerCreate(d *schema.ResourceData, meta interface{}) e d.SetId(*resp.ServerId) + if updateAfterCreate { + updateOpts := &transfer.UpdateServerInput{ + ServerId: aws.String(d.Id()), + EndpointDetails: expandTransferServerEndpointDetails(d.Get("endpoint_details").([]interface{})), + } + + if err := doTransferServerUpdate(d, updateOpts, conn, meta.(*AWSClient).ec2conn, true); err != nil { + return err + } + } + return resourceAwsTransferServerRead(d, meta) } @@ -219,6 +249,7 @@ func resourceAwsTransferServerRead(d *schema.ResourceData, meta interface{}) err func resourceAwsTransferServerUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).transferconn updateFlag := false + stopFlag := false updateOpts := &transfer.UpdateServerInput{ ServerId: aws.String(d.Id()), } @@ -253,6 +284,10 @@ func resourceAwsTransferServerUpdate(d *schema.ResourceData, meta interface{}) e if attr, ok := d.GetOk("endpoint_details"); ok { updateOpts.EndpointDetails = expandTransferServerEndpointDetails(attr.([]interface{})) } + + if d.HasChange("endpoint_details.0.address_allocation_ids") { + stopFlag = true + } } if d.HasChange("host_key") { @@ -263,14 +298,8 @@ func resourceAwsTransferServerUpdate(d *schema.ResourceData, meta interface{}) e } if updateFlag { - _, err := conn.UpdateServer(updateOpts) - if err != nil { - if isAWSErr(err, transfer.ErrCodeResourceNotFoundException, "") { - log.Printf("[WARN] Transfer Server (%s) not found, removing from state", d.Id()) - d.SetId("") - return nil - } - return fmt.Errorf("error updating Transfer Server (%s): %s", d.Id(), err) + if err := doTransferServerUpdate(d, updateOpts, conn, meta.(*AWSClient).ec2conn, stopFlag); err != nil { + return err } } @@ -392,9 +421,25 @@ func expandTransferServerEndpointDetails(l []interface{}) *transfer.EndpointDeta } e := l[0].(map[string]interface{}) - return &transfer.EndpointDetails{ - VpcEndpointId: aws.String(e["vpc_endpoint_id"].(string)), + out := &transfer.EndpointDetails{} + + if v, ok := e["vpc_endpoint_id"]; ok && v != "" { + out.VpcEndpointId = aws.String(v.(string)) + } + + if v, ok := e["address_allocation_ids"]; ok { + out.AddressAllocationIds = expandStringSet(v.(*schema.Set)) + } + + if v, ok := e["subnet_ids"]; ok { + out.SubnetIds = expandStringSet(v.(*schema.Set)) + } + + if v, ok := e["vpc_id"]; ok { + out.VpcId = aws.String(v.(string)) } + + return out } func flattenTransferServerEndpointDetails(endpointDetails *transfer.EndpointDetails) []interface{} { @@ -402,9 +447,132 @@ func flattenTransferServerEndpointDetails(endpointDetails *transfer.EndpointDeta return []interface{}{} } - e := map[string]interface{}{ - "vpc_endpoint_id": aws.StringValue(endpointDetails.VpcEndpointId), + e := make(map[string]interface{}) + if endpointDetails.VpcEndpointId != nil { + e["vpc_endpoint_id"] = aws.StringValue(endpointDetails.VpcEndpointId) + } + if endpointDetails.AddressAllocationIds != nil { + e["address_allocation_ids"] = flattenStringSet(endpointDetails.AddressAllocationIds) + } + if endpointDetails.SubnetIds != nil { + e["subnet_ids"] = flattenStringSet(endpointDetails.SubnetIds) + } + if endpointDetails.VpcId != nil { + e["vpc_id"] = aws.StringValue(endpointDetails.VpcId) } return []interface{}{e} } + +func doTransferServerUpdate(d *schema.ResourceData, updateOpts *transfer.UpdateServerInput, transferConn *transfer.Transfer, ec2Conn *ec2.EC2, stopFlag bool) error { + if stopFlag { + if err := waitForTransferServerVPCEndpointState(transferConn, ec2Conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { + return fmt.Errorf("error waiting for Transfer Server VPC Endpoint (%s) to start: %s", d.Id(), err) + } + + if err := stopAndWaitForTransferServer(d.Id(), transferConn, d.Timeout(schema.TimeoutCreate)); err != nil { + return err + } + } + + _, err := transferConn.UpdateServer(updateOpts) + if err != nil { + if isAWSErr(err, transfer.ErrCodeResourceNotFoundException, "") { + log.Printf("[WARN] Transfer Server (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("error updating Transfer Server (%s): %s", d.Id(), err) + } + + if stopFlag { + if err := startAndWaitForTransferServer(d.Id(), transferConn, d.Timeout(schema.TimeoutCreate)); err != nil { + return err + } + } + + return nil +} + +func stopAndWaitForTransferServer(serverId string, conn *transfer.Transfer, timeout time.Duration) error { + stopReq := &transfer.StopServerInput{ + ServerId: aws.String(serverId), + } + if _, err := conn.StopServer(stopReq); err != nil { + return fmt.Errorf("error stopping Transfer Server (%s): %s", serverId, err) + } + + stateChangeConf := &resource.StateChangeConf{ + Pending: []string{transfer.StateStarting, transfer.StateOnline, transfer.StateStopping}, + Target: []string{transfer.StateOffline}, + Refresh: refreshTransferServerStatus(conn, serverId), + Timeout: timeout, + Delay: 10 * time.Second, + } + + if _, err := stateChangeConf.WaitForState(); err != nil { + return fmt.Errorf("error waiting for Transfer Server (%s) to stop: %s", serverId, err) + } + + return nil +} + +func startAndWaitForTransferServer(serverId string, conn *transfer.Transfer, timeout time.Duration) error { + stopReq := &transfer.StartServerInput{ + ServerId: aws.String(serverId), + } + + if _, err := conn.StartServer(stopReq); err != nil { + return fmt.Errorf("error starting Transfer Server (%s): %s", serverId, err) + } + + stateChangeConf := &resource.StateChangeConf{ + Pending: []string{transfer.StateStarting, transfer.StateOffline, transfer.StateStopping}, + Target: []string{transfer.StateOnline}, + Refresh: refreshTransferServerStatus(conn, serverId), + Timeout: timeout, + Delay: 10 * time.Second, + } + + if _, err := stateChangeConf.WaitForState(); err != nil { + return fmt.Errorf("error waiting for Transfer Server (%s) to start: %s", serverId, err) + } + + return nil +} + +func refreshTransferServerStatus(conn *transfer.Transfer, serverId string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + server, err := describeTransferServer(conn, serverId) + + if server == nil { + return 42, "destroyed", nil + } + + return server, aws.StringValue(server.State), err + } +} + +func describeTransferServer(conn *transfer.Transfer, serverId string) (*transfer.DescribedServer, error) { + params := &transfer.DescribeServerInput{ + ServerId: aws.String(serverId), + } + + resp, err := conn.DescribeServer(params) + + return resp.Server, err +} + +func waitForTransferServerVPCEndpointState(transferConn *transfer.Transfer, ec2Conn *ec2.EC2, serverId string, timeout time.Duration) error { + server, err := describeTransferServer(transferConn, serverId) + + if err != nil { + return err + } + + if err := vpcEndpointWaitUntilAvailable(ec2Conn, *server.EndpointDetails.VpcEndpointId, timeout); err != nil { + return err + } + + return nil +} diff --git a/aws/resource_aws_transfer_server_test.go b/aws/resource_aws_transfer_server_test.go index c9e848eb349..d8d011a8bfa 100644 --- a/aws/resource_aws_transfer_server_test.go +++ b/aws/resource_aws_transfer_server_test.go @@ -67,28 +67,29 @@ func testSweepTransferServers(region string) error { func TestAccAWSTransferServer_basic(t *testing.T) { var conf transfer.DescribedServer + resourceName := "aws_transfer_server.foo" rName := acctest.RandString(5) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSTransfer(t) }, - IDRefreshName: "aws_transfer_server.foo", + IDRefreshName: resourceName, Providers: testAccProviders, CheckDestroy: testAccCheckAWSTransferServerDestroy, Steps: []resource.TestStep{ { Config: testAccAWSTransferServerConfig_basic, Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferServerExists("aws_transfer_server.foo", &conf), - testAccMatchResourceAttrRegionalARN("aws_transfer_server.foo", "arn", "transfer", regexp.MustCompile(`server/.+`)), + testAccCheckAWSTransferServerExists(resourceName, &conf), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "transfer", regexp.MustCompile(`server/.+`)), resource.TestMatchResourceAttr( - "aws_transfer_server.foo", "endpoint", regexp.MustCompile(fmt.Sprintf("^s-[a-z0-9]+.server.transfer.%s.amazonaws.com$", testAccGetRegion()))), + resourceName, "endpoint", regexp.MustCompile(fmt.Sprintf("^s-[a-z0-9]+.server.transfer.%s.amazonaws.com$", testAccGetRegion()))), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "identity_provider_type", "SERVICE_MANAGED"), - resource.TestCheckResourceAttr("aws_transfer_server.foo", "tags.%", "0"), + resourceName, "identity_provider_type", "SERVICE_MANAGED"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), ), }, { - ResourceName: "aws_transfer_server.foo", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"force_destroy"}, @@ -96,15 +97,57 @@ func TestAccAWSTransferServer_basic(t *testing.T) { { Config: testAccAWSTransferServerConfig_basicUpdate(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferServerExists("aws_transfer_server.foo", &conf), + testAccCheckAWSTransferServerExists(resourceName, &conf), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "tags.%", "2"), + resourceName, "tags.%", "2"), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "tags.NAME", "tf-acc-test-transfer-server"), + resourceName, "tags.NAME", "tf-acc-test-transfer-server"), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "tags.ENV", "test"), + resourceName, "tags.ENV", "test"), resource.TestCheckResourceAttrPair( - "aws_transfer_server.foo", "logging_role", "aws_iam_role.foo", "arn"), + resourceName, "logging_role", "aws_iam_role.foo", "arn"), + ), + }, + }, + }) +} + +func TestAccAWSTransferServer_Vpc(t *testing.T) { + var conf transfer.DescribedServer + resourceName := "aws_transfer_server.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSTransfer(t) }, + IDRefreshName: resourceName, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSTransferServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSTransferServerConfig_Vpc, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSTransferServerExists(resourceName, &conf), + resource.TestCheckResourceAttr( + resourceName, "endpoint_type", "VPC"), + resource.TestCheckResourceAttr( + resourceName, "endpoint_details.0.subnet_ids.#", "1"), + resource.TestCheckResourceAttr( + resourceName, "endpoint_details.0.address_allocation_ids.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccAWSTransferServerConfig_VpcUpdate, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSTransferServerExists(resourceName, &conf), + resource.TestCheckResourceAttr( + resourceName, "endpoint_type", "VPC"), + resource.TestCheckResourceAttr( + resourceName, "endpoint_details.0.address_allocation_ids.#", "1"), ), }, }, @@ -113,28 +156,29 @@ func TestAccAWSTransferServer_basic(t *testing.T) { func TestAccAWSTransferServer_apigateway(t *testing.T) { var conf transfer.DescribedServer + resourceName := "aws_transfer_server.foo" rName := acctest.RandString(5) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSTransfer(t) }, - IDRefreshName: "aws_transfer_server.foo", + IDRefreshName: resourceName, Providers: testAccProviders, CheckDestroy: testAccCheckAWSTransferServerDestroy, Steps: []resource.TestStep{ { Config: testAccAWSTransferServerConfig_apigateway(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferServerExists("aws_transfer_server.foo", &conf), + testAccCheckAWSTransferServerExists(resourceName, &conf), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "identity_provider_type", "API_GATEWAY"), + resourceName, "identity_provider_type", "API_GATEWAY"), resource.TestCheckResourceAttrSet( - "aws_transfer_server.foo", "invocation_role"), + resourceName, "invocation_role"), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "tags.%", "2"), + resourceName, "tags.%", "2"), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "tags.NAME", "tf-acc-test-transfer-server"), + resourceName, "tags.NAME", "tf-acc-test-transfer-server"), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "tags.TYPE", "apigateway"), + resourceName, "tags.TYPE", "apigateway"), ), }, }, @@ -164,29 +208,30 @@ func TestAccAWSTransferServer_disappears(t *testing.T) { func TestAccAWSTransferServer_forcedestroy(t *testing.T) { var conf transfer.DescribedServer var roleConf iam.GetRoleOutput + resourceName := "aws_transfer_server.foo" rName := acctest.RandString(5) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSTransfer(t) }, - IDRefreshName: "aws_transfer_server.foo", + IDRefreshName: resourceName, Providers: testAccProviders, CheckDestroy: testAccCheckAWSTransferServerDestroy, Steps: []resource.TestStep{ { Config: testAccAWSTransferServerConfig_forcedestroy(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferServerExists("aws_transfer_server.foo", &conf), + testAccCheckAWSTransferServerExists(resourceName, &conf), testAccCheckAWSRoleExists("aws_iam_role.foo", &roleConf), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "identity_provider_type", "SERVICE_MANAGED"), + resourceName, "identity_provider_type", "SERVICE_MANAGED"), resource.TestCheckResourceAttr( - "aws_transfer_server.foo", "force_destroy", "true"), + resourceName, "force_destroy", "true"), testAccCheckAWSTransferCreateUser(&conf, &roleConf, rName), testAccCheckAWSTransferCreateSshKey(&conf, rName), ), }, { - ResourceName: "aws_transfer_server.foo", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"force_destroy", "host_key"}, @@ -653,6 +698,88 @@ resource "aws_transfer_server" "default" { } ` +const testAccAWSTransferServerConfig_VpcDefault = ` +data "aws_region" "current" {} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = "terraform-testacc-vpc" + } +} + +resource "aws_internet_gateway" "test" { + vpc_id = "${aws_vpc.test.id}" + + tags = { + Name = "terraform-testacc-igw" + } +} + +resource "aws_subnet" "test" { + vpc_id = "${aws_vpc.test.id}" + cidr_block = "10.0.0.0/24" + map_public_ip_on_launch = true + + depends_on = ["aws_internet_gateway.test"] +} + +resource "aws_default_route_table" "test" { + default_route_table_id = "${aws_vpc.test.default_route_table_id}" + + route { + cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.test.id}" + } + + tags = { + Name = "terraform-testacc-subnet" + } +} + +resource "aws_security_group" "test" { + name = "terraform-testacc-security-group" + vpc_id = data.aws_vpc.test.id + + tags = { + Name = "terraform-testacc-security-group" + } +} + +resource "aws_eip" "testa" { + vpc = true +} + +resource "aws_eip" "testb" { + vpc = true +} +` + +const testAccAWSTransferServerConfig_Vpc = testAccAWSTransferServerConfig_VpcDefault + ` + +resource "aws_transfer_server" "test" { + endpoint_type = "VPC" + endpoint_details { + vpc_id = "${aws_vpc.test.id}" + address_allocation_ids = ["${aws_eip.testa.id}"] + subnet_ids = ["${aws_subnet.test.id}"] + } +} +` + +const testAccAWSTransferServerConfig_VpcUpdate = testAccAWSTransferServerConfig_VpcDefault + ` + +resource "aws_transfer_server" "test" { + endpoint_type = "VPC" + endpoint_details { + vpc_id = "${aws_vpc.test.id}" + address_allocation_ids = ["${aws_eip.testb.id}"] + subnet_ids = ["${aws_subnet.test.id}"] + } +} +` + func testAccAWSTransferServerConfig_hostKey(hostKey string) string { return fmt.Sprintf(` resource "aws_transfer_server" "default" { diff --git a/aws/resource_aws_transfer_user_test.go b/aws/resource_aws_transfer_user_test.go index f8e8895f036..33b099dc9ff 100644 --- a/aws/resource_aws_transfer_user_test.go +++ b/aws/resource_aws_transfer_user_test.go @@ -15,27 +15,61 @@ import ( func TestAccAWSTransferUser_basic(t *testing.T) { var conf transfer.DescribedUser + resourceName := "aws_transfer_user.foo" rName := acctest.RandString(10) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSTransfer(t) }, - IDRefreshName: "aws_transfer_user.foo", + IDRefreshName: resourceName, Providers: testAccProviders, CheckDestroy: testAccCheckAWSTransferUserDestroy, Steps: []resource.TestStep{ { Config: testAccAWSTransferUserConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferUserExists("aws_transfer_user.foo", &conf), - testAccMatchResourceAttrRegionalARN("aws_transfer_user.foo", "arn", "transfer", regexp.MustCompile(`user/.+`)), + testAccCheckAWSTransferUserExists(resourceName, &conf), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "transfer", regexp.MustCompile(`user/.+`)), + resource.TestCheckResourceAttrPair( + resourceName, "server_id", "aws_transfer_server.foo", "id"), + resource.TestCheckResourceAttrPair( + resourceName, "role", "aws_iam_role.foo", "arn"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSTransferUser_restricted(t *testing.T) { + var conf transfer.DescribedUser + resourceName := "aws_transfer_user.foo" + rName := acctest.RandString(10) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSTransfer(t) }, + IDRefreshName: resourceName, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSTransferUserDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSTransferUserConfig_restricted(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSTransferUserExists(resourceName, &conf), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "transfer", regexp.MustCompile(`user/.+`)), resource.TestCheckResourceAttrPair( - "aws_transfer_user.foo", "server_id", "aws_transfer_server.foo", "id"), + resourceName, "server_id", "aws_transfer_server.foo", "id"), resource.TestCheckResourceAttrPair( - "aws_transfer_user.foo", "role", "aws_iam_role.foo", "arn"), + resourceName, "role", "aws_iam_role.foo", "arn"), + resource.TestCheckResourceAttr( + resourceName, "home_directory_type", "LOGICAL"), ), }, { - ResourceName: "aws_transfer_user.foo", + ResourceName: resourceName, ImportState: true, ImportStateVerify: true, }, @@ -45,57 +79,58 @@ func TestAccAWSTransferUser_basic(t *testing.T) { func TestAccAWSTransferUser_modifyWithOptions(t *testing.T) { var conf transfer.DescribedUser + resourceName := "aws_transfer_user.foo" rName := acctest.RandString(10) rName2 := acctest.RandString(10) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSTransfer(t) }, - IDRefreshName: "aws_transfer_user.foo", + IDRefreshName: resourceName, Providers: testAccProviders, CheckDestroy: testAccCheckAWSTransferUserDestroy, Steps: []resource.TestStep{ { Config: testAccAWSTransferUserConfig_options(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferUserExists("aws_transfer_user.foo", &conf), + testAccCheckAWSTransferUserExists(resourceName, &conf), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "home_directory", "/home/tftestuser"), + resourceName, "home_directory", "/home/tftestuser"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "tags.%", "3"), + resourceName, "tags.%", "3"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "tags.NAME", "tftestuser"), + resourceName, "tags.NAME", "tftestuser"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "tags.ENV", "test"), + resourceName, "tags.ENV", "test"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "tags.ADMIN", "test"), + resourceName, "tags.ADMIN", "test"), ), }, { Config: testAccAWSTransferUserConfig_modify(rName2), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferUserExists("aws_transfer_user.foo", &conf), + testAccCheckAWSTransferUserExists(resourceName, &conf), resource.TestCheckResourceAttrPair( - "aws_transfer_user.foo", "role", "aws_iam_role.foo", "arn"), + resourceName, "role", "aws_iam_role.foo", "arn"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "home_directory", "/test"), + resourceName, "home_directory", "/test"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "tags.%", "2"), + resourceName, "tags.%", "2"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "tags.NAME", "tf-test-user"), + resourceName, "tags.NAME", "tf-test-user"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "tags.TEST", "test2"), + resourceName, "tags.TEST", "test2"), ), }, { Config: testAccAWSTransferUserConfig_forceNew(rName2), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSTransferUserExists("aws_transfer_user.foo", &conf), + testAccCheckAWSTransferUserExists(resourceName, &conf), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "user_name", "tftestuser2"), + resourceName, "user_name", "tftestuser2"), resource.TestCheckResourceAttrPair( - "aws_transfer_user.foo", "role", "aws_iam_role.foo", "arn"), + resourceName, "role", "aws_iam_role.foo", "arn"), resource.TestCheckResourceAttr( - "aws_transfer_user.foo", "home_directory", "/home/tftestuser2"), + resourceName, "home_directory", "/home/tftestuser2"), ), }, }, @@ -327,6 +362,74 @@ resource "aws_transfer_user" "foo" { `, rName, rName) } +func testAccAWSTransferUserConfig_restricted(rName string) string { + return fmt.Sprintf(` +resource "aws_transfer_server" "foo" { + identity_provider_type = "SERVICE_MANAGED" + + tags = { + NAME = "tf-acc-test-transfer-server" + } +} + +resource "aws_iam_role" "foo" { + name = "tf-test-transfer-user-iam-role-%s" + + assume_role_policy = <