diff --git a/.changelog/33641.txt b/.changelog/33641.txt new file mode 100644 index 000000000000..ae2973973ae1 --- /dev/null +++ b/.changelog/33641.txt @@ -0,0 +1,4 @@ + +```release-note:bug +resource/aws_datasync_location_fsx_ontap_file_system: Correct handling of `protocol.smb.domain`, `protocol.smb.user` and `protocol.smb.password` +``` \ No newline at end of file diff --git a/internal/service/datasync/common_fsx_protocol_functions.go b/internal/service/datasync/common_fsx_protocol_functions.go index 3a3a007b2a26..2bb97e5e83a4 100644 --- a/internal/service/datasync/common_fsx_protocol_functions.go +++ b/internal/service/datasync/common_fsx_protocol_functions.go @@ -4,6 +4,7 @@ package datasync import ( + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/datasync" ) @@ -66,6 +67,15 @@ func expandSMB(l []interface{}) *datasync.FsxProtocolSmb { protocol := &datasync.FsxProtocolSmb{ MountOptions: expandSMBMountOptions(m["mount_options"].([]interface{})), } + if v, ok := m["domain"].(string); ok && v != "" { + protocol.Domain = aws.String(v) + } + if v, ok := m["password"].(string); ok && v != "" { + protocol.Password = aws.String(v) + } + if v, ok := m["user"].(string); ok && v != "" { + protocol.User = aws.String(v) + } return protocol } @@ -91,6 +101,15 @@ func flattenSMB(smb *datasync.FsxProtocolSmb) []interface{} { m := map[string]interface{}{ "mount_options": flattenSMBMountOptions(smb.MountOptions), } + if v := smb.Domain; v != nil { + m["domain"] = aws.StringValue(v) + } + if v := smb.Password; v != nil { + m["password"] = aws.StringValue(v) + } + if v := smb.User; v != nil { + m["user"] = aws.StringValue(v) + } return []interface{}{m} } diff --git a/internal/service/datasync/location_fsx_ontap_file_system.go b/internal/service/datasync/location_fsx_ontap_file_system.go index 27ff9ff235fd..20263884cf2f 100644 --- a/internal/service/datasync/location_fsx_ontap_file_system.go +++ b/internal/service/datasync/location_fsx_ontap_file_system.go @@ -244,6 +244,12 @@ func resourceLocationFSxONTAPFileSystemRead(ctx context.Context, d *schema.Resou d.Set("arn", output.LocationArn) d.Set("creation_time", output.CreationTime.Format(time.RFC3339)) d.Set("fsx_filesystem_arn", output.FsxFilesystemArn) + // SMB Password is not returned from the API. + if output.Protocol != nil && output.Protocol.SMB != nil && aws.StringValue(output.Protocol.SMB.Password) == "" { + if smbPassword := d.Get("protocol.0.smb.0.password").(string); smbPassword != "" { + output.Protocol.SMB.Password = aws.String(smbPassword) + } + } if err := d.Set("protocol", flattenProtocol(output.Protocol)); err != nil { return sdkdiag.AppendErrorf(diags, "setting protocol: %s", err) } diff --git a/internal/service/datasync/location_fsx_ontap_file_system_test.go b/internal/service/datasync/location_fsx_ontap_file_system_test.go index 7ea0bad5bf9f..2fb8c704294b 100644 --- a/internal/service/datasync/location_fsx_ontap_file_system_test.go +++ b/internal/service/datasync/location_fsx_ontap_file_system_test.go @@ -40,11 +40,16 @@ func TestAccDataSyncLocationFSxONTAPFileSystem_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccLocationFSxONTAPFileSystemConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLocationFSxONTAPExists(ctx, resourceName, &v), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "datasync", regexache.MustCompile(`location/loc-.+`)), resource.TestCheckResourceAttrSet(resourceName, "creation_time"), resource.TestCheckResourceAttrPair(resourceName, "fsx_filesystem_arn", fsResourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "protocol.#", "1"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.nfs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.nfs.0.mount_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.nfs.0.mount_options.0.version", "NFS3"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.smb.#", "0"), resource.TestCheckResourceAttr(resourceName, "subdirectory", "/"), resource.TestCheckResourceAttrPair(resourceName, "storage_virtual_machine_arn", svmResourceName, "arn"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), @@ -89,6 +94,50 @@ func TestAccDataSyncLocationFSxONTAPFileSystem_disappears(t *testing.T) { }) } +func TestAccDataSyncLocationFSxONTAPFileSystem_smb(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + netBiosName := "tftest-" + sdkacctest.RandString(7) + domainNetbiosName := "tftest" + sdkacctest.RandString(4) + domainName := domainNetbiosName + ".local" + var v datasync.DescribeLocationFsxOntapOutput + resourceName := "aws_datasync_location_fsx_ontap_file_system.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, datasync.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLocationFSxONTAPDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccLocationFSxONTAPFileSystemConfig_smb(rName, netBiosName, domainNetbiosName, domainName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLocationFSxONTAPExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "protocol.#", "1"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.nfs.#", "0"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.smb.#", "1"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.smb.0.domain", domainName), + resource.TestCheckResourceAttr(resourceName, "protocol.0.smb.0.mount_options.#", "1"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.smb.0.mount_options.0.version", "SMB3"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.smb.0.password", "MyPassw0rd1"), + resource.TestCheckResourceAttr(resourceName, "protocol.0.smb.0.user", "Admin"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"protocol.0.smb.0.password"}, // Not returned from API. + ImportStateIdFunc: testAccLocationFSxONTAPImportStateID(resourceName), + }, + }, + }) +} + func TestAccDataSyncLocationFSxONTAPFileSystem_subdirectory(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -231,8 +280,8 @@ func testAccLocationFSxONTAPImportStateID(n string) resource.ImportStateIdFunc { } } -func testAccFSxOntapFileSystemConfig_base(rName string) string { - return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` +func testAccFSxOntapFileSystemConfig_base(rName string, nSubnets int, deploymentType string) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, nSubnets), fmt.Sprintf(` resource "aws_security_group" "test" { name = %[1]q vpc_id = aws_vpc.test.id @@ -259,7 +308,7 @@ resource "aws_security_group" "test" { resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 subnet_ids = aws_subnet.test[*].id - deployment_type = "SINGLE_AZ_1" + deployment_type = %[2]q throughput_capacity = 512 preferred_subnet_id = aws_subnet.test[0].id @@ -267,7 +316,11 @@ resource "aws_fsx_ontap_file_system" "test" { Name = %[1]q } } +`, rName, deploymentType)) +} +func testAccFSxOntapFileSystemConfig_baseNFS(rName string) string { + return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_base(rName, 1, "SINGLE_AZ_1"), fmt.Sprintf(` resource "aws_fsx_ontap_storage_virtual_machine" "test" { file_system_id = aws_fsx_ontap_file_system.test.id name = %[1]q @@ -275,8 +328,24 @@ resource "aws_fsx_ontap_storage_virtual_machine" "test" { `, rName)) } +func testAccFSxOntapFileSystemConfig_baseSMB(rName, domainName string) string { + return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_base(rName, 2, "MULTI_AZ_1"), fmt.Sprintf(` +resource "aws_directory_service_directory" "test" { + edition = "Standard" + name = %[1]q + password = "MyPassw0rd1" + type = "MicrosoftAD" + + vpc_settings { + subnet_ids = aws_subnet.test[*].id + vpc_id = aws_vpc.test.id + } +} +`, domainName)) +} + func testAccLocationFSxONTAPFileSystemConfig_basic(rName string) string { - return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_base(rName), ` + return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_baseNFS(rName), ` resource "aws_datasync_location_fsx_ontap_file_system" "test" { security_group_arns = [aws_security_group.test.arn] storage_virtual_machine_arn = aws_fsx_ontap_storage_virtual_machine.test.arn @@ -292,8 +361,48 @@ resource "aws_datasync_location_fsx_ontap_file_system" "test" { `) } +func testAccLocationFSxONTAPFileSystemConfig_smb(rName, netBiosName, domainNetbiosName, domainName string) string { + return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_baseSMB(rName, domainName), fmt.Sprintf(` +resource "aws_fsx_ontap_storage_virtual_machine" "test" { + file_system_id = aws_fsx_ontap_file_system.test.id + name = %[1]q + depends_on = [aws_directory_service_directory.test] + + active_directory_configuration { + netbios_name = %[2]q + self_managed_active_directory_configuration { + dns_ips = aws_directory_service_directory.test.dns_ip_addresses + domain_name = %[3]q + password = "MyPassw0rd1" + username = "Admin" + organizational_unit_distinguished_name = "OU=computers,OU=%[4]s" + file_system_administrators_group = "Admins" + } + } +} + +resource "aws_datasync_location_fsx_ontap_file_system" "test" { + security_group_arns = [aws_security_group.test.arn] + storage_virtual_machine_arn = aws_fsx_ontap_storage_virtual_machine.test.arn + + protocol { + smb { + domain = %[3]q + + mount_options { + version = "SMB3" + } + + password = "MyPassw0rd1" + user = "Admin" + } + } +} +`, rName, netBiosName, domainName, domainNetbiosName)) +} + func testAccLocationFSxONTAPFileSystemConfig_subdirectory(rName, subdirectory string) string { - return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_base(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_baseNFS(rName), fmt.Sprintf(` resource "aws_datasync_location_fsx_ontap_file_system" "test" { security_group_arns = [aws_security_group.test.arn] storage_virtual_machine_arn = aws_fsx_ontap_storage_virtual_machine.test.arn @@ -311,7 +420,7 @@ resource "aws_datasync_location_fsx_ontap_file_system" "test" { } func testAccLocationFSxONTAPFileSystemConfig_tags1(rName, key1, value1 string) string { - return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_base(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_baseNFS(rName), fmt.Sprintf(` resource "aws_datasync_location_fsx_ontap_file_system" "test" { security_group_arns = [aws_security_group.test.arn] storage_virtual_machine_arn = aws_fsx_ontap_storage_virtual_machine.test.arn @@ -332,7 +441,7 @@ resource "aws_datasync_location_fsx_ontap_file_system" "test" { } func testAccLocationFSxONTAPFileSystemConfig_tags2(rName, key1, value1, key2, value2 string) string { - return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_base(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccFSxOntapFileSystemConfig_baseNFS(rName), fmt.Sprintf(` resource "aws_datasync_location_fsx_ontap_file_system" "test" { security_group_arns = [aws_security_group.test.arn] storage_virtual_machine_arn = aws_fsx_ontap_storage_virtual_machine.test.arn