diff --git a/.changelog/33466.txt b/.changelog/33466.txt new file mode 100644 index 000000000000..af3005b7582e --- /dev/null +++ b/.changelog/33466.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_fsx_ontap_storage_virtual_machine: Remove [ForceNew](https://developer.hashicorp.com/terraform/plugin/sdkv2/schemas/schema-behaviors#forcenew) from `active_directory_configuration.self_managed_active_directory_configuration.domain_name`, `active_directory_configuration.self_managed_active_directory_configuration.file_system_administrators_group` and `active_directory_configuration.self_managed_active_directory_configuration.organizational_unit_distinguished_name` allowing an SVM to join AD after creation +``` + +```release-note:bug +resource/aws_fsx_ontap_storage_virtual_machine: Avoid recreating resource when `active_directory_configuration.self_managed_active_directory_configuration.file_system_administrators_group` is configured +``` \ No newline at end of file diff --git a/internal/service/athena/sweep.go b/internal/service/athena/sweep.go index b47c9e4d3351..c31e70e746d9 100644 --- a/internal/service/athena/sweep.go +++ b/internal/service/athena/sweep.go @@ -12,7 +12,6 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/athena" - "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" ) @@ -34,13 +33,14 @@ func sweepDatabases(region string) error { input := &athena.ListDatabasesInput{ CatalogName: aws.String("AwsDataCatalog"), } - var errs *multierror.Error - sweepResources := make([]sweep.Sweepable, 0) - for { - output, err := conn.ListDatabasesWithContext(ctx, input) - for _, v := range output.DatabaseList { + err = conn.ListDatabasesPagesWithContext(ctx, input, func(page *athena.ListDatabasesOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.DatabaseList { name := aws.StringValue(v.Name) if name == "default" { continue @@ -48,34 +48,28 @@ func sweepDatabases(region string) error { r := ResourceDatabase() d := r.Data(nil) d.SetId(name) - - if err != nil { - err := fmt.Errorf("error listing Athena Databases (%s): %w", name, err) - log.Printf("[ERROR] %s", err) - errs = multierror.Append(errs, err) - continue - } + d.Set("force_destroy", true) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - if aws.StringValue(output.NextToken) == "" { - break - } - - input.NextToken = output.NextToken - } + return !lastPage + }) if sweep.SkipSweepError(err) { log.Printf("[WARN] Skipping Athena Database sweep for %s: %s", region, err) return nil } + if err != nil { + return fmt.Errorf("error listing Athena Databases (%s): %w", region, err) + } + err = sweep.SweepOrchestrator(ctx, sweepResources) if err != nil { - errs = multierror.Append(errs, fmt.Errorf("error sweeping Athena Databases (%s): %w", region, err)) + return fmt.Errorf("error sweeping Athena Databases (%s): %w", region, err) } - return errs.ErrorOrNil() + return nil } diff --git a/internal/service/cloudformation/sweep.go b/internal/service/cloudformation/sweep.go index ea1f8e707cc5..43bc206a3cd0 100644 --- a/internal/service/cloudformation/sweep.go +++ b/internal/service/cloudformation/sweep.go @@ -77,6 +77,7 @@ func sweepStackSetInstances(region string) error { aws.StringValue(summary.Region), ) d.SetId(id) + d.Set("call_as", "SELF") sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } @@ -135,6 +136,7 @@ func sweepStackSets(region string) error { r := ResourceStackSet() d := r.Data(nil) d.SetId(aws.StringValue(summary.StackSetName)) + d.Set("call_as", "SELF") sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } diff --git a/internal/service/codestarconnections/sweep.go b/internal/service/codestarconnections/sweep.go index bab6c6a2e9f6..92e31cf97651 100644 --- a/internal/service/codestarconnections/sweep.go +++ b/internal/service/codestarconnections/sweep.go @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/codestarconnections" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" ) func init() { @@ -45,7 +46,7 @@ func sweepConnections(region string) error { for pages.HasMorePages() { page, err := pages.NextPage(ctx) - if sweep.SkipSweepError(err) { + if awsv2.SkipSweepError(err) { log.Printf("[WARN] Skipping CodeStar Connections Connection sweep for %s: %s", region, err) return nil } @@ -86,7 +87,7 @@ func sweepHosts(region string) error { for pages.HasMorePages() { page, err := pages.NextPage(ctx) - if sweep.SkipSweepError(err) { + if awsv2.SkipSweepError(err) { log.Printf("[WARN] Skipping CodeStar Connections Host sweep for %s: %s", region, err) return nil } diff --git a/internal/service/cur/sweep.go b/internal/service/cur/sweep.go index 07655842ed6d..7a3a0953d276 100644 --- a/internal/service/cur/sweep.go +++ b/internal/service/cur/sweep.go @@ -14,6 +14,7 @@ import ( cur "github.com/aws/aws-sdk-go/service/costandusagereportservice" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" + "github.com/hashicorp/terraform-provider-aws/names" ) func init() { @@ -25,6 +26,10 @@ func init() { func sweepReportDefinitions(region string) error { ctx := sweep.Context(region) + if region != names.USEast1RegionID { + log.Printf("[WARN] Skipping Cost And Usage Report Definition sweep for region: %s", region) + return nil + } client, err := sweep.SharedRegionalSweepClient(ctx, region) if err != nil { return fmt.Errorf("error getting client: %s", err) @@ -50,7 +55,7 @@ func sweepReportDefinitions(region string) error { }) if sweep.SkipSweepError(err) { - log.Printf("[WARN] Skipping EC2 Cost And Usage Report Definition sweep for %s: %s", region, err) + log.Printf("[WARN] Skipping Cost And Usage Report Definition sweep for %s: %s", region, err) return nil } if err != nil { diff --git a/internal/service/fsx/find.go b/internal/service/fsx/find.go index 236c50adcdb9..c24a32bda5de 100644 --- a/internal/service/fsx/find.go +++ b/internal/service/fsx/find.go @@ -71,45 +71,6 @@ func findFileCacheByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.File return fileCaches[0], nil } -func FindStorageVirtualMachineByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.StorageVirtualMachine, error) { - input := &fsx.DescribeStorageVirtualMachinesInput{ - StorageVirtualMachineIds: []*string{aws.String(id)}, - } - - var storageVirtualMachines []*fsx.StorageVirtualMachine - - err := conn.DescribeStorageVirtualMachinesPagesWithContext(ctx, input, func(page *fsx.DescribeStorageVirtualMachinesOutput, lastPage bool) bool { - if page == nil { - return !lastPage - } - - storageVirtualMachines = append(storageVirtualMachines, page.StorageVirtualMachines...) - - return !lastPage - }) - - if tfawserr.ErrCodeEquals(err, fsx.ErrCodeStorageVirtualMachineNotFound) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if len(storageVirtualMachines) == 0 || storageVirtualMachines[0] == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - if count := len(storageVirtualMachines); count > 1 { - return nil, tfresource.NewTooManyResultsError(count, input) - } - - return storageVirtualMachines[0], nil -} - func FindSnapshotByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.Snapshot, error) { input := &fsx.DescribeSnapshotsInput{ SnapshotIds: aws.StringSlice([]string{id}), diff --git a/internal/service/fsx/lustre_file_system.go b/internal/service/fsx/lustre_file_system.go index 01066ba083db..dc5f17841823 100644 --- a/internal/service/fsx/lustre_file_system.go +++ b/internal/service/fsx/lustre_file_system.go @@ -492,11 +492,10 @@ func resourceLustreFileSystemUpdate(ctx context.Context, d *schema.ResourceData, conn := meta.(*conns.AWSClient).FSxConn(ctx) if d.HasChangesExcept("tags", "tags_all") { - waitAdminAction := false input := &fsx.UpdateFileSystemInput{ ClientRequestToken: aws.String(id.UniqueId()), - LustreConfiguration: &fsx.UpdateFileSystemLustreConfiguration{}, FileSystemId: aws.String(d.Id()), + LustreConfiguration: &fsx.UpdateFileSystemLustreConfiguration{}, } if d.HasChange("auto_import_policy") { @@ -517,12 +516,10 @@ func resourceLustreFileSystemUpdate(ctx context.Context, d *schema.ResourceData, if d.HasChange("log_configuration") { input.LustreConfiguration.LogConfiguration = expandLustreLogCreateConfiguration(d.Get("log_configuration").([]interface{})) - waitAdminAction = true } if d.HasChange("root_squash_configuration") { input.LustreConfiguration.RootSquashConfiguration = expandLustreRootSquashConfiguration(d.Get("root_squash_configuration").([]interface{})) - waitAdminAction = true } if d.HasChange("storage_capacity") { @@ -544,10 +541,8 @@ func resourceLustreFileSystemUpdate(ctx context.Context, d *schema.ResourceData, return sdkdiag.AppendErrorf(diags, "waiting for FSx for Lustre File System (%s) update: %s", d.Id(), err) } - if waitAdminAction { - if _, err := waitAdministrativeActionCompleted(ctx, conn, d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for FSx for Lustre File System (%s) administrative action (%s) complete: %s", d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, err) - } + if _, err := waitAdministrativeActionCompleted(ctx, conn, d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, d.Timeout(schema.TimeoutUpdate)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for FSx for Lustre File System (%s) administrative action (%s) complete: %s", d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, err) } } @@ -663,43 +658,12 @@ func logStateFunc(v interface{}) string { return value } -func FindFileSystemByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.FileSystem, error) { +func findFileSystemByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.FileSystem, error) { input := &fsx.DescribeFileSystemsInput{ - FileSystemIds: []*string{aws.String(id)}, - } - - var filesystems []*fsx.FileSystem - - err := conn.DescribeFileSystemsPagesWithContext(ctx, input, func(page *fsx.DescribeFileSystemsOutput, lastPage bool) bool { - if page == nil { - return !lastPage - } - - filesystems = append(filesystems, page.FileSystems...) - - return !lastPage - }) - - if tfawserr.ErrCodeEquals(err, fsx.ErrCodeFileSystemNotFound) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - if len(filesystems) == 0 || filesystems[0] == nil { - return nil, tfresource.NewEmptyResultError(input) - } - - if count := len(filesystems); count > 1 { - return nil, tfresource.NewTooManyResultsError(count, input) + FileSystemIds: aws.StringSlice([]string{id}), } - return filesystems[0], nil + return findFileSystem(ctx, conn, input, tfslices.PredicateTrue[*fsx.FileSystem]()) } func FindLustreFileSystemByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.FileSystem, error) { @@ -770,7 +734,7 @@ func findFileSystems(ctx context.Context, conn *fsx.FSx, input *fsx.DescribeFile func statusFileSystem(ctx context.Context, conn *fsx.FSx, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - output, err := FindFileSystemByID(ctx, conn, id) + output, err := findFileSystemByID(ctx, conn, id) if tfresource.NotFound(err) { return nil, "", nil @@ -869,7 +833,7 @@ func waitFileSystemDeleted(ctx context.Context, conn *fsx.FSx, id string, timeou } func findAdministrativeAction(ctx context.Context, conn *fsx.FSx, fsID, actionType string) (*fsx.AdministrativeAction, error) { - output, err := FindFileSystemByID(ctx, conn, fsID) + output, err := findFileSystemByID(ctx, conn, fsID) if err != nil { return nil, err diff --git a/internal/service/fsx/lustre_file_system_test.go b/internal/service/fsx/lustre_file_system_test.go index 63cf038d2e73..6795c9949ac3 100644 --- a/internal/service/fsx/lustre_file_system_test.go +++ b/internal/service/fsx/lustre_file_system_test.go @@ -791,7 +791,7 @@ func TestAccFSxLustreFileSystem_kmsKeyID(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckLustreFileSystemExists(ctx, resourceName, &filesystem2), resource.TestCheckResourceAttr(resourceName, "deployment_type", fsx.LustreDeploymentTypePersistent1), - testAccCheckWindowsFileSystemRecreated(&filesystem1, &filesystem2), + testAccCheckLustreFileSystemRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttrPair(resourceName, "kms_key_id", kmsKeyResourceName2, "arn"), ), }, diff --git a/internal/service/fsx/ontap_file_system.go b/internal/service/fsx/ontap_file_system.go index b4d62a100ff7..07adec5097db 100644 --- a/internal/service/fsx/ontap_file_system.go +++ b/internal/service/fsx/ontap_file_system.go @@ -27,12 +27,13 @@ import ( // @SDKResource("aws_fsx_ontap_file_system", name="ONTAP File System") // @Tags(identifierAttribute="arn") -func ResourceOntapFileSystem() *schema.Resource { +func ResourceONTAPFileSystem() *schema.Resource { return &schema.Resource{ - CreateWithoutTimeout: resourceOntapFileSystemCreate, - ReadWithoutTimeout: resourceOntapFileSystemRead, - UpdateWithoutTimeout: resourceOntapFileSystemUpdate, - DeleteWithoutTimeout: resourceOntapFileSystemDelete, + CreateWithoutTimeout: resourceONTAPFileSystemCreate, + ReadWithoutTimeout: resourceONTAPFileSystemRead, + UpdateWithoutTimeout: resourceONTAPFileSystemUpdate, + DeleteWithoutTimeout: resourceONTAPFileSystemDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -95,6 +96,13 @@ func ResourceOntapFileSystem() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "endpoint_ip_address_range": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, + }, "endpoints": { Type: schema.TypeList, Computed: true, @@ -137,13 +145,6 @@ func ResourceOntapFileSystem() *schema.Resource { }, }, }, - "endpoint_ip_address_range": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, - }, "fsx_admin_password": { Type: schema.TypeString, Optional: true, @@ -173,17 +174,17 @@ func ResourceOntapFileSystem() *schema.Resource { Required: true, ForceNew: true, }, - "security_group_ids": { + "route_table_ids": { Type: schema.TypeSet, Optional: true, - ForceNew: true, + Computed: true, MaxItems: 50, Elem: &schema.Schema{Type: schema.TypeString}, }, - "route_table_ids": { + "security_group_ids": { Type: schema.TypeSet, Optional: true, - Computed: true, + ForceNew: true, MaxItems: 50, Elem: &schema.Schema{Type: schema.TypeString}, }, @@ -233,31 +234,23 @@ func ResourceOntapFileSystem() *schema.Resource { } } -func resourceOntapFileSystemCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPFileSystemCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) input := &fsx.CreateFileSystemInput{ ClientRequestToken: aws.String(id.UniqueId()), FileSystemType: aws.String(fsx.FileSystemTypeOntap), - StorageCapacity: aws.Int64(int64(d.Get("storage_capacity").(int))), - StorageType: aws.String(d.Get("storage_type").(string)), - SubnetIds: flex.ExpandStringList(d.Get("subnet_ids").([]interface{})), OntapConfiguration: &fsx.CreateFileSystemOntapConfiguration{ - DeploymentType: aws.String(d.Get("deployment_type").(string)), AutomaticBackupRetentionDays: aws.Int64(int64(d.Get("automatic_backup_retention_days").(int))), - ThroughputCapacity: aws.Int64(int64(d.Get("throughput_capacity").(int))), + DeploymentType: aws.String(d.Get("deployment_type").(string)), PreferredSubnetId: aws.String(d.Get("preferred_subnet_id").(string)), + ThroughputCapacity: aws.Int64(int64(d.Get("throughput_capacity").(int))), }, - Tags: getTagsIn(ctx), - } - - if v, ok := d.GetOk("kms_key_id"); ok { - input.KmsKeyId = aws.String(v.(string)) - } - - if v, ok := d.GetOk("endpoint_ip_address_range"); ok { - input.OntapConfiguration.EndpointIpAddressRange = aws.String(v.(string)) + StorageCapacity: aws.Int64(int64(d.Get("storage_capacity").(int))), + StorageType: aws.String(d.Get("storage_type").(string)), + SubnetIds: flex.ExpandStringList(d.Get("subnet_ids").([]interface{})), + Tags: getTagsIn(ctx), } if v, ok := d.GetOk("daily_automatic_backup_start_time"); ok { @@ -268,10 +261,18 @@ func resourceOntapFileSystemCreate(ctx context.Context, d *schema.ResourceData, input.OntapConfiguration.DiskIopsConfiguration = expandOntapFileDiskIopsConfiguration(v.([]interface{})) } + if v, ok := d.GetOk("endpoint_ip_address_range"); ok { + input.OntapConfiguration.EndpointIpAddressRange = aws.String(v.(string)) + } + if v, ok := d.GetOk("fsx_admin_password"); ok { input.OntapConfiguration.FsxAdminPassword = aws.String(v.(string)) } + if v, ok := d.GetOk("kms_key_id"); ok { + input.KmsKeyId = aws.String(v.(string)) + } + if v, ok := d.GetOk("route_table_ids"); ok { input.OntapConfiguration.RouteTableIds = flex.ExpandStringSet(v.(*schema.Set)) } @@ -284,98 +285,80 @@ func resourceOntapFileSystemCreate(ctx context.Context, d *schema.ResourceData, input.OntapConfiguration.WeeklyMaintenanceStartTime = aws.String(v.(string)) } - result, err := conn.CreateFileSystemWithContext(ctx, input) + output, err := conn.CreateFileSystemWithContext(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "creating FSx ONTAP File System: %s", err) + return sdkdiag.AppendErrorf(diags, "creating FSx for NetApp ONTAP File System: %s", err) } - d.SetId(aws.StringValue(result.FileSystem.FileSystemId)) + d.SetId(aws.StringValue(output.FileSystem.FileSystemId)) if _, err := waitFileSystemCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for FSx ONTAP File System (%s) create: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for FSx for NetApp ONTAP File System (%s) create: %s", d.Id(), err) } - return append(diags, resourceOntapFileSystemRead(ctx, d, meta)...) + return append(diags, resourceONTAPFileSystemRead(ctx, d, meta)...) } -func resourceOntapFileSystemRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPFileSystemRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) - filesystem, err := FindFileSystemByID(ctx, conn, d.Id()) + filesystem, err := FindONTAPFileSystemByID(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { - log.Printf("[WARN] FSx ONTAP File System (%s) not found, removing from state", d.Id()) + log.Printf("[WARN] FSx for NetApp ONTAP File System (%s) not found, removing from state", d.Id()) d.SetId("") return diags } if err != nil { - return sdkdiag.AppendErrorf(diags, "reading FSx ONTAP File System (%s): %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "reading FSx for NetApp ONTAP File System (%s): %s", d.Id(), err) } ontapConfig := filesystem.OntapConfiguration - if ontapConfig == nil { - return sdkdiag.AppendErrorf(diags, "describing FSx ONTAP File System (%s): empty ONTAP configuration", d.Id()) - } d.Set("arn", filesystem.ResourceARN) - d.Set("dns_name", filesystem.DNSName) - d.Set("deployment_type", ontapConfig.DeploymentType) - d.Set("storage_type", filesystem.StorageType) - d.Set("vpc_id", filesystem.VpcId) - d.Set("weekly_maintenance_start_time", ontapConfig.WeeklyMaintenanceStartTime) d.Set("automatic_backup_retention_days", ontapConfig.AutomaticBackupRetentionDays) d.Set("daily_automatic_backup_start_time", ontapConfig.DailyAutomaticBackupStartTime) - d.Set("throughput_capacity", ontapConfig.ThroughputCapacity) - d.Set("preferred_subnet_id", ontapConfig.PreferredSubnetId) - d.Set("endpoint_ip_address_range", ontapConfig.EndpointIpAddressRange) - d.Set("owner_id", filesystem.OwnerId) - d.Set("storage_capacity", filesystem.StorageCapacity) - d.Set("fsx_admin_password", d.Get("fsx_admin_password").(string)) - d.Set("kms_key_id", filesystem.KmsKeyId) - - if err := d.Set("network_interface_ids", aws.StringValueSlice(filesystem.NetworkInterfaceIds)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting network_interface_ids: %s", err) - } - - if err := d.Set("subnet_ids", aws.StringValueSlice(filesystem.SubnetIds)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting subnet_ids: %s", err) - } - - if err := d.Set("route_table_ids", aws.StringValueSlice(ontapConfig.RouteTableIds)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting subnet_ids: %s", err) + d.Set("deployment_type", ontapConfig.DeploymentType) + if err := d.Set("disk_iops_configuration", flattenOntapFileDiskIopsConfiguration(ontapConfig.DiskIopsConfiguration)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting disk_iops_configuration: %s", err) } - + d.Set("dns_name", filesystem.DNSName) + d.Set("endpoint_ip_address_range", ontapConfig.EndpointIpAddressRange) if err := d.Set("endpoints", flattenOntapFileSystemEndpoints(ontapConfig.Endpoints)); err != nil { return sdkdiag.AppendErrorf(diags, "setting endpoints: %s", err) } - - if err := d.Set("disk_iops_configuration", flattenOntapFileDiskIopsConfiguration(ontapConfig.DiskIopsConfiguration)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting disk_iops_configuration: %s", err) - } + d.Set("fsx_admin_password", d.Get("fsx_admin_password").(string)) + d.Set("kms_key_id", filesystem.KmsKeyId) + d.Set("network_interface_ids", aws.StringValueSlice(filesystem.NetworkInterfaceIds)) + d.Set("owner_id", filesystem.OwnerId) + d.Set("preferred_subnet_id", ontapConfig.PreferredSubnetId) + d.Set("route_table_ids", aws.StringValueSlice(ontapConfig.RouteTableIds)) + d.Set("storage_capacity", filesystem.StorageCapacity) + d.Set("storage_type", filesystem.StorageType) + d.Set("subnet_ids", aws.StringValueSlice(filesystem.SubnetIds)) + d.Set("throughput_capacity", ontapConfig.ThroughputCapacity) + d.Set("vpc_id", filesystem.VpcId) + d.Set("weekly_maintenance_start_time", ontapConfig.WeeklyMaintenanceStartTime) setTagsOut(ctx, filesystem.Tags) return diags } -func resourceOntapFileSystemUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPFileSystemUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) - if d.HasChangesExcept("tags_all", "tags") { + if d.HasChangesExcept("tags", "tags_all") { input := &fsx.UpdateFileSystemInput{ ClientRequestToken: aws.String(id.UniqueId()), FileSystemId: aws.String(d.Id()), OntapConfiguration: &fsx.UpdateFileSystemOntapConfiguration{}, } - if d.HasChange("storage_capacity") { - input.StorageCapacity = aws.Int64(int64(d.Get("storage_capacity").(int))) - } - if d.HasChange("automatic_backup_retention_days") { input.OntapConfiguration.AutomaticBackupRetentionDays = aws.Int64(int64(d.Get("automatic_backup_retention_days").(int))) } @@ -384,47 +367,49 @@ func resourceOntapFileSystemUpdate(ctx context.Context, d *schema.ResourceData, input.OntapConfiguration.DailyAutomaticBackupStartTime = aws.String(d.Get("daily_automatic_backup_start_time").(string)) } - if d.HasChange("fsx_admin_password") { - input.OntapConfiguration.FsxAdminPassword = aws.String(d.Get("fsx_admin_password").(string)) - } - - if d.HasChange("weekly_maintenance_start_time") { - input.OntapConfiguration.WeeklyMaintenanceStartTime = aws.String(d.Get("weekly_maintenance_start_time").(string)) - } - - if d.HasChange("throughput_capacity") { - input.OntapConfiguration.ThroughputCapacity = aws.Int64(int64(d.Get("throughput_capacity").(int))) - } - if d.HasChange("disk_iops_configuration") { input.OntapConfiguration.DiskIopsConfiguration = expandOntapFileDiskIopsConfiguration(d.Get("disk_iops_configuration").([]interface{})) } + if d.HasChange("fsx_admin_password") { + input.OntapConfiguration.FsxAdminPassword = aws.String(d.Get("fsx_admin_password").(string)) + } + if d.HasChange("route_table_ids") { o, n := d.GetChange("route_table_ids") - ns := n.(*schema.Set) - os := o.(*schema.Set) - added := ns.Difference(os) - removed := os.Difference(ns) + os, ns := o.(*schema.Set), n.(*schema.Set) + add, del := flex.ExpandStringValueSet(ns.Difference(os)), flex.ExpandStringValueSet(os.Difference(ns)) - if added.Len() > 0 { - input.OntapConfiguration.AddRouteTableIds = flex.ExpandStringSet(added) + if len(add) > 0 { + input.OntapConfiguration.AddRouteTableIds = aws.StringSlice(add) } - if removed.Len() > 0 { - input.OntapConfiguration.RemoveRouteTableIds = flex.ExpandStringSet(removed) + if len(del) > 0 { + input.OntapConfiguration.RemoveRouteTableIds = aws.StringSlice(del) } } + if d.HasChange("storage_capacity") { + input.StorageCapacity = aws.Int64(int64(d.Get("storage_capacity").(int))) + } + + if d.HasChange("throughput_capacity") { + input.OntapConfiguration.ThroughputCapacity = aws.Int64(int64(d.Get("throughput_capacity").(int))) + } + + if d.HasChange("weekly_maintenance_start_time") { + input.OntapConfiguration.WeeklyMaintenanceStartTime = aws.String(d.Get("weekly_maintenance_start_time").(string)) + } + startTime := time.Now() _, err := conn.UpdateFileSystemWithContext(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "updating FSx ONTAP File System (%s): %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "updating FSx for NetApp ONTAP File System (%s): %s", d.Id(), err) } if _, err := waitFileSystemUpdated(ctx, conn, d.Id(), startTime, d.Timeout(schema.TimeoutUpdate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for FSx ONTAP File System (%s) update: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for FSx for NetApp ONTAP File System (%s) update: %s", d.Id(), err) } if _, err := waitAdministrativeActionCompleted(ctx, conn, d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, d.Timeout(schema.TimeoutUpdate)); err != nil { @@ -432,14 +417,14 @@ func resourceOntapFileSystemUpdate(ctx context.Context, d *schema.ResourceData, } } - return append(diags, resourceOntapFileSystemRead(ctx, d, meta)...) + return append(diags, resourceONTAPFileSystemRead(ctx, d, meta)...) } -func resourceOntapFileSystemDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPFileSystemDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) - log.Printf("[DEBUG] Deleting FSx ONTAP File System: %s", d.Id()) + log.Printf("[DEBUG] Deleting FSx for NetApp ONTAP File System: %s", d.Id()) _, err := conn.DeleteFileSystemWithContext(ctx, &fsx.DeleteFileSystemInput{ FileSystemId: aws.String(d.Id()), }) @@ -449,11 +434,11 @@ func resourceOntapFileSystemDelete(ctx context.Context, d *schema.ResourceData, } if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting FSx ONTAP File System (%s): %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "deleting FSx for NetApp ONTAP File System (%s): %s", d.Id(), err) } if _, err := waitFileSystemDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for FSx ONTAP File System (%s) delete: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for FSx for NetApp ONTAP File System (%s) delete: %s", d.Id(), err) } return diags @@ -525,3 +510,17 @@ func flattenOntapFileSystemEndpoint(rs *fsx.FileSystemEndpoint) []interface{} { return []interface{}{m} } + +func FindONTAPFileSystemByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.FileSystem, error) { + output, err := findFileSystemByIDAndType(ctx, conn, id, fsx.FileSystemTypeOntap) + + if err != nil { + return nil, err + } + + if output.OntapConfiguration == nil { + return nil, tfresource.NewEmptyResultError(nil) + } + + return output, nil +} diff --git a/internal/service/fsx/ontap_file_system_test.go b/internal/service/fsx/ontap_file_system_test.go index 677a1549488e..64dd825cb172 100644 --- a/internal/service/fsx/ontap_file_system_test.go +++ b/internal/service/fsx/ontap_file_system_test.go @@ -20,7 +20,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -func TestAccFSxOntapFileSystem_basic(t *testing.T) { +func TestAccFSxONTAPFileSystem_basic(t *testing.T) { ctx := acctest.Context(t) var filesystem fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -30,39 +30,39 @@ func TestAccFSxOntapFileSystem_basic(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "fsx", regexache.MustCompile(`file-system/fs-.+`)), - resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "2"), - acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), - resource.TestCheckResourceAttr(resourceName, "storage_capacity", "1024"), - resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test1", "id"), - resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test2", "id"), - resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), - resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), - resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"), - resource.TestMatchResourceAttr(resourceName, "weekly_maintenance_start_time", regexache.MustCompile(`^\d:\d\d:\d\d$`)), - resource.TestCheckResourceAttr(resourceName, "deployment_type", fsx.OntapDeploymentTypeMultiAz1), resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "0"), - resource.TestCheckResourceAttr(resourceName, "storage_type", fsx.StorageTypeSsd), - resource.TestCheckResourceAttrSet(resourceName, "kms_key_id"), + resource.TestCheckResourceAttr(resourceName, "deployment_type", fsx.OntapDeploymentTypeMultiAz1), + resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.iops", "3072"), + resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.mode", "AUTOMATIC"), resource.TestCheckResourceAttrSet(resourceName, "endpoint_ip_address_range"), - resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "1"), - resource.TestCheckTypeSetElemAttrPair(resourceName, "route_table_ids.*", "aws_vpc.test", "default_route_table_id"), - resource.TestCheckResourceAttr(resourceName, "throughput_capacity", "128"), - resource.TestCheckResourceAttrPair(resourceName, "preferred_subnet_id", "aws_subnet.test1", "id"), resource.TestCheckResourceAttr(resourceName, "endpoints.#", "1"), resource.TestCheckResourceAttr(resourceName, "endpoints.0.intercluster.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "endpoints.0.intercluster.0.dns_name"), resource.TestCheckResourceAttr(resourceName, "endpoints.0.management.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "endpoints.0.management.0.dns_name"), - resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.#", "1"), - resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.mode", "AUTOMATIC"), - resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.iops", "3072"), + resource.TestCheckResourceAttrSet(resourceName, "kms_key_id"), + resource.TestCheckResourceAttr(resourceName, "network_interface_ids.#", "2"), + acctest.CheckResourceAttrAccountID(resourceName, "owner_id"), + resource.TestCheckResourceAttrPair(resourceName, "preferred_subnet_id", "aws_subnet.test.0", "id"), + resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "route_table_ids.*", "aws_vpc.test", "default_route_table_id"), + resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "storage_capacity", "1024"), + resource.TestCheckResourceAttr(resourceName, "storage_type", fsx.StorageTypeSsd), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test.0", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_ids.*", "aws_subnet.test.1", "id"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "throughput_capacity", "128"), + resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"), + resource.TestMatchResourceAttr(resourceName, "weekly_maintenance_start_time", regexache.MustCompile(`^\d:\d\d:\d\d$`)), ), }, { @@ -75,7 +75,7 @@ func TestAccFSxOntapFileSystem_basic(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_fsxSingleAz(t *testing.T) { +func TestAccFSxONTAPFileSystem_singleAZ(t *testing.T) { ctx := acctest.Context(t) var filesystem fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -85,12 +85,12 @@ func TestAccFSxOntapFileSystem_fsxSingleAz(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccONTAPFileSystemConfig_singleAz(rName), + Config: testAccONTAPFileSystemConfig_singleAZ(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "fsx", regexache.MustCompile(`file-system/fs-.+`)), resource.TestCheckResourceAttr(resourceName, "deployment_type", fsx.OntapDeploymentTypeSingleAz1), ), @@ -105,7 +105,7 @@ func TestAccFSxOntapFileSystem_fsxSingleAz(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_fsxAdminPassword(t *testing.T) { +func TestAccFSxONTAPFileSystem_fsxAdminPassword(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -117,12 +117,12 @@ func TestAccFSxOntapFileSystem_fsxAdminPassword(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_adminPassword(rName, pass1), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "fsx_admin_password", pass1), ), }, @@ -135,8 +135,8 @@ func TestAccFSxOntapFileSystem_fsxAdminPassword(t *testing.T) { { Config: testAccONTAPFileSystemConfig_adminPassword(rName, pass2), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemNotRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemNotRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "fsx_admin_password", pass2), ), }, @@ -144,7 +144,7 @@ func TestAccFSxOntapFileSystem_fsxAdminPassword(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_endpointIPAddressRange(t *testing.T) { +func TestAccFSxONTAPFileSystem_endpointIPAddressRange(t *testing.T) { ctx := acctest.Context(t) var filesystem fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -154,12 +154,12 @@ func TestAccFSxOntapFileSystem_endpointIPAddressRange(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_endpointIPAddressRange(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem), resource.TestCheckResourceAttr(resourceName, "endpoint_ip_address_range", "198.19.255.0/24"), ), }, @@ -173,7 +173,7 @@ func TestAccFSxOntapFileSystem_endpointIPAddressRange(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_diskIops(t *testing.T) { +func TestAccFSxONTAPFileSystem_diskIOPS(t *testing.T) { ctx := acctest.Context(t) var filesystem fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -183,12 +183,12 @@ func TestAccFSxOntapFileSystem_diskIops(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_diskIOPSConfiguration(rName, 3072), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem), resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.mode", "USER_PROVISIONED"), resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.iops", "3072"), @@ -203,7 +203,7 @@ func TestAccFSxOntapFileSystem_diskIops(t *testing.T) { { Config: testAccONTAPFileSystemConfig_diskIOPSConfiguration(rName, 4000), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem), resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.mode", "USER_PROVISIONED"), resource.TestCheckResourceAttr(resourceName, "disk_iops_configuration.0.iops", "4000"), @@ -213,7 +213,7 @@ func TestAccFSxOntapFileSystem_diskIops(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_disappears(t *testing.T) { +func TestAccFSxONTAPFileSystem_disappears(t *testing.T) { ctx := acctest.Context(t) var filesystem fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -223,13 +223,13 @@ func TestAccFSxOntapFileSystem_disappears(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem), - acctest.CheckResourceDisappears(ctx, acctest.Provider, tffsx.ResourceOntapFileSystem(), resourceName), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tffsx.ResourceONTAPFileSystem(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -237,7 +237,7 @@ func TestAccFSxOntapFileSystem_disappears(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_securityGroupIDs(t *testing.T) { +func TestAccFSxONTAPFileSystem_securityGroupIDs(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -247,12 +247,12 @@ func TestAccFSxOntapFileSystem_securityGroupIDs(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_securityGroupIDs1(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "1"), ), }, @@ -265,8 +265,8 @@ func TestAccFSxOntapFileSystem_securityGroupIDs(t *testing.T) { { Config: testAccONTAPFileSystemConfig_securityGroupIDs2(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "security_group_ids.#", "2"), ), }, @@ -274,7 +274,7 @@ func TestAccFSxOntapFileSystem_securityGroupIDs(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_routeTableIDs(t *testing.T) { +func TestAccFSxONTAPFileSystem_routeTableIDs(t *testing.T) { ctx := acctest.Context(t) var filesystem1 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -284,12 +284,12 @@ func TestAccFSxOntapFileSystem_routeTableIDs(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_routeTable(rName, 1), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "1"), resource.TestCheckTypeSetElemAttrPair(resourceName, "route_table_ids.*", "aws_route_table.test.0", "id"), ), @@ -303,7 +303,7 @@ func TestAccFSxOntapFileSystem_routeTableIDs(t *testing.T) { { Config: testAccONTAPFileSystemConfig_routeTable(rName, 2), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "2"), resource.TestCheckTypeSetElemAttrPair(resourceName, "route_table_ids.*", "aws_route_table.test.0", "id"), resource.TestCheckTypeSetElemAttrPair(resourceName, "route_table_ids.*", "aws_route_table.test.1", "id"), @@ -312,7 +312,7 @@ func TestAccFSxOntapFileSystem_routeTableIDs(t *testing.T) { { Config: testAccONTAPFileSystemConfig_routeTable(rName, 1), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "route_table_ids.#", "1"), resource.TestCheckTypeSetElemAttrPair(resourceName, "route_table_ids.*", "aws_route_table.test.0", "id"), ), @@ -321,7 +321,7 @@ func TestAccFSxOntapFileSystem_routeTableIDs(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_tags(t *testing.T) { +func TestAccFSxONTAPFileSystem_tags(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2, filesystem3 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -331,12 +331,12 @@ func TestAccFSxOntapFileSystem_tags(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_tags1(rName, "key1", "value1"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), @@ -350,8 +350,8 @@ func TestAccFSxOntapFileSystem_tags(t *testing.T) { { Config: testAccONTAPFileSystemConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemNotRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemNotRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), @@ -360,8 +360,8 @@ func TestAccFSxOntapFileSystem_tags(t *testing.T) { { Config: testAccONTAPFileSystemConfig_tags1(rName, "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem3), - testAccCheckOntapFileSystemNotRecreated(&filesystem2, &filesystem3), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem3), + testAccCheckONTAPFileSystemNotRecreated(&filesystem2, &filesystem3), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), ), @@ -370,7 +370,7 @@ func TestAccFSxOntapFileSystem_tags(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_weeklyMaintenanceStartTime(t *testing.T) { +func TestAccFSxONTAPFileSystem_weeklyMaintenanceStartTime(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -380,12 +380,12 @@ func TestAccFSxOntapFileSystem_weeklyMaintenanceStartTime(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_weeklyMaintenanceStartTime(rName, "1:01:01"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "weekly_maintenance_start_time", "1:01:01"), ), }, @@ -398,8 +398,8 @@ func TestAccFSxOntapFileSystem_weeklyMaintenanceStartTime(t *testing.T) { { Config: testAccONTAPFileSystemConfig_weeklyMaintenanceStartTime(rName, "2:02:02"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemNotRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemNotRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "weekly_maintenance_start_time", "2:02:02"), ), }, @@ -407,7 +407,7 @@ func TestAccFSxOntapFileSystem_weeklyMaintenanceStartTime(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_automaticBackupRetentionDays(t *testing.T) { +func TestAccFSxONTAPFileSystem_automaticBackupRetentionDays(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -417,12 +417,12 @@ func TestAccFSxOntapFileSystem_automaticBackupRetentionDays(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_automaticBackupRetentionDays(rName, 90), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "90"), ), }, @@ -435,15 +435,15 @@ func TestAccFSxOntapFileSystem_automaticBackupRetentionDays(t *testing.T) { { Config: testAccONTAPFileSystemConfig_automaticBackupRetentionDays(rName, 0), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemNotRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemNotRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "0"), ), }, { Config: testAccONTAPFileSystemConfig_automaticBackupRetentionDays(rName, 1), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "automatic_backup_retention_days", "1"), ), }, @@ -451,7 +451,7 @@ func TestAccFSxOntapFileSystem_automaticBackupRetentionDays(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_kmsKeyID(t *testing.T) { +func TestAccFSxONTAPFileSystem_kmsKeyID(t *testing.T) { ctx := acctest.Context(t) var filesystem fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -461,12 +461,12 @@ func TestAccFSxOntapFileSystem_kmsKeyID(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_kmsKeyID(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem), resource.TestCheckResourceAttrPair(resourceName, "kms_key_id", "aws_kms_key.test", "arn"), ), }, @@ -480,7 +480,7 @@ func TestAccFSxOntapFileSystem_kmsKeyID(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_dailyAutomaticBackupStartTime(t *testing.T) { +func TestAccFSxONTAPFileSystem_dailyAutomaticBackupStartTime(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -495,7 +495,7 @@ func TestAccFSxOntapFileSystem_dailyAutomaticBackupStartTime(t *testing.T) { { Config: testAccONTAPFileSystemConfig_dailyAutomaticBackupStartTime(rName, "01:01"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "daily_automatic_backup_start_time", "01:01"), ), }, @@ -508,8 +508,8 @@ func TestAccFSxOntapFileSystem_dailyAutomaticBackupStartTime(t *testing.T) { { Config: testAccONTAPFileSystemConfig_dailyAutomaticBackupStartTime(rName, "02:02"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemNotRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemNotRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "daily_automatic_backup_start_time", "02:02"), ), }, @@ -517,7 +517,7 @@ func TestAccFSxOntapFileSystem_dailyAutomaticBackupStartTime(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_throughputCapacity(t *testing.T) { +func TestAccFSxONTAPFileSystem_throughputCapacity(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -527,12 +527,12 @@ func TestAccFSxOntapFileSystem_throughputCapacity(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "throughput_capacity", "128"), ), }, @@ -545,8 +545,8 @@ func TestAccFSxOntapFileSystem_throughputCapacity(t *testing.T) { { Config: testAccONTAPFileSystemConfig_throughputCapacity(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemNotRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemNotRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "throughput_capacity", "256"), ), }, @@ -554,7 +554,7 @@ func TestAccFSxOntapFileSystem_throughputCapacity(t *testing.T) { }) } -func TestAccFSxOntapFileSystem_storageCapacity(t *testing.T) { +func TestAccFSxONTAPFileSystem_storageCapacity(t *testing.T) { ctx := acctest.Context(t) var filesystem1, filesystem2 fsx.FileSystem resourceName := "aws_fsx_ontap_file_system.test" @@ -564,12 +564,12 @@ func TestAccFSxOntapFileSystem_storageCapacity(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapFileSystemDestroy(ctx), + CheckDestroy: testAccCheckONTAPFileSystemDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPFileSystemConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem1), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem1), resource.TestCheckResourceAttr(resourceName, "storage_capacity", "1024"), ), }, @@ -582,8 +582,8 @@ func TestAccFSxOntapFileSystem_storageCapacity(t *testing.T) { { Config: testAccONTAPFileSystemConfig_storageCapacity(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapFileSystemExists(ctx, resourceName, &filesystem2), - testAccCheckOntapFileSystemNotRecreated(&filesystem1, &filesystem2), + testAccCheckONTAPFileSystemExists(ctx, resourceName, &filesystem2), + testAccCheckONTAPFileSystemNotRecreated(&filesystem1, &filesystem2), resource.TestCheckResourceAttr(resourceName, "storage_capacity", "2048"), ), }, @@ -591,31 +591,28 @@ func TestAccFSxOntapFileSystem_storageCapacity(t *testing.T) { }) } -func testAccCheckOntapFileSystemExists(ctx context.Context, resourceName string, fs *fsx.FileSystem) resource.TestCheckFunc { +func testAccCheckONTAPFileSystemExists(ctx context.Context, n string, v *fsx.FileSystem) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", resourceName) + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).FSxConn(ctx) - filesystem, err := tffsx.FindFileSystemByID(ctx, conn, rs.Primary.ID) + output, err := tffsx.FindONTAPFileSystemByID(ctx, conn, rs.Primary.ID) + if err != nil { return err } - if filesystem == nil { - return fmt.Errorf("FSx ONTAP File System (%s) not found", rs.Primary.ID) - } - - *fs = *filesystem + *v = *output return nil } } -func testAccCheckOntapFileSystemDestroy(ctx context.Context) resource.TestCheckFunc { +func testAccCheckONTAPFileSystemDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).FSxConn(ctx) @@ -624,105 +621,83 @@ func testAccCheckOntapFileSystemDestroy(ctx context.Context) resource.TestCheckF continue } - filesystem, err := tffsx.FindFileSystemByID(ctx, conn, rs.Primary.ID) + _, err := tffsx.FindONTAPFileSystemByID(ctx, conn, rs.Primary.ID) + if tfresource.NotFound(err) { continue } - if filesystem != nil { - return fmt.Errorf("FSx ONTAP File System (%s) still exists", rs.Primary.ID) + if err != nil { + return err } + + return fmt.Errorf("FSx for NetApp ONTAP File System (%s) still exists", rs.Primary.ID) } + return nil } } -func testAccCheckOntapFileSystemNotRecreated(i, j *fsx.FileSystem) resource.TestCheckFunc { +func testAccCheckONTAPFileSystemNotRecreated(i, j *fsx.FileSystem) resource.TestCheckFunc { return func(s *terraform.State) error { if aws.StringValue(i.FileSystemId) != aws.StringValue(j.FileSystemId) { - return fmt.Errorf("FSx ONTAP File System (%s) recreated", aws.StringValue(i.FileSystemId)) + return fmt.Errorf("FSx for NetApp ONTAP File System (%s) recreated", aws.StringValue(i.FileSystemId)) } return nil } } -func testAccCheckOntapFileSystemRecreated(i, j *fsx.FileSystem) resource.TestCheckFunc { +func testAccCheckONTAPFileSystemRecreated(i, j *fsx.FileSystem) resource.TestCheckFunc { return func(s *terraform.State) error { if aws.StringValue(i.FileSystemId) == aws.StringValue(j.FileSystemId) { - return fmt.Errorf("FSx ONTAP File System (%s) not recreated", aws.StringValue(i.FileSystemId)) + return fmt.Errorf("FSx for NetApp ONTAP File System (%s) not recreated", aws.StringValue(i.FileSystemId)) } return nil } } -func testAccOntapFileSystemBaseConfig(rName string) string { - return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` -data "aws_partition" "current" {} - -resource "aws_vpc" "test" { - cidr_block = "10.0.0.0/16" - - tags = { - Name = %[1]q - } -} - -resource "aws_subnet" "test1" { - vpc_id = aws_vpc.test.id - cidr_block = "10.0.1.0/24" - availability_zone = data.aws_availability_zones.available.names[0] - - tags = { - Name = %[1]q - } -} - -resource "aws_subnet" "test2" { - vpc_id = aws_vpc.test.id - cidr_block = "10.0.2.0/24" - availability_zone = data.aws_availability_zones.available.names[1] - - tags = { - Name = %[1]q - } -} -`, rName)) +func testAccONTAPFileSystemConfig_base(rName string) string { + return acctest.ConfigVPCWithSubnets(rName, 2) } func testAccONTAPFileSystemConfig_basic(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), ` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), ` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id } `) } -func testAccONTAPFileSystemConfig_singleAz(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), ` +func testAccONTAPFileSystemConfig_singleAZ(rName string) string { + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id] + subnet_ids = [aws_subnet.test[0].id] deployment_type = "SINGLE_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id + + tags = { + Name = %[1]q + } } -`) +`, rName)) } func testAccONTAPFileSystemConfig_adminPassword(rName, pass string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id fsx_admin_password = %[2]q tags = { @@ -733,13 +708,13 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_endpointIPAddressRange(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id endpoint_ip_address_range = "198.19.255.0/24" tags = { @@ -750,13 +725,13 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_diskIOPSConfiguration(rName string, iops int) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id disk_iops_configuration { mode = "USER_PROVISIONED" @@ -771,7 +746,7 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_routeTable(rName string, cnt int) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_internet_gateway" "test" { vpc_id = aws_vpc.test.id @@ -797,10 +772,10 @@ resource "aws_route_table" "test" { resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id route_table_ids = aws_route_table.test[*].id tags = { @@ -811,10 +786,10 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_securityGroupIDs1(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_security_group" "test1" { - description = "security group for FSx testing" - vpc_id = aws_vpc.test.id + name = "%[1]s-1" + vpc_id = aws_vpc.test.id ingress { cidr_blocks = [aws_vpc.test.cidr_block] @@ -838,10 +813,10 @@ resource "aws_security_group" "test1" { resource "aws_fsx_ontap_file_system" "test" { security_group_ids = [aws_security_group.test1.id] storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id tags = { Name = %[1]q @@ -851,10 +826,10 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_securityGroupIDs2(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_security_group" "test1" { - description = "security group for FSx testing" - vpc_id = aws_vpc.test.id + name = "%[1]s-1" + vpc_id = aws_vpc.test.id ingress { cidr_blocks = [aws_vpc.test.cidr_block] @@ -876,8 +851,8 @@ resource "aws_security_group" "test1" { } resource "aws_security_group" "test2" { - description = "security group for FSx testing" - vpc_id = aws_vpc.test.id + name = "%[1]s-2" + vpc_id = aws_vpc.test.id ingress { cidr_blocks = [aws_vpc.test.cidr_block] @@ -901,10 +876,10 @@ resource "aws_security_group" "test2" { resource "aws_fsx_ontap_file_system" "test" { security_group_ids = [aws_security_group.test1.id, aws_security_group.test2.id] storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id tags = { Name = %[1]q @@ -914,13 +889,13 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_tags1(rName, tagKey1, tagValue1 string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id tags = { %[1]q = %[2]q @@ -930,13 +905,13 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id tags = { %[1]q = %[2]q @@ -947,13 +922,13 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_weeklyMaintenanceStartTime(rName, weeklyMaintenanceStartTime string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id weekly_maintenance_start_time = %[2]q tags = { @@ -964,13 +939,13 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_dailyAutomaticBackupStartTime(rName, dailyAutomaticBackupStartTime string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id daily_automatic_backup_start_time = %[2]q automatic_backup_retention_days = 1 @@ -982,13 +957,13 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_automaticBackupRetentionDays(rName string, retention int) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id automatic_backup_retention_days = %[2]d tags = { @@ -999,7 +974,7 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_kmsKeyID(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_kms_key" "test" { description = %[1]q deletion_window_in_days = 7 @@ -1007,10 +982,10 @@ resource "aws_kms_key" "test" { resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id kms_key_id = aws_kms_key.test.arn tags = { @@ -1021,25 +996,33 @@ resource "aws_fsx_ontap_file_system" "test" { } func testAccONTAPFileSystemConfig_throughputCapacity(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), ` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 256 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id + + tags = { + Name = %[1]q + } } -`) +`, rName)) } func testAccONTAPFileSystemConfig_storageCapacity(rName string) string { - return acctest.ConfigCompose(testAccOntapFileSystemBaseConfig(rName), ` + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 2048 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 128 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id + + tags = { + Name = %[1]q + } } -`) +`, rName)) } diff --git a/internal/service/fsx/ontap_storage_virtual_machine.go b/internal/service/fsx/ontap_storage_virtual_machine.go index b9f9e4e6baca..b888ee4f90b6 100644 --- a/internal/service/fsx/ontap_storage_virtual_machine.go +++ b/internal/service/fsx/ontap_storage_virtual_machine.go @@ -5,8 +5,8 @@ package fsx import ( "context" + "errors" "log" - "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -14,11 +14,13 @@ import ( "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" + tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -27,12 +29,13 @@ import ( // @SDKResource("aws_fsx_ontap_storage_virtual_machine", name="ONTAP Storage Virtual Machine") // @Tags(identifierAttribute="arn") -func ResourceOntapStorageVirtualMachine() *schema.Resource { +func ResourceONTAPStorageVirtualMachine() *schema.Resource { return &schema.Resource{ - CreateWithoutTimeout: resourceOntapStorageVirtualMachineCreate, - ReadWithoutTimeout: resourceOntapStorageVirtualMachineRead, - UpdateWithoutTimeout: resourceOntapStorageVirtualMachineUpdate, - DeleteWithoutTimeout: resourceOntapStorageVirtualMachineDelete, + CreateWithoutTimeout: resourceONTAPStorageVirtualMachineCreate, + ReadWithoutTimeout: resourceONTAPStorageVirtualMachineRead, + UpdateWithoutTimeout: resourceONTAPStorageVirtualMachineUpdate, + DeleteWithoutTimeout: resourceONTAPStorageVirtualMachineDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -46,17 +49,13 @@ func ResourceOntapStorageVirtualMachine() *schema.Resource { SchemaVersion: 1, StateUpgraders: []schema.StateUpgrader{ { - Type: ResourceOntapStorageVirtualMachineV0().CoreConfigSchema().ImpliedType(), - Upgrade: ResourceOntapStorageVirtualMachineStateUpgradeV0, + Type: ResourceONTAPStorageVirtualMachineV0().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceONTAPStorageVirtualMachineStateUpgradeV0, Version: 0, }, }, Schema: map[string]*schema.Schema{ - "arn": { - Type: schema.TypeString, - Computed: true, - }, "active_directory_configuration": { Type: schema.TypeList, Optional: true, @@ -64,12 +63,10 @@ func ResourceOntapStorageVirtualMachine() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "netbios_name": { - Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.EqualFold(old, new) - }, - ValidateFunc: validation.StringLenBetween(1, 15), + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: verify.SuppressEquivalentStringCaseInsensitive, + ValidateFunc: validation.StringLenBetween(1, 15), }, "self_managed_active_directory_configuration": { Type: schema.TypeList, @@ -90,19 +87,16 @@ func ResourceOntapStorageVirtualMachine() *schema.Resource { "domain_name": { Type: schema.TypeString, Required: true, - ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 255), }, "file_system_administrators_group": { Type: schema.TypeString, Optional: true, - ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 256), }, "organizational_unit_distinguished_name": { Type: schema.TypeString, Optional: true, - ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 2000), }, "password": { @@ -122,6 +116,10 @@ func ResourceOntapStorageVirtualMachine() *schema.Resource { }, }, }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, "endpoints": { Type: schema.TypeList, Computed: true, @@ -237,18 +235,19 @@ func ResourceOntapStorageVirtualMachine() *schema.Resource { } } -func resourceOntapStorageVirtualMachineCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPStorageVirtualMachineCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) + name := d.Get("name").(string) input := &fsx.CreateStorageVirtualMachineInput{ FileSystemId: aws.String(d.Get("file_system_id").(string)), - Name: aws.String(d.Get("name").(string)), + Name: aws.String(name), Tags: getTagsIn(ctx), } if v, ok := d.GetOk("active_directory_configuration"); ok { - input.ActiveDirectoryConfiguration = expandOntapSvmActiveDirectoryConfigurationCreate(v.([]interface{})) + input.ActiveDirectoryConfiguration = expandCreateSvmActiveDirectoryConfiguration(v.([]interface{})) } if v, ok := d.GetOk("root_volume_security_style"); ok { @@ -259,22 +258,22 @@ func resourceOntapStorageVirtualMachineCreate(ctx context.Context, d *schema.Res input.SvmAdminPassword = aws.String(v.(string)) } - result, err := conn.CreateStorageVirtualMachineWithContext(ctx, input) + output, err := conn.CreateStorageVirtualMachineWithContext(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "creating FSx Storage Virtual System: %s", err) + return sdkdiag.AppendErrorf(diags, "creating FSx ONTAP Storage Virtual Machine (%s): %s", name, err) } - d.SetId(aws.StringValue(result.StorageVirtualMachine.StorageVirtualMachineId)) + d.SetId(aws.StringValue(output.StorageVirtualMachine.StorageVirtualMachineId)) if _, err := waitStorageVirtualMachineCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for FSx Storage Virtual Machine (%s) create: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "waiting for FSx ONTAP Storage Virtual Machine (%s) create: %s", d.Id(), err) } - return append(diags, resourceOntapStorageVirtualMachineRead(ctx, d, meta)...) + return append(diags, resourceONTAPStorageVirtualMachineRead(ctx, d, meta)...) } -func resourceOntapStorageVirtualMachineRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPStorageVirtualMachineRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) @@ -290,38 +289,36 @@ func resourceOntapStorageVirtualMachineRead(ctx context.Context, d *schema.Resou return sdkdiag.AppendErrorf(diags, "reading FSx ONTAP Storage Virtual Machine (%s): %s", d.Id(), err) } + if err := d.Set("active_directory_configuration", flattenSvmActiveDirectoryConfiguration(d, storageVirtualMachine.ActiveDirectoryConfiguration)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting svm_active_directory: %s", err) + } d.Set("arn", storageVirtualMachine.ResourceARN) - d.Set("name", storageVirtualMachine.Name) + if err := d.Set("endpoints", flattenSvmEndpoints(storageVirtualMachine.Endpoints)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting endpoints: %s", err) + } d.Set("file_system_id", storageVirtualMachine.FileSystemId) - //RootVolumeSecurityStyle and SVMAdminPassword are write only properties so they don't get returned from the describe API so we just store the original setting to state + d.Set("name", storageVirtualMachine.Name) + // RootVolumeSecurityStyle and SVMAdminPassword are write only properties so they don't get returned from the describe API so we just store the original setting to state d.Set("root_volume_security_style", d.Get("root_volume_security_style").(string)) - d.Set("svm_admin_password", d.Get("svm_admin_password").(string)) d.Set("subtype", storageVirtualMachine.Subtype) + d.Set("svm_admin_password", d.Get("svm_admin_password").(string)) d.Set("uuid", storageVirtualMachine.UUID) - if err := d.Set("active_directory_configuration", flattenOntapSvmActiveDirectoryConfiguration(d, storageVirtualMachine.ActiveDirectoryConfiguration)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting svm_active_directory: %s", err) - } - - if err := d.Set("endpoints", flattenOntapStorageVirtualMachineEndpoints(storageVirtualMachine.Endpoints)); err != nil { - return sdkdiag.AppendErrorf(diags, "setting endpoints: %s", err) - } - return diags } -func resourceOntapStorageVirtualMachineUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPStorageVirtualMachineUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) - if d.HasChangesExcept("tags_all", "tags") { + if d.HasChangesExcept("tags", "tags_all") { input := &fsx.UpdateStorageVirtualMachineInput{ ClientRequestToken: aws.String(id.UniqueId()), StorageVirtualMachineId: aws.String(d.Id()), } if d.HasChange("active_directory_configuration") { - input.ActiveDirectoryConfiguration = expandOntapSvmActiveDirectoryConfigurationUpdate(d.Get("active_directory_configuration").([]interface{})) + input.ActiveDirectoryConfiguration = expandUpdateSvmActiveDirectoryConfiguration(d.Get("active_directory_configuration").([]interface{})) } if d.HasChange("svm_admin_password") { @@ -339,10 +336,10 @@ func resourceOntapStorageVirtualMachineUpdate(ctx context.Context, d *schema.Res } } - return append(diags, resourceOntapStorageVirtualMachineRead(ctx, d, meta)...) + return append(diags, resourceONTAPStorageVirtualMachineRead(ctx, d, meta)...) } -func resourceOntapStorageVirtualMachineDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceONTAPStorageVirtualMachineDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(*conns.AWSClient).FSxConn(ctx) @@ -366,7 +363,7 @@ func resourceOntapStorageVirtualMachineDelete(ctx context.Context, d *schema.Res return diags } -func expandOntapSvmActiveDirectoryConfigurationCreate(cfg []interface{}) *fsx.CreateSvmActiveDirectoryConfiguration { +func expandCreateSvmActiveDirectoryConfiguration(cfg []interface{}) *fsx.CreateSvmActiveDirectoryConfiguration { if len(cfg) < 1 { return nil } @@ -380,13 +377,13 @@ func expandOntapSvmActiveDirectoryConfigurationCreate(cfg []interface{}) *fsx.Cr } if v, ok := conf["self_managed_active_directory_configuration"].([]interface{}); ok { - out.SelfManagedActiveDirectoryConfiguration = expandOntapSvmSelfManagedActiveDirectoryConfiguration(v) + out.SelfManagedActiveDirectoryConfiguration = expandSelfManagedActiveDirectoryConfiguration(v) } return &out } -func expandOntapSvmSelfManagedActiveDirectoryConfiguration(cfg []interface{}) *fsx.SelfManagedActiveDirectoryConfiguration { +func expandSelfManagedActiveDirectoryConfiguration(cfg []interface{}) *fsx.SelfManagedActiveDirectoryConfiguration { if len(cfg) < 1 { return nil } @@ -422,7 +419,7 @@ func expandOntapSvmSelfManagedActiveDirectoryConfiguration(cfg []interface{}) *f return &out } -func expandOntapSvmActiveDirectoryConfigurationUpdate(cfg []interface{}) *fsx.UpdateSvmActiveDirectoryConfiguration { +func expandUpdateSvmActiveDirectoryConfiguration(cfg []interface{}) *fsx.UpdateSvmActiveDirectoryConfiguration { if len(cfg) < 1 { return nil } @@ -431,14 +428,18 @@ func expandOntapSvmActiveDirectoryConfigurationUpdate(cfg []interface{}) *fsx.Up out := fsx.UpdateSvmActiveDirectoryConfiguration{} + if v, ok := conf["netbios_name"].(string); ok && len(v) > 0 { + out.NetBiosName = aws.String(v) + } + if v, ok := conf["self_managed_active_directory_configuration"].([]interface{}); ok { - out.SelfManagedActiveDirectoryConfiguration = expandOntapSvmSelfManagedActiveDirectoryConfigurationUpdate(v) + out.SelfManagedActiveDirectoryConfiguration = expandSelfManagedActiveDirectoryConfigurationUpdates(v) } return &out } -func expandOntapSvmSelfManagedActiveDirectoryConfigurationUpdate(cfg []interface{}) *fsx.SelfManagedActiveDirectoryConfigurationUpdates { +func expandSelfManagedActiveDirectoryConfigurationUpdates(cfg []interface{}) *fsx.SelfManagedActiveDirectoryConfigurationUpdates { if len(cfg) < 1 { return nil } @@ -451,18 +452,30 @@ func expandOntapSvmSelfManagedActiveDirectoryConfigurationUpdate(cfg []interface out.DnsIps = flex.ExpandStringSet(v) } - if v, ok := conf["password"].(string); ok { + if v, ok := conf["domain_name"].(string); ok && len(v) > 0 { + out.DomainName = aws.String(v) + } + + if v, ok := conf["file_system_administrators_group"].(string); ok && len(v) > 0 { + out.FileSystemAdministratorsGroup = aws.String(v) + } + + if v, ok := conf["organizational_unit_distinguished_name"].(string); ok && len(v) > 0 { + out.OrganizationalUnitDistinguishedName = aws.String(v) + } + + if v, ok := conf["password"].(string); ok && len(v) > 0 { out.Password = aws.String(v) } - if v, ok := conf["username"].(string); ok { + if v, ok := conf["username"].(string); ok && len(v) > 0 { out.UserName = aws.String(v) } return &out } -func flattenOntapSvmActiveDirectoryConfiguration(d *schema.ResourceData, rs *fsx.SvmActiveDirectoryConfiguration) []interface{} { +func flattenSvmActiveDirectoryConfiguration(d *schema.ResourceData, rs *fsx.SvmActiveDirectoryConfiguration) []interface{} { if rs == nil { return []interface{}{} } @@ -473,13 +486,13 @@ func flattenOntapSvmActiveDirectoryConfiguration(d *schema.ResourceData, rs *fsx } if rs.SelfManagedActiveDirectoryConfiguration != nil { - m["self_managed_active_directory_configuration"] = flattenOntapSelfManagedActiveDirectoryConfiguration(d, rs.SelfManagedActiveDirectoryConfiguration) + m["self_managed_active_directory_configuration"] = flattenSelfManagedActiveDirectoryAttributes(d, rs.SelfManagedActiveDirectoryConfiguration) } return []interface{}{m} } -func flattenOntapSelfManagedActiveDirectoryConfiguration(d *schema.ResourceData, rs *fsx.SelfManagedActiveDirectoryAttributes) []interface{} { +func flattenSelfManagedActiveDirectoryAttributes(d *schema.ResourceData, rs *fsx.SelfManagedActiveDirectoryAttributes) []interface{} { if rs == nil { return []interface{}{} } @@ -493,10 +506,6 @@ func flattenOntapSelfManagedActiveDirectoryConfiguration(d *schema.ResourceData, m["domain_name"] = aws.StringValue(rs.DomainName) } - if rs.FileSystemAdministratorsGroup != nil { - m["file_system_administrators_group"] = aws.StringValue(rs.FileSystemAdministratorsGroup) - } - if rs.OrganizationalUnitDistinguishedName != nil { if _, ok := d.GetOk("active_directory_configuration.0.self_managed_active_directory_configuration.0.organizational_unit_distinguished_name"); ok { m["organizational_unit_distinguished_name"] = aws.StringValue(rs.OrganizationalUnitDistinguishedName) @@ -508,37 +517,38 @@ func flattenOntapSelfManagedActiveDirectoryConfiguration(d *schema.ResourceData, } // Since we are in a configuration block and the FSx API does not return - // the password, we need to set the value if we can or Terraform will - // show a difference for the argument from empty string to the value. + // the password or file_system_administrators_group, we need to set the values + // if we can or Terraform will show a difference for the argument from empty string to the value. // This is not a pattern that should be used normally. // See also: flattenEmrKerberosAttributes + m["file_system_administrators_group"] = d.Get("active_directory_configuration.0.self_managed_active_directory_configuration.0.file_system_administrators_group").(string) m["password"] = d.Get("active_directory_configuration.0.self_managed_active_directory_configuration.0.password").(string) return []interface{}{m} } -func flattenOntapStorageVirtualMachineEndpoints(rs *fsx.SvmEndpoints) []interface{} { +func flattenSvmEndpoints(rs *fsx.SvmEndpoints) []interface{} { if rs == nil { return []interface{}{} } m := make(map[string]interface{}) if rs.Iscsi != nil { - m["iscsi"] = flattenOntapStorageVirtualMachineEndpoint(rs.Iscsi) + m["iscsi"] = flattenSvmEndpoint(rs.Iscsi) } if rs.Management != nil { - m["management"] = flattenOntapStorageVirtualMachineEndpoint(rs.Management) + m["management"] = flattenSvmEndpoint(rs.Management) } if rs.Nfs != nil { - m["nfs"] = flattenOntapStorageVirtualMachineEndpoint(rs.Nfs) + m["nfs"] = flattenSvmEndpoint(rs.Nfs) } if rs.Smb != nil { - m["smb"] = flattenOntapStorageVirtualMachineEndpoint(rs.Smb) + m["smb"] = flattenSvmEndpoint(rs.Smb) } return []interface{}{m} } -func flattenOntapStorageVirtualMachineEndpoint(rs *fsx.SvmEndpoint) []interface{} { +func flattenSvmEndpoint(rs *fsx.SvmEndpoint) []interface{} { if rs == nil { return []interface{}{} } @@ -553,3 +563,134 @@ func flattenOntapStorageVirtualMachineEndpoint(rs *fsx.SvmEndpoint) []interface{ return []interface{}{m} } + +func FindStorageVirtualMachineByID(ctx context.Context, conn *fsx.FSx, id string) (*fsx.StorageVirtualMachine, error) { + input := &fsx.DescribeStorageVirtualMachinesInput{ + StorageVirtualMachineIds: []*string{aws.String(id)}, + } + + return findStorageVirtualMachine(ctx, conn, input, tfslices.PredicateTrue[*fsx.StorageVirtualMachine]()) +} + +func findStorageVirtualMachine(ctx context.Context, conn *fsx.FSx, input *fsx.DescribeStorageVirtualMachinesInput, filter tfslices.Predicate[*fsx.StorageVirtualMachine]) (*fsx.StorageVirtualMachine, error) { + output, err := findStorageVirtualMachines(ctx, conn, input, filter) + + if err != nil { + return nil, err + } + + return tfresource.AssertSinglePtrResult(output) +} + +func findStorageVirtualMachines(ctx context.Context, conn *fsx.FSx, input *fsx.DescribeStorageVirtualMachinesInput, filter tfslices.Predicate[*fsx.StorageVirtualMachine]) ([]*fsx.StorageVirtualMachine, error) { + var output []*fsx.StorageVirtualMachine + + err := conn.DescribeStorageVirtualMachinesPagesWithContext(ctx, input, func(page *fsx.DescribeStorageVirtualMachinesOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.StorageVirtualMachines { + if v != nil && filter(v) { + output = append(output, v) + } + } + + return !lastPage + }) + + if tfawserr.ErrCodeEquals(err, fsx.ErrCodeStorageVirtualMachineNotFound) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + return output, nil +} + +func statusStorageVirtualMachine(ctx context.Context, conn *fsx.FSx, id string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := FindStorageVirtualMachineByID(ctx, conn, id) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return output, aws.StringValue(output.Lifecycle), nil + } +} + +func waitStorageVirtualMachineCreated(ctx context.Context, conn *fsx.FSx, id string, timeout time.Duration) (*fsx.StorageVirtualMachine, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{fsx.StorageVirtualMachineLifecycleCreating, fsx.StorageVirtualMachineLifecyclePending}, + Target: []string{fsx.StorageVirtualMachineLifecycleCreated, fsx.StorageVirtualMachineLifecycleMisconfigured}, + Refresh: statusStorageVirtualMachine(ctx, conn, id), + Timeout: timeout, + Delay: 30 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*fsx.StorageVirtualMachine); ok { + if reason := output.LifecycleTransitionReason; reason != nil { + tfresource.SetLastError(err, errors.New(aws.StringValue(reason.Message))) + } + + return output, err + } + + return nil, err +} + +func waitStorageVirtualMachineUpdated(ctx context.Context, conn *fsx.FSx, id string, timeout time.Duration) (*fsx.StorageVirtualMachine, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{fsx.StorageVirtualMachineLifecyclePending}, + Target: []string{fsx.StorageVirtualMachineLifecycleCreated, fsx.StorageVirtualMachineLifecycleMisconfigured}, + Refresh: statusStorageVirtualMachine(ctx, conn, id), + Timeout: timeout, + Delay: 30 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*fsx.StorageVirtualMachine); ok { + if reason := output.LifecycleTransitionReason; reason != nil { + tfresource.SetLastError(err, errors.New(aws.StringValue(reason.Message))) + } + + return output, err + } + + return nil, err +} + +func waitStorageVirtualMachineDeleted(ctx context.Context, conn *fsx.FSx, id string, timeout time.Duration) (*fsx.StorageVirtualMachine, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{fsx.StorageVirtualMachineLifecycleCreated, fsx.StorageVirtualMachineLifecycleDeleting}, + Target: []string{}, + Refresh: statusStorageVirtualMachine(ctx, conn, id), + Timeout: timeout, + Delay: 30 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*fsx.StorageVirtualMachine); ok { + if reason := output.LifecycleTransitionReason; reason != nil { + tfresource.SetLastError(err, errors.New(aws.StringValue(reason.Message))) + } + + return output, err + } + + return nil, err +} diff --git a/internal/service/fsx/ontap_storage_virtual_machine_migrate.go b/internal/service/fsx/ontap_storage_virtual_machine_migrate.go index f4ff73432372..6df182278438 100644 --- a/internal/service/fsx/ontap_storage_virtual_machine_migrate.go +++ b/internal/service/fsx/ontap_storage_virtual_machine_migrate.go @@ -15,7 +15,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func ResourceOntapStorageVirtualMachineV0() *schema.Resource { +func ResourceONTAPStorageVirtualMachineV0() *schema.Resource { return &schema.Resource{ SchemaVersion: 0, Schema: map[string]*schema.Schema{ @@ -210,7 +210,7 @@ func ResourceOntapStorageVirtualMachineV0() *schema.Resource { } } -func ResourceOntapStorageVirtualMachineStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { +func ResourceONTAPStorageVirtualMachineStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { log.Printf("[DEBUG] Attributes before migration: %#v", rawState) rawState["active_directory_configuration.0.self_managed_active_directory_configuration.0.organizational_unit_distinguished_name"] = rawState["active_directory_configuration.0.self_managed_active_directory_configuration.0.organizational_unit_distinguidshed_name"] diff --git a/internal/service/fsx/ontap_storage_virtual_machine_migrate_test.go b/internal/service/fsx/ontap_storage_virtual_machine_migrate_test.go index 4e03b1f8518d..e6056558a577 100644 --- a/internal/service/fsx/ontap_storage_virtual_machine_migrate_test.go +++ b/internal/service/fsx/ontap_storage_virtual_machine_migrate_test.go @@ -29,7 +29,7 @@ func TestOntapStorageVirtualMachineStateUpgradeV0(t *testing.T) { t.Parallel() expected := testOntapStorageVirtualMachineStateDataV1() - actual, err := tffsx.ResourceOntapStorageVirtualMachineStateUpgradeV0(ctx, testOntapStorageVirtualMachineStateDataV0(), nil) + actual, err := tffsx.ResourceONTAPStorageVirtualMachineStateUpgradeV0(ctx, testOntapStorageVirtualMachineStateDataV0(), nil) if err != nil { t.Fatalf("error migrating state: %s", err) diff --git a/internal/service/fsx/ontap_storage_virtual_machine_test.go b/internal/service/fsx/ontap_storage_virtual_machine_test.go index 653ece822924..b86c9c9648df 100644 --- a/internal/service/fsx/ontap_storage_virtual_machine_test.go +++ b/internal/service/fsx/ontap_storage_virtual_machine_test.go @@ -21,7 +21,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" ) -func TestAccFSxOntapStorageVirtualMachine_basic(t *testing.T) { +func TestAccFSxONTAPStorageVirtualMachine_basic(t *testing.T) { ctx := acctest.Context(t) var storageVirtualMachine fsx.StorageVirtualMachine resourceName := "aws_fsx_ontap_storage_virtual_machine.test" @@ -31,12 +31,12 @@ func TestAccFSxOntapStorageVirtualMachine_basic(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapStorageVirtualMachineDestroy(ctx), + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPStorageVirtualMachineConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "fsx", regexache.MustCompile(`storage-virtual-machine/fs-.+`)), resource.TestCheckResourceAttr(resourceName, "endpoints.#", "1"), resource.TestCheckResourceAttr(resourceName, "endpoints.0.iscsi.#", "1"), @@ -61,7 +61,7 @@ func TestAccFSxOntapStorageVirtualMachine_basic(t *testing.T) { }) } -func TestAccFSxOntapStorageVirtualMachine_rootVolumeSecurityStyle(t *testing.T) { +func TestAccFSxONTAPStorageVirtualMachine_rootVolumeSecurityStyle(t *testing.T) { ctx := acctest.Context(t) var storageVirtualMachine fsx.StorageVirtualMachine resourceName := "aws_fsx_ontap_storage_virtual_machine.test" @@ -71,12 +71,12 @@ func TestAccFSxOntapStorageVirtualMachine_rootVolumeSecurityStyle(t *testing.T) PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapStorageVirtualMachineDestroy(ctx), + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPStorageVirtualMachineConfig_rootVolumeSecurityStyle(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "fsx", regexache.MustCompile(`storage-virtual-machine/fs-.+`)), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), resource.TestCheckResourceAttr(resourceName, "endpoints.#", "1"), @@ -99,7 +99,7 @@ func TestAccFSxOntapStorageVirtualMachine_rootVolumeSecurityStyle(t *testing.T) }) } -func TestAccFSxOntapStorageVirtualMachine_svmAdminPassword(t *testing.T) { +func TestAccFSxONTAPStorageVirtualMachine_svmAdminPassword(t *testing.T) { ctx := acctest.Context(t) var storageVirtualMachine1, storageVirtualMachine2 fsx.StorageVirtualMachine resourceName := "aws_fsx_ontap_storage_virtual_machine.test" @@ -111,12 +111,12 @@ func TestAccFSxOntapStorageVirtualMachine_svmAdminPassword(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapStorageVirtualMachineDestroy(ctx), + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPStorageVirtualMachineConfig_svmAdminPassword(rName, pass1), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), resource.TestCheckResourceAttr(resourceName, "svm_admin_password", pass1), ), }, @@ -129,8 +129,8 @@ func TestAccFSxOntapStorageVirtualMachine_svmAdminPassword(t *testing.T) { { Config: testAccONTAPStorageVirtualMachineConfig_svmAdminPassword(rName, pass2), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine2), - testAccCheckOntapStorageVirtualMachineNotRecreated(&storageVirtualMachine1, &storageVirtualMachine2), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine2), + testAccCheckONTAPStorageVirtualMachineNotRecreated(&storageVirtualMachine1, &storageVirtualMachine2), resource.TestCheckResourceAttr(resourceName, "svm_admin_password", pass2), ), }, @@ -138,7 +138,7 @@ func TestAccFSxOntapStorageVirtualMachine_svmAdminPassword(t *testing.T) { }) } -func TestAccFSxOntapStorageVirtualMachine_disappears(t *testing.T) { +func TestAccFSxONTAPStorageVirtualMachine_disappears(t *testing.T) { ctx := acctest.Context(t) var storageVirtualMachine fsx.StorageVirtualMachine resourceName := "aws_fsx_ontap_storage_virtual_machine.test" @@ -148,13 +148,13 @@ func TestAccFSxOntapStorageVirtualMachine_disappears(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapStorageVirtualMachineDestroy(ctx), + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPStorageVirtualMachineConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine), - acctest.CheckResourceDisappears(ctx, acctest.Provider, tffsx.ResourceOntapStorageVirtualMachine(), resourceName), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tffsx.ResourceONTAPStorageVirtualMachine(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -162,7 +162,7 @@ func TestAccFSxOntapStorageVirtualMachine_disappears(t *testing.T) { }) } -func TestAccFSxOntapStorageVirtualMachine_name(t *testing.T) { +func TestAccFSxONTAPStorageVirtualMachine_name(t *testing.T) { ctx := acctest.Context(t) var storageVirtualMachine1, storageVirtualMachine2 fsx.StorageVirtualMachine resourceName := "aws_fsx_ontap_storage_virtual_machine.test" @@ -173,12 +173,12 @@ func TestAccFSxOntapStorageVirtualMachine_name(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapStorageVirtualMachineDestroy(ctx), + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPStorageVirtualMachineConfig_basic(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), resource.TestCheckResourceAttr(resourceName, "name", rName), ), }, @@ -190,8 +190,8 @@ func TestAccFSxOntapStorageVirtualMachine_name(t *testing.T) { { Config: testAccONTAPStorageVirtualMachineConfig_basic(rName2), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine2), - testAccCheckOntapStorageVirtualMachineRecreated(&storageVirtualMachine1, &storageVirtualMachine2), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine2), + testAccCheckONTAPStorageVirtualMachineRecreated(&storageVirtualMachine1, &storageVirtualMachine2), resource.TestCheckResourceAttr(resourceName, "name", rName2), ), }, @@ -199,7 +199,7 @@ func TestAccFSxOntapStorageVirtualMachine_name(t *testing.T) { }) } -func TestAccFSxOntapStorageVirtualMachine_tags(t *testing.T) { +func TestAccFSxONTAPStorageVirtualMachine_tags(t *testing.T) { ctx := acctest.Context(t) var storageVirtualMachine1, storageVirtualMachine2, storageVirtualMachine3 fsx.StorageVirtualMachine resourceName := "aws_fsx_ontap_storage_virtual_machine.test" @@ -209,12 +209,12 @@ func TestAccFSxOntapStorageVirtualMachine_tags(t *testing.T) { PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapStorageVirtualMachineDestroy(ctx), + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccONTAPStorageVirtualMachineConfig_tags1(rName, "key1", "value1"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), @@ -227,8 +227,8 @@ func TestAccFSxOntapStorageVirtualMachine_tags(t *testing.T) { { Config: testAccONTAPStorageVirtualMachineConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine2), - testAccCheckOntapStorageVirtualMachineNotRecreated(&storageVirtualMachine1, &storageVirtualMachine2), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine2), + testAccCheckONTAPStorageVirtualMachineNotRecreated(&storageVirtualMachine1, &storageVirtualMachine2), resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), @@ -237,8 +237,8 @@ func TestAccFSxOntapStorageVirtualMachine_tags(t *testing.T) { { Config: testAccONTAPStorageVirtualMachineConfig_tags1(rName, "key2", "value2"), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine3), - testAccCheckOntapStorageVirtualMachineNotRecreated(&storageVirtualMachine2, &storageVirtualMachine3), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine3), + testAccCheckONTAPStorageVirtualMachineNotRecreated(&storageVirtualMachine2, &storageVirtualMachine3), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), ), @@ -247,33 +247,35 @@ func TestAccFSxOntapStorageVirtualMachine_tags(t *testing.T) { }) } -func TestAccFSxOntapStorageVirtualMachine_activeDirectory(t *testing.T) { +func TestAccFSxONTAPStorageVirtualMachine_activeDirectoryCreate(t *testing.T) { ctx := acctest.Context(t) - var storageVirtualMachine1 fsx.StorageVirtualMachine + var storageVirtualMachine fsx.StorageVirtualMachine resourceName := "aws_fsx_ontap_storage_virtual_machine.test" rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) netBiosName := "tftest-" + sdkacctest.RandString(7) - domainNetbiosName := "tftestcorp" - domainName := "tftestcorp.local" - domainPassword1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + domainNetbiosName := "tftest" + sdkacctest.RandString(4) + domainName := domainNetbiosName + ".local" + domainPassword := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckOntapStorageVirtualMachineDestroy(ctx), + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccONTAPStorageVirtualMachineConfig_virutalSelfManagedActiveDirectory(rName, netBiosName, domainNetbiosName, domainName, domainPassword1), + Config: testAccONTAPStorageVirtualMachineConfig_selfManagedActiveDirectory(rName, netBiosName, domainNetbiosName, domainName, domainPassword), Check: resource.ComposeTestCheckFunc( - testAccCheckOntapStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine), resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.netbios_name", strings.ToUpper(netBiosName)), resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.domain_name", domainName), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.file_system_administrators_group", "Admins"), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.organizational_unit_distinguished_name", fmt.Sprintf("OU=computers,OU=%s", domainNetbiosName)), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.password", domainPassword), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.username", "Admin"), resource.TestCheckResourceAttr(resourceName, "endpoints.0.smb.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "endpoints.0.smb.0.dns_name"), - resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.organizational_unit_distinguished_name", fmt.Sprintf("OU=computers,OU=%s", domainNetbiosName)), - resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.password", domainPassword1), ), }, { @@ -288,31 +290,69 @@ func TestAccFSxOntapStorageVirtualMachine_activeDirectory(t *testing.T) { }) } -func testAccCheckOntapStorageVirtualMachineExists(ctx context.Context, resourceName string, svm *fsx.StorageVirtualMachine) resource.TestCheckFunc { +func TestAccFSxONTAPStorageVirtualMachine_activeDirectoryJoin(t *testing.T) { + ctx := acctest.Context(t) + var storageVirtualMachine1, storageVirtualMachine2 fsx.StorageVirtualMachine + resourceName := "aws_fsx_ontap_storage_virtual_machine.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + netBiosName := "tftest-" + sdkacctest.RandString(7) + domainNetbiosName := "tftest" + sdkacctest.RandString(4) + domainName := domainNetbiosName + ".local" + domainPassword := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, fsx.EndpointsID) }, + ErrorCheck: acctest.ErrorCheck(t, fsx.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckONTAPStorageVirtualMachineDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccONTAPStorageVirtualMachineConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine1), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.#", "0"), + ), + }, + { + Config: testAccONTAPStorageVirtualMachineConfig_selfManagedActiveDirectory(rName, netBiosName, domainNetbiosName, domainName, domainPassword), + Check: resource.ComposeTestCheckFunc( + testAccCheckONTAPStorageVirtualMachineExists(ctx, resourceName, &storageVirtualMachine2), + testAccCheckONTAPStorageVirtualMachineNotRecreated(&storageVirtualMachine1, &storageVirtualMachine2), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.#", "1"), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.netbios_name", netBiosName), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.domain_name", domainName), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.file_system_administrators_group", "Admins"), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.organizational_unit_distinguished_name", fmt.Sprintf("OU=computers,OU=%s", domainNetbiosName)), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.password", domainPassword), + resource.TestCheckResourceAttr(resourceName, "active_directory_configuration.0.self_managed_active_directory_configuration.0.username", "Admin"), + ), + }, + }, + }) +} + +func testAccCheckONTAPStorageVirtualMachineExists(ctx context.Context, n string, v *fsx.StorageVirtualMachine) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", resourceName) + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).FSxConn(ctx) - storageVirtualMachine, err := tffsx.FindStorageVirtualMachineByID(ctx, conn, rs.Primary.ID) + output, err := tffsx.FindStorageVirtualMachineByID(ctx, conn, rs.Primary.ID) + if err != nil { return err } - if storageVirtualMachine == nil { - return fmt.Errorf("FSx ONTAP Storage Virtual Machine (%s) not found", rs.Primary.ID) - } - - *svm = *storageVirtualMachine + *v = *output return nil } } -func testAccCheckOntapStorageVirtualMachineDestroy(ctx context.Context) resource.TestCheckFunc { +func testAccCheckONTAPStorageVirtualMachineDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).FSxConn(ctx) @@ -321,77 +361,47 @@ func testAccCheckOntapStorageVirtualMachineDestroy(ctx context.Context) resource continue } - storageVirtualMachine, err := tffsx.FindStorageVirtualMachineByID(ctx, conn, rs.Primary.ID) + _, err := tffsx.FindStorageVirtualMachineByID(ctx, conn, rs.Primary.ID) + if tfresource.NotFound(err) { continue } - if storageVirtualMachine != nil { - return fmt.Errorf("FSx ONTAP Storage Virtual Machine (%s) still exists", rs.Primary.ID) - } + return fmt.Errorf("FSx ONTAP Storage Virtual Machine (%s) still exists", rs.Primary.ID) } + return nil } } -func testAccCheckOntapStorageVirtualMachineNotRecreated(i, j *fsx.StorageVirtualMachine) resource.TestCheckFunc { +func testAccCheckONTAPStorageVirtualMachineNotRecreated(i, j *fsx.StorageVirtualMachine) resource.TestCheckFunc { return func(s *terraform.State) error { if aws.StringValue(i.StorageVirtualMachineId) != aws.StringValue(j.StorageVirtualMachineId) { - return fmt.Errorf("FSx Storage Virtual Machine (%s) recreated", aws.StringValue(i.StorageVirtualMachineId)) + return fmt.Errorf("FSx ONTAP Storage Virtual Machine (%s) recreated", aws.StringValue(i.StorageVirtualMachineId)) } return nil } } -func testAccCheckOntapStorageVirtualMachineRecreated(i, j *fsx.StorageVirtualMachine) resource.TestCheckFunc { +func testAccCheckONTAPStorageVirtualMachineRecreated(i, j *fsx.StorageVirtualMachine) resource.TestCheckFunc { return func(s *terraform.State) error { if aws.StringValue(i.StorageVirtualMachineId) == aws.StringValue(j.StorageVirtualMachineId) { - return fmt.Errorf("FSx Storage Virtual Machine (%s) not recreated", aws.StringValue(i.StorageVirtualMachineId)) + return fmt.Errorf("FSx ONTAP Storage Virtual Machine (%s) not recreated", aws.StringValue(i.StorageVirtualMachineId)) } return nil } } -func testAccOntapStorageVirtualMachineBaseConfig(rName string) string { - return acctest.ConfigCompose(acctest.ConfigAvailableAZsNoOptIn(), fmt.Sprintf(` -data "aws_partition" "current" {} - -resource "aws_vpc" "test" { - cidr_block = "10.0.0.0/16" - - tags = { - Name = %[1]q - } -} - -resource "aws_subnet" "test1" { - vpc_id = aws_vpc.test.id - cidr_block = "10.0.1.0/24" - availability_zone = data.aws_availability_zones.available.names[0] - - tags = { - Name = %[1]q - } -} - -resource "aws_subnet" "test2" { - vpc_id = aws_vpc.test.id - cidr_block = "10.0.2.0/24" - availability_zone = data.aws_availability_zones.available.names[1] - - tags = { - Name = %[1]q - } -} - +func testAccONTAPStorageVirtualMachineConfig_base(rName string) string { + return acctest.ConfigCompose(testAccONTAPFileSystemConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_file_system" "test" { storage_capacity = 1024 - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id deployment_type = "MULTI_AZ_1" throughput_capacity = 512 - preferred_subnet_id = aws_subnet.test1.id + preferred_subnet_id = aws_subnet.test[0].id tags = { Name = %[1]q @@ -400,25 +410,24 @@ resource "aws_fsx_ontap_file_system" "test" { `, rName)) } -func testAccOntapStorageVirtualMachineADConfig(rName string, domainName string, domainPassword string) string { - return acctest.ConfigCompose(testAccOntapStorageVirtualMachineBaseConfig(rName), fmt.Sprintf(` - +func testAccONTAPStorageVirtualMachineADConfig_base(rName, domainName, domainPassword string) string { + return acctest.ConfigCompose(testAccONTAPStorageVirtualMachineConfig_base(rName), fmt.Sprintf(` resource "aws_directory_service_directory" "test" { edition = "Standard" - name = %[2]q - password = %[3]q + name = %[1]q + password = %[2]q type = "MicrosoftAD" vpc_settings { - subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + subnet_ids = aws_subnet.test[*].id vpc_id = aws_vpc.test.id } } -`, rName, domainName, domainPassword)) +`, domainName, domainPassword)) } func testAccONTAPStorageVirtualMachineConfig_basic(rName string) string { - return acctest.ConfigCompose(testAccOntapStorageVirtualMachineBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPStorageVirtualMachineConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_storage_virtual_machine" "test" { file_system_id = aws_fsx_ontap_file_system.test.id name = %[1]q @@ -427,7 +436,7 @@ resource "aws_fsx_ontap_storage_virtual_machine" "test" { } func testAccONTAPStorageVirtualMachineConfig_rootVolumeSecurityStyle(rName string) string { - return acctest.ConfigCompose(testAccOntapStorageVirtualMachineBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPStorageVirtualMachineConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_storage_virtual_machine" "test" { file_system_id = aws_fsx_ontap_file_system.test.id name = %[1]q @@ -436,8 +445,8 @@ resource "aws_fsx_ontap_storage_virtual_machine" "test" { `, rName)) } -func testAccONTAPStorageVirtualMachineConfig_svmAdminPassword(rName string, pass string) string { - return acctest.ConfigCompose(testAccOntapStorageVirtualMachineBaseConfig(rName), fmt.Sprintf(` +func testAccONTAPStorageVirtualMachineConfig_svmAdminPassword(rName, pass string) string { + return acctest.ConfigCompose(testAccONTAPStorageVirtualMachineConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_storage_virtual_machine" "test" { file_system_id = aws_fsx_ontap_file_system.test.id name = %[1]q @@ -447,7 +456,7 @@ resource "aws_fsx_ontap_storage_virtual_machine" "test" { } func testAccONTAPStorageVirtualMachineConfig_tags1(rName, tagKey1, tagValue1 string) string { - return acctest.ConfigCompose(testAccOntapStorageVirtualMachineBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPStorageVirtualMachineConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_storage_virtual_machine" "test" { file_system_id = aws_fsx_ontap_file_system.test.id name = %[1]q @@ -460,7 +469,7 @@ resource "aws_fsx_ontap_storage_virtual_machine" "test" { } func testAccONTAPStorageVirtualMachineConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { - return acctest.ConfigCompose(testAccOntapStorageVirtualMachineBaseConfig(rName), fmt.Sprintf(` + return acctest.ConfigCompose(testAccONTAPStorageVirtualMachineConfig_base(rName), fmt.Sprintf(` resource "aws_fsx_ontap_storage_virtual_machine" "test" { file_system_id = aws_fsx_ontap_file_system.test.id name = %[1]q @@ -473,8 +482,8 @@ resource "aws_fsx_ontap_storage_virtual_machine" "test" { `, rName, tagKey1, tagValue1, tagKey2, tagValue2)) } -func testAccONTAPStorageVirtualMachineConfig_virutalSelfManagedActiveDirectory(rName string, netBiosName string, domainNetbiosName string, domainName string, domainPassword string) string { - return acctest.ConfigCompose(testAccOntapStorageVirtualMachineADConfig(rName, domainName, domainPassword), fmt.Sprintf(` +func testAccONTAPStorageVirtualMachineConfig_selfManagedActiveDirectory(rName, netBiosName, domainNetbiosName, domainName, domainPassword string) string { + return acctest.ConfigCompose(testAccONTAPStorageVirtualMachineADConfig_base(rName, domainName, domainPassword), fmt.Sprintf(` resource "aws_fsx_ontap_storage_virtual_machine" "test" { file_system_id = aws_fsx_ontap_file_system.test.id name = %[1]q @@ -488,6 +497,7 @@ resource "aws_fsx_ontap_storage_virtual_machine" "test" { password = %[4]q username = "Admin" organizational_unit_distinguished_name = "OU=computers,OU=%[5]s" + file_system_administrators_group = "Admins" } } } diff --git a/internal/service/fsx/service_package_gen.go b/internal/service/fsx/service_package_gen.go index 20bade3c119b..39d013f49d7a 100644 --- a/internal/service/fsx/service_package_gen.go +++ b/internal/service/fsx/service_package_gen.go @@ -71,7 +71,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceOntapFileSystem, + Factory: ResourceONTAPFileSystem, TypeName: "aws_fsx_ontap_file_system", Name: "ONTAP File System", Tags: &types.ServicePackageResourceTags{ @@ -79,7 +79,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceOntapStorageVirtualMachine, + Factory: ResourceONTAPStorageVirtualMachine, TypeName: "aws_fsx_ontap_storage_virtual_machine", Name: "ONTAP Storage Virtual Machine", Tags: &types.ServicePackageResourceTags{ diff --git a/internal/service/fsx/status.go b/internal/service/fsx/status.go index 4d660ea59754..5ffe34db1056 100644 --- a/internal/service/fsx/status.go +++ b/internal/service/fsx/status.go @@ -43,22 +43,6 @@ func statusFileCache(ctx context.Context, conn *fsx.FSx, id string) retry.StateR } } -func statusStorageVirtualMachine(ctx context.Context, conn *fsx.FSx, id string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - output, err := FindStorageVirtualMachineByID(ctx, conn, id) - - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - return output, aws.StringValue(output.Lifecycle), nil - } -} - func statusVolume(ctx context.Context, conn *fsx.FSx, id string) retry.StateRefreshFunc { return func() (interface{}, string, error) { output, err := FindVolumeByID(ctx, conn, id) diff --git a/internal/service/fsx/sweep.go b/internal/service/fsx/sweep.go index 3cda7b30059c..7fe2bd1681cc 100644 --- a/internal/service/fsx/sweep.go +++ b/internal/service/fsx/sweep.go @@ -33,7 +33,7 @@ func init() { resource.AddTestSweepers("aws_fsx_ontap_file_system", &resource.Sweeper{ Name: "aws_fsx_ontap_file_system", - F: sweepOntapFileSystems, + F: sweepONTAPFileSystems, Dependencies: []string{ "aws_datasync_location", "aws_fsx_ontap_storage_virtual_machine", @@ -42,7 +42,7 @@ func init() { resource.AddTestSweepers("aws_fsx_ontap_storage_virtual_machine", &resource.Sweeper{ Name: "aws_fsx_ontap_storage_virtual_machine", - F: sweepOntapStorageVirtualMachine, + F: sweepONTAPStorageVirtualMachine, Dependencies: []string{ "aws_fsx_ontap_volume", }, @@ -50,7 +50,7 @@ func init() { resource.AddTestSweepers("aws_fsx_ontap_volume", &resource.Sweeper{ Name: "aws_fsx_ontap_volume", - F: sweepOntapVolume, + F: sweepONTAPVolumes, }) resource.AddTestSweepers("aws_fsx_openzfs_file_system", &resource.Sweeper{ @@ -171,7 +171,7 @@ func sweepLustreFileSystems(region string) error { return errs.ErrorOrNil() } -func sweepOntapFileSystems(region string) error { +func sweepONTAPFileSystems(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) @@ -194,7 +194,7 @@ func sweepOntapFileSystems(region string) error { continue } - r := ResourceOntapFileSystem() + r := ResourceONTAPFileSystem() d := r.Data(nil) d.SetId(aws.StringValue(fs.FileSystemId)) @@ -220,7 +220,7 @@ func sweepOntapFileSystems(region string) error { return errs.ErrorOrNil() } -func sweepOntapStorageVirtualMachine(region string) error { +func sweepONTAPStorageVirtualMachine(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) @@ -239,7 +239,7 @@ func sweepOntapStorageVirtualMachine(region string) error { } for _, vm := range page.StorageVirtualMachines { - r := ResourceOntapStorageVirtualMachine() + r := ResourceONTAPStorageVirtualMachine() d := r.Data(nil) d.SetId(aws.StringValue(vm.StorageVirtualMachineId)) @@ -265,7 +265,7 @@ func sweepOntapStorageVirtualMachine(region string) error { return errs.ErrorOrNil() } -func sweepOntapVolume(region string) error { +func sweepONTAPVolumes(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) diff --git a/internal/service/fsx/wait.go b/internal/service/fsx/wait.go index 035dc743875d..86cab76105c1 100644 --- a/internal/service/fsx/wait.go +++ b/internal/service/fsx/wait.go @@ -115,72 +115,6 @@ func waitFileCacheDeleted(ctx context.Context, conn *fsx.FSx, id string, timeout return nil, err } -func waitStorageVirtualMachineCreated(ctx context.Context, conn *fsx.FSx, id string, timeout time.Duration) (*fsx.StorageVirtualMachine, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{fsx.StorageVirtualMachineLifecycleCreating, fsx.StorageVirtualMachineLifecyclePending}, - Target: []string{fsx.StorageVirtualMachineLifecycleCreated, fsx.StorageVirtualMachineLifecycleMisconfigured}, - Refresh: statusStorageVirtualMachine(ctx, conn, id), - Timeout: timeout, - Delay: 30 * time.Second, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*fsx.StorageVirtualMachine); ok { - if status, details := aws.StringValue(output.Lifecycle), output.LifecycleTransitionReason; status == fsx.FileSystemLifecycleFailed && details != nil { - tfresource.SetLastError(err, errors.New(aws.StringValue(output.LifecycleTransitionReason.Message))) - } - - return output, err - } - - return nil, err -} - -func waitStorageVirtualMachineUpdated(ctx context.Context, conn *fsx.FSx, id string, timeout time.Duration) (*fsx.StorageVirtualMachine, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{fsx.StorageVirtualMachineLifecyclePending}, - Target: []string{fsx.StorageVirtualMachineLifecycleCreated, fsx.StorageVirtualMachineLifecycleMisconfigured}, - Refresh: statusStorageVirtualMachine(ctx, conn, id), - Timeout: timeout, - Delay: 30 * time.Second, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*fsx.StorageVirtualMachine); ok { - if status, details := aws.StringValue(output.Lifecycle), output.LifecycleTransitionReason; status == fsx.FileSystemLifecycleFailed && details != nil { - tfresource.SetLastError(err, errors.New(aws.StringValue(output.LifecycleTransitionReason.Message))) - } - - return output, err - } - - return nil, err -} - -func waitStorageVirtualMachineDeleted(ctx context.Context, conn *fsx.FSx, id string, timeout time.Duration) (*fsx.StorageVirtualMachine, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{fsx.StorageVirtualMachineLifecycleCreated, fsx.StorageVirtualMachineLifecycleDeleting}, - Target: []string{}, - Refresh: statusStorageVirtualMachine(ctx, conn, id), - Timeout: timeout, - Delay: 30 * time.Second, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*fsx.StorageVirtualMachine); ok { - if status, details := aws.StringValue(output.Lifecycle), output.LifecycleTransitionReason; status == fsx.StorageVirtualMachineLifecycleFailed && details != nil { - tfresource.SetLastError(err, errors.New(aws.StringValue(output.LifecycleTransitionReason.Message))) - } - - return output, err - } - - return nil, err -} - func waitVolumeCreated(ctx context.Context, conn *fsx.FSx, id string, timeout time.Duration) (*fsx.Volume, error) { //nolint:unparam stateConf := &retry.StateChangeConf{ Pending: []string{fsx.VolumeLifecycleCreating, fsx.VolumeLifecyclePending}, diff --git a/internal/service/fsx/windows_file_system.go b/internal/service/fsx/windows_file_system.go index 63a07e0e25dd..bb6f3189d8c2 100644 --- a/internal/service/fsx/windows_file_system.go +++ b/internal/service/fsx/windows_file_system.go @@ -534,6 +534,10 @@ func resourceWindowsFileSystemUpdate(ctx context.Context, d *schema.ResourceData if _, err := waitFileSystemUpdated(ctx, conn, d.Id(), startTime, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for FSx Windows File Server File System (%s) update: %s", d.Id(), err) } + + if _, err := waitAdministrativeActionCompleted(ctx, conn, d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, d.Timeout(schema.TimeoutUpdate)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for FSx Windows File Server File System (%s) administrative action (%s) complete: %s", d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, err) + } } } @@ -586,6 +590,10 @@ func resourceWindowsFileSystemUpdate(ctx context.Context, d *schema.ResourceData if _, err := waitFileSystemUpdated(ctx, conn, d.Id(), startTime, d.Timeout(schema.TimeoutUpdate)); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for FSx Windows File Server File System (%s) update: %s", d.Id(), err) } + + if _, err := waitAdministrativeActionCompleted(ctx, conn, d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, d.Timeout(schema.TimeoutUpdate)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for FSx Windows File Server File System (%s) administrative action (%s) complete: %s", d.Id(), fsx.AdministrativeActionTypeFileSystemUpdate, err) + } } return append(diags, resourceWindowsFileSystemRead(ctx, d, meta)...) diff --git a/internal/service/fsx/windows_file_system_test.go b/internal/service/fsx/windows_file_system_test.go index 294ec8c75dc0..3f92c89a730e 100644 --- a/internal/service/fsx/windows_file_system_test.go +++ b/internal/service/fsx/windows_file_system_test.go @@ -885,6 +885,7 @@ func testAccCheckWindowsFileSystemDestroy(ctx context.Context) resource.TestChec return fmt.Errorf("FSx for Windows File Server File System (%s) still exists", rs.Primary.ID) } + return nil } } diff --git a/internal/service/kms/sweep.go b/internal/service/kms/sweep.go index 61710943837f..06338ae75964 100644 --- a/internal/service/kms/sweep.go +++ b/internal/service/kms/sweep.go @@ -75,7 +75,7 @@ func sweepKeys(region string) error { d := r.Data(nil) d.SetId(keyID) d.Set("key_id", keyID) - d.Set("deletion_window_in_days", "7") + d.Set("deletion_window_in_days", 7) sweepResources = append(sweepResources, sdk.NewSweepResource(r, d, client)) } diff --git a/internal/service/logs/group.go b/internal/service/logs/group.go index 0b26749899ad..3f1ecee3cc78 100644 --- a/internal/service/logs/group.go +++ b/internal/service/logs/group.go @@ -6,6 +6,7 @@ package logs import ( "context" "log" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" @@ -218,9 +219,11 @@ func resourceGroupDelete(ctx context.Context, d *schema.ResourceData, meta inter conn := meta.(*conns.AWSClient).LogsConn(ctx) log.Printf("[INFO] Deleting CloudWatch Logs Log Group: %s", d.Id()) - _, err := conn.DeleteLogGroupWithContext(ctx, &cloudwatchlogs.DeleteLogGroupInput{ - LogGroupName: aws.String(d.Id()), - }) + _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, 1*time.Minute, func() (interface{}, error) { + return conn.DeleteLogGroupWithContext(ctx, &cloudwatchlogs.DeleteLogGroupInput{ + LogGroupName: aws.String(d.Id()), + }) + }, cloudwatchlogs.ErrCodeOperationAbortedException, "try again") if tfawserr.ErrCodeEquals(err, cloudwatchlogs.ErrCodeResourceNotFoundException) { return nil diff --git a/internal/service/quicksight/sweep.go b/internal/service/quicksight/sweep.go index ef169af6fc56..362b13150008 100644 --- a/internal/service/quicksight/sweep.go +++ b/internal/service/quicksight/sweep.go @@ -363,6 +363,9 @@ func skipSweepUserError(err error) bool { if tfawserr.ErrMessageContains(err, quicksight.ErrCodeResourceNotFoundException, "not signed up with QuickSight") { return true } + if tfawserr.ErrMessageContains(err, quicksight.ErrCodeResourceNotFoundException, "Namespace default not found in account") { + return true + } return sweep.SkipSweepError(err) diff --git a/internal/service/ssm/patch_group.go b/internal/service/ssm/patch_group.go index e5f26c6d4522..f22e42f9ec9c 100644 --- a/internal/service/ssm/patch_group.go +++ b/internal/service/ssm/patch_group.go @@ -113,20 +113,20 @@ func resourcePatchGroupDelete(ctx context.Context, d *schema.ResourceData, meta patchGroup, baselineId, err := ParsePatchGroupID(d.Id()) if err != nil { - return sdkdiag.AppendErrorf(diags, "parsing SSM Patch Group ID (%s): %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } - params := &ssm.DeregisterPatchBaselineForPatchGroupInput{ + log.Printf("[WARN] Deleting SSM Patch Group: %s", d.Id()) + _, err = conn.DeregisterPatchBaselineForPatchGroupWithContext(ctx, &ssm.DeregisterPatchBaselineForPatchGroupInput{ BaselineId: aws.String(baselineId), PatchGroup: aws.String(patchGroup), - } + }) - _, err = conn.DeregisterPatchBaselineForPatchGroupWithContext(ctx, params) + if tfawserr.ErrCodeEquals(err, ssm.ErrCodeDoesNotExistException) { + return diags + } if err != nil { - if tfawserr.ErrCodeEquals(err, ssm.ErrCodeDoesNotExistException) { - return diags - } return sdkdiag.AppendErrorf(diags, "deregistering SSM Patch Baseline (%s) for Patch Group (%s): %s", baselineId, patchGroup, err) } diff --git a/internal/service/ssm/sweep.go b/internal/service/ssm/sweep.go index 47cfd9038c3e..7669bd41ad6e 100644 --- a/internal/service/ssm/sweep.go +++ b/internal/service/ssm/sweep.go @@ -31,7 +31,7 @@ import ( func init() { resource.AddTestSweepers("aws_ssm_default_patch_baseline", &resource.Sweeper{ Name: "aws_ssm_default_patch_baseline", - F: sweepResourceDefaultPatchBaselines, + F: sweepDefaultPatchBaselines, }) resource.AddTestSweepers("aws_ssm_maintenance_window", &resource.Sweeper{ @@ -41,19 +41,25 @@ func init() { resource.AddTestSweepers("aws_ssm_patch_baseline", &resource.Sweeper{ Name: "aws_ssm_patch_baseline", - F: sweepResourcePatchBaselines, + F: sweepPatchBaselines, Dependencies: []string{ "aws_ssm_default_patch_baseline", + "aws_ssm_patch_group", }, }) + resource.AddTestSweepers("aws_ssm_patch_group", &resource.Sweeper{ + Name: "aws_ssm_patch_group", + F: sweepPatchGroups, + }) + resource.AddTestSweepers("aws_ssm_resource_data_sync", &resource.Sweeper{ Name: "aws_ssm_resource_data_sync", F: sweepResourceDataSyncs, }) } -func sweepResourceDefaultPatchBaselines(region string) error { +func sweepDefaultPatchBaselines(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) if err != nil { @@ -173,7 +179,7 @@ func sweepMaintenanceWindows(region string) error { return nil } -func sweepResourcePatchBaselines(region string) error { +func sweepPatchBaselines(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) if err != nil { @@ -201,8 +207,8 @@ func sweepResourcePatchBaselines(region string) error { baselineID := aws.ToString(identity.BaselineId) r := ResourcePatchBaseline() d := r.Data(nil) - d.SetId(baselineID) + d.Set("operating_system", identity.OperatingSystem) sweepables = append(sweepables, sweep.NewSweepResource(r, d, client)) } @@ -215,6 +221,50 @@ func sweepResourcePatchBaselines(region string) error { return errs.ErrorOrNil() } +func sweepPatchGroups(region string) error { + ctx := sweep.Context(region) + client, err := sweep.SharedRegionalSweepClient(ctx, region) + if err != nil { + return fmt.Errorf("getting client: %w", err) + } + conn := client.SSMConn(ctx) + sweepResources := make([]sweep.Sweepable, 0) + var errs *multierror.Error + + input := &ssm_sdkv1.DescribePatchGroupsInput{} + + err = conn.DescribePatchGroupsPagesWithContext(ctx, input, func(page *ssm_sdkv1.DescribePatchGroupsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, mapping := range page.Mappings { + r := ResourcePatchGroup() + d := r.Data(nil) + d.SetId(fmt.Sprintf("%s,%s", aws.ToString(mapping.PatchGroup), aws.ToString(mapping.BaselineIdentity.BaselineId))) + + sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) + } + + return !lastPage + }) + + if err != nil { + errs = multierror.Append(errs, fmt.Errorf("listing SSM Patch Groups for %s: %w", region, err)) + } + + if err := sweep.SweepOrchestrator(ctx, sweepResources); err != nil { + errs = multierror.Append(errs, fmt.Errorf("sweeping SSM Patch Groups for %s: %w", region, err)) + } + + if awsv1.SkipSweepError(errs.ErrorOrNil()) { + log.Printf("[WARN] Skipping SSM Patch Group sweep for %s: %s", region, errs) + return nil + } + + return errs.ErrorOrNil() +} + func sweepResourceDataSyncs(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) diff --git a/internal/sweep/awsv1/skip.go b/internal/sweep/awsv1/skip.go index ee7f551ddd86..b7d63eeef90e 100644 --- a/internal/sweep/awsv1/skip.go +++ b/internal/sweep/awsv1/skip.go @@ -39,7 +39,7 @@ func SkipSweepError(err error) bool { return true } // Example: InvalidAction: InvalidAction: Operation (ListPlatformApplications) is not supported in this region - if tfawserr.ErrMessageContains(err, "InvalidAction", "is not supported in this region") { + if tfawserr.ErrMessageContains(err, "InvalidAction", "is not supported") { return true } // Example: InvalidAction: The action DescribeTransitGatewayAttachments is not valid for this web service diff --git a/names/names.go b/names/names.go index 101d272f5680..d523cd589730 100644 --- a/names/names.go +++ b/names/names.go @@ -77,6 +77,7 @@ const ( ) const ( + USEast1RegionID = "us-east-1" // US East (N. Virginia). USWest2RegionID = "us-west-2" // US West (Oregon). )