diff --git a/go.mod b/go.mod index d2e530b6b49d..0c29829bdbad 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ec2 v1.99.0 github.com/aws/aws-sdk-go-v2/service/finspace v1.10.0 github.com/aws/aws-sdk-go-v2/service/fis v1.14.10 + github.com/aws/aws-sdk-go-v2/service/glacier v1.14.11 github.com/aws/aws-sdk-go-v2/service/healthlake v1.16.0 github.com/aws/aws-sdk-go-v2/service/identitystore v1.16.11 github.com/aws/aws-sdk-go-v2/service/inspector2 v1.14.0 diff --git a/go.sum b/go.sum index 9330e01694be..639cd9e36c5a 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/aws/aws-sdk-go-v2/service/finspace v1.10.0 h1:vZczEtJSs8HEkZ9JuxkKIHg github.com/aws/aws-sdk-go-v2/service/finspace v1.10.0/go.mod h1:y9XeW3Hxtkh+Sled61taaqOk1Lk7wdGpLRBx9Z/twOk= github.com/aws/aws-sdk-go-v2/service/fis v1.14.10 h1:uDfGkU0W6mO34XFbXgc9sFjOXTNA6IRoeeoPkCnZnx4= github.com/aws/aws-sdk-go-v2/service/fis v1.14.10/go.mod h1:UFu/qHPW17t5CcwChAc76mSq3v/bRyzhqjwiTcqlwLI= +github.com/aws/aws-sdk-go-v2/service/glacier v1.14.11 h1:dTa4Macg5HxqrQfauBnhpx5cDU9S17mpMI/++BuG/2g= +github.com/aws/aws-sdk-go-v2/service/glacier v1.14.11/go.mod h1:7RgtFQVsN4MpvQieAJkHSUuvPTiMcEZO57tAnpzlM1I= github.com/aws/aws-sdk-go-v2/service/healthlake v1.16.0 h1:8CXnXojAdCTtFhrJn2Ez6DDFFykbd9lWOu0Frs1zoqk= github.com/aws/aws-sdk-go-v2/service/healthlake v1.16.0/go.mod h1:n1IxBDIRdNPVLrEDqwDSZSF60FkFIO43gWVMZo4Y/Rk= github.com/aws/aws-sdk-go-v2/service/iam v1.19.12 h1:JH1H7POlsZt41X9JYIBLZoXW0Qv+WOuC48xsafsls2Q= diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index 821e155c1dd1..bf4e994e7b5e 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -18,6 +18,7 @@ import ( ec2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/finspace" "github.com/aws/aws-sdk-go-v2/service/fis" + "github.com/aws/aws-sdk-go-v2/service/glacier" "github.com/aws/aws-sdk-go-v2/service/healthlake" "github.com/aws/aws-sdk-go-v2/service/identitystore" "github.com/aws/aws-sdk-go-v2/service/inspector2" @@ -159,7 +160,6 @@ import ( "github.com/aws/aws-sdk-go/service/frauddetector" "github.com/aws/aws-sdk-go/service/fsx" "github.com/aws/aws-sdk-go/service/gamelift" - "github.com/aws/aws-sdk-go/service/glacier" "github.com/aws/aws-sdk-go/service/globalaccelerator" "github.com/aws/aws-sdk-go/service/glue" "github.com/aws/aws-sdk-go/service/gluedatabrew" @@ -476,7 +476,7 @@ type AWSClient struct { forecastqueryConn *forecastqueryservice.ForecastQueryService frauddetectorConn *frauddetector.FraudDetector gameliftConn *gamelift.GameLift - glacierConn *glacier.Glacier + glacierClient *glacier.Client globalacceleratorConn *globalaccelerator.GlobalAccelerator glueConn *glue.Glue grafanaConn *managedgrafana.ManagedGrafana @@ -1168,8 +1168,8 @@ func (client *AWSClient) GameLiftConn() *gamelift.GameLift { return client.gameliftConn } -func (client *AWSClient) GlacierConn() *glacier.Glacier { - return client.glacierConn +func (client *AWSClient) GlacierClient() *glacier.Client { + return client.glacierClient } func (client *AWSClient) GlobalAcceleratorConn() *globalaccelerator.GlobalAccelerator { diff --git a/internal/conns/config_gen.go b/internal/conns/config_gen.go index 51ecb0439022..549fb60f3242 100644 --- a/internal/conns/config_gen.go +++ b/internal/conns/config_gen.go @@ -17,6 +17,7 @@ import ( ec2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/finspace" "github.com/aws/aws-sdk-go-v2/service/fis" + "github.com/aws/aws-sdk-go-v2/service/glacier" "github.com/aws/aws-sdk-go-v2/service/healthlake" "github.com/aws/aws-sdk-go-v2/service/identitystore" "github.com/aws/aws-sdk-go-v2/service/inspector2" @@ -158,7 +159,6 @@ import ( "github.com/aws/aws-sdk-go/service/frauddetector" "github.com/aws/aws-sdk-go/service/fsx" "github.com/aws/aws-sdk-go/service/gamelift" - "github.com/aws/aws-sdk-go/service/glacier" "github.com/aws/aws-sdk-go/service/glue" "github.com/aws/aws-sdk-go/service/gluedatabrew" "github.com/aws/aws-sdk-go/service/greengrass" @@ -436,7 +436,6 @@ func (c *Config) sdkv1Conns(client *AWSClient, sess *session.Session) { client.forecastqueryConn = forecastqueryservice.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints[names.ForecastQuery])})) client.frauddetectorConn = frauddetector.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints[names.FraudDetector])})) client.gameliftConn = gamelift.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints[names.GameLift])})) - client.glacierConn = glacier.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints[names.Glacier])})) client.glueConn = glue.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints[names.Glue])})) client.grafanaConn = managedgrafana.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints[names.Grafana])})) client.greengrassConn = greengrass.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints[names.Greengrass])})) @@ -660,6 +659,11 @@ func (c *Config) sdkv2Conns(client *AWSClient, cfg aws_sdkv2.Config) { o.EndpointResolver = finspace.EndpointResolverFromURL(endpoint) } }) + client.glacierClient = glacier.NewFromConfig(cfg, func(o *glacier.Options) { + if endpoint := c.Endpoints[names.Glacier]; endpoint != "" { + o.EndpointResolver = glacier.EndpointResolverFromURL(endpoint) + } + }) client.healthlakeClient = healthlake.NewFromConfig(cfg, func(o *healthlake.Options) { if endpoint := c.Endpoints[names.HealthLake]; endpoint != "" { o.EndpointResolver = healthlake.EndpointResolverFromURL(endpoint) diff --git a/internal/generate/tags/templates/v2/service_tags_value_map_body.tmpl b/internal/generate/tags/templates/v2/service_tags_value_map_body.tmpl index 18513aac18e0..cde476c97fda 100644 --- a/internal/generate/tags/templates/v2/service_tags_value_map_body.tmpl +++ b/internal/generate/tags/templates/v2/service_tags_value_map_body.tmpl @@ -28,3 +28,14 @@ func SetTagsOut(ctx context.Context, tags map[string]string) { inContext.TagsOut = types.Some(KeyValueTags(ctx, tags)) } } + +{{- if ne .CreateTagsFunc "" }} +// {{ .CreateTagsFunc }} creates {{ .ServicePackage }} service tags for new resources. +func {{ .CreateTagsFunc }}(ctx context.Context, conn {{ .ClientType }}, identifier{{ if .TagResTypeElem }}, resourceType{{ end }} string, tags map[string]string) error { + if len(tags) == 0 { + return nil + } + + return {{ .UpdateTagsFunc }}(ctx, conn, identifier{{ if .TagResTypeElem }}, resourceType{{ end }}, nil, tags) +} +{{- end }} diff --git a/internal/service/glacier/exports_test.go b/internal/service/glacier/exports_test.go new file mode 100644 index 000000000000..43675c936826 --- /dev/null +++ b/internal/service/glacier/exports_test.go @@ -0,0 +1,10 @@ +package glacier + +// Exports for use in tests only. +var ( + ResourceVault = resourceVault + ResourceVaultLock = resourceVaultLock + + FindVaultByName = findVaultByName + FindVaultLockByName = findVaultLockByName +) diff --git a/internal/service/glacier/generate.go b/internal/service/glacier/generate.go index fd6511717ab6..5868ef7092b5 100644 --- a/internal/service/glacier/generate.go +++ b/internal/service/glacier/generate.go @@ -1,4 +1,4 @@ -//go:generate go run ../../generate/tags/main.go -ListTags -ListTagsOp=ListTagsForVault -ListTagsInIDElem=VaultName -ServiceTagsMap -TagOp=AddTagsToVault -TagInIDElem=VaultName -UntagOp=RemoveTagsFromVault -UpdateTags -CreateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTags -ListTagsOp=ListTagsForVault -ListTagsInIDElem=VaultName -ServiceTagsMap -KVTValues -TagOp=AddTagsToVault -TagInIDElem=VaultName -UntagOp=RemoveTagsFromVault -UpdateTags -CreateTags -SkipTypesImp // ONLY generate directives and package declaration! Do not add anything else to this file. package glacier diff --git a/internal/service/glacier/service_package_gen.go b/internal/service/glacier/service_package_gen.go index 3a453c7ce9ae..8f7e379479d6 100644 --- a/internal/service/glacier/service_package_gen.go +++ b/internal/service/glacier/service_package_gen.go @@ -26,7 +26,7 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ { - Factory: ResourceVault, + Factory: resourceVault, TypeName: "aws_glacier_vault", Name: "Vault", Tags: &types.ServicePackageResourceTags{ @@ -34,7 +34,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceVaultLock, + Factory: resourceVaultLock, TypeName: "aws_glacier_vault_lock", }, } diff --git a/internal/service/glacier/sweep.go b/internal/service/glacier/sweep.go index 640d605ec0b3..be88f4225f06 100644 --- a/internal/service/glacier/sweep.go +++ b/internal/service/glacier/sweep.go @@ -7,8 +7,8 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/glacier" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/glacier" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/sweep" @@ -28,32 +28,29 @@ func sweepVaults(region string) error { return fmt.Errorf("error getting client: %w", err) } input := &glacier.ListVaultsInput{} - conn := client.(*conns.AWSClient).GlacierConn() + conn := client.(*conns.AWSClient).GlacierClient() sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListVaultsPagesWithContext(ctx, input, func(page *glacier.ListVaultsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := glacier.NewListVaultsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if sweep.SkipSweepError(err) { + log.Printf("[WARN] Skipping Glacier Vault sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing Glacier Vaults (%s): %w", region, err) } for _, v := range page.VaultList { - r := ResourceVault() + r := resourceVault() d := r.Data(nil) - d.SetId(aws.StringValue(v.VaultName)) + d.SetId(aws.ToString(v.VaultName)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if sweep.SkipSweepError(err) { - log.Printf("[WARN] Skipping Glacier Vault sweep for %s: %s", region, err) - return nil - } - - if err != nil { - return fmt.Errorf("error listing Glacier Vaults (%s): %w", region, err) } err = sweep.SweepOrchestratorWithContext(ctx, sweepResources) diff --git a/internal/service/glacier/tags_gen.go b/internal/service/glacier/tags_gen.go index eb4e4de312e4..51f0b28abf9d 100644 --- a/internal/service/glacier/tags_gen.go +++ b/internal/service/glacier/tags_gen.go @@ -5,9 +5,8 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/glacier" - "github.com/aws/aws-sdk-go/service/glacier/glacieriface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/glacier" "github.com/hashicorp/terraform-provider-aws/internal/conns" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/types" @@ -17,12 +16,12 @@ import ( // ListTags lists glacier service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func ListTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier string) (tftags.KeyValueTags, error) { +func ListTags(ctx context.Context, conn *glacier.Client, identifier string) (tftags.KeyValueTags, error) { input := &glacier.ListTagsForVaultInput{ VaultName: aws.String(identifier), } - output, err := conn.ListTagsForVaultWithContext(ctx, input) + output, err := conn.ListTagsForVault(ctx, input) if err != nil { return tftags.New(ctx, nil), err @@ -34,7 +33,7 @@ func ListTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier stri // ListTags lists glacier service tags and set them in Context. // It is called from outside this package. func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { - tags, err := ListTags(ctx, meta.(*conns.AWSClient).GlacierConn(), identifier) + tags, err := ListTags(ctx, meta.(*conns.AWSClient).GlacierClient(), identifier) if err != nil { return err @@ -47,21 +46,21 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier stri return nil } -// map[string]*string handling +// map[string]string handling // Tags returns glacier service tags. -func Tags(tags tftags.KeyValueTags) map[string]*string { - return aws.StringMap(tags.Map()) +func Tags(tags tftags.KeyValueTags) map[string]string { + return tags.Map() } // KeyValueTags creates KeyValueTags from glacier service tags. -func KeyValueTags(ctx context.Context, tags map[string]*string) tftags.KeyValueTags { +func KeyValueTags(ctx context.Context, tags map[string]string) tftags.KeyValueTags { return tftags.New(ctx, tags) } // GetTagsIn returns glacier service tags from Context. // nil is returned if there are no input tags. -func GetTagsIn(ctx context.Context) map[string]*string { +func GetTagsIn(ctx context.Context) map[string]string { if inContext, ok := tftags.FromContext(ctx); ok { if tags := Tags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { return tags @@ -72,14 +71,14 @@ func GetTagsIn(ctx context.Context) map[string]*string { } // SetTagsOut sets glacier service tags in Context. -func SetTagsOut(ctx context.Context, tags map[string]*string) { +func SetTagsOut(ctx context.Context, tags map[string]string) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = types.Some(KeyValueTags(ctx, tags)) } } // createTags creates glacier service tags for new resources. -func createTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier string, tags map[string]*string) error { +func createTags(ctx context.Context, conn *glacier.Client, identifier string, tags map[string]string) error { if len(tags) == 0 { return nil } @@ -90,7 +89,7 @@ func createTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier st // UpdateTags updates glacier service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func UpdateTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier string, oldTagsMap, newTagsMap any) error { +func UpdateTags(ctx context.Context, conn *glacier.Client, identifier string, oldTagsMap, newTagsMap any) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -99,10 +98,10 @@ func UpdateTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier st if len(removedTags) > 0 { input := &glacier.RemoveTagsFromVaultInput{ VaultName: aws.String(identifier), - TagKeys: aws.StringSlice(removedTags.Keys()), + TagKeys: removedTags.Keys(), } - _, err := conn.RemoveTagsFromVaultWithContext(ctx, input) + _, err := conn.RemoveTagsFromVault(ctx, input) if err != nil { return fmt.Errorf("untagging resource (%s): %w", identifier, err) @@ -117,7 +116,7 @@ func UpdateTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier st Tags: Tags(updatedTags), } - _, err := conn.AddTagsToVaultWithContext(ctx, input) + _, err := conn.AddTagsToVault(ctx, input) if err != nil { return fmt.Errorf("tagging resource (%s): %w", identifier, err) @@ -130,5 +129,5 @@ func UpdateTags(ctx context.Context, conn glacieriface.GlacierAPI, identifier st // UpdateTags updates glacier service tags. // It is called from outside this package. func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { - return UpdateTags(ctx, meta.(*conns.AWSClient).GlacierConn(), identifier, oldTags, newTags) + return UpdateTags(ctx, meta.(*conns.AWSClient).GlacierClient(), identifier, oldTags, newTags) } diff --git a/internal/service/glacier/vault.go b/internal/service/glacier/vault.go index f0783bbc5edb..908d77e4bc78 100644 --- a/internal/service/glacier/vault.go +++ b/internal/service/glacier/vault.go @@ -2,29 +2,31 @@ package glacier import ( "context" - "errors" "fmt" "log" "regexp" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/glacier" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/glacier" + "github.com/aws/aws-sdk-go-v2/service/glacier/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "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/structure" "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" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" 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" "github.com/hashicorp/terraform-provider-aws/names" ) // @SDKResource("aws_glacier_vault", name="Vault") // @Tags(identifierAttribute="id") -func ResourceVault() *schema.Resource { +func resourceVault() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceVaultCreate, ReadWithoutTimeout: resourceVaultRead, @@ -36,27 +38,6 @@ func ResourceVault() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 255), - validation.StringMatch(regexp.MustCompile(`^[.0-9A-Za-z-_]+$`), - "only alphanumeric characters, hyphens, underscores, and periods are allowed"), - ), - }, - - "location": { - Type: schema.TypeString, - Computed: true, - }, - - "arn": { - Type: schema.TypeString, - Computed: true, - }, - "access_policy": { Type: schema.TypeString, Optional: true, @@ -68,7 +49,24 @@ func ResourceVault() *schema.Resource { return json }, }, - + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 255), + validation.StringMatch(regexp.MustCompile(`^[.0-9A-Za-z-_]+$`), + "only alphanumeric characters, hyphens, underscores, and periods are allowed"), + ), + }, "notification": { Type: schema.TypeList, Optional: true, @@ -85,7 +83,6 @@ func ResourceVault() *schema.Resource { "InventoryRetrievalCompleted", }, false), }, - Set: schema.HashString, }, "sns_topic": { Type: schema.TypeString, @@ -95,7 +92,6 @@ func ResourceVault() *schema.Resource { }, }, }, - names.AttrTags: tftags.TagsSchema(), names.AttrTagsAll: tftags.TagsSchemaComputed(), }, @@ -106,32 +102,56 @@ func ResourceVault() *schema.Resource { func resourceVaultCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlacierConn() + conn := meta.(*conns.AWSClient).GlacierClient() + name := d.Get("name").(string) input := &glacier.CreateVaultInput{ - VaultName: aws.String(d.Get("name").(string)), + VaultName: aws.String(name), } - _, err := conn.CreateVaultWithContext(ctx, input) + _, err := conn.CreateVault(ctx, input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "creating Glacier Vault: %s", err) + return sdkdiag.AppendErrorf(diags, "creating Glacier Vault (%s): %s", name, err) } - d.SetId(d.Get("name").(string)) + d.SetId(name) if err := createTags(ctx, conn, d.Id(), GetTagsIn(ctx)); err != nil { return sdkdiag.AppendErrorf(diags, "setting Glacier Vault (%s) tags: %s", d.Id(), err) } - if _, ok := d.GetOk("access_policy"); ok { - if err := resourceVaultPolicyUpdate(ctx, conn, d); err != nil { - return sdkdiag.AppendErrorf(diags, "updating Glacier Vault (%s) access policy: %s", d.Id(), err) + if v, ok := d.GetOk("access_policy"); ok { + policy, err := structure.NormalizeJsonString(v.(string)) + + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + + input := &glacier.SetVaultAccessPolicyInput{ + Policy: &types.VaultAccessPolicy{ + Policy: aws.String(policy), + }, + VaultName: aws.String(d.Id()), + } + + _, err = conn.SetVaultAccessPolicy(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "setting Glacier Vault (%s) access policy: %s", d.Id(), err) } } - if _, ok := d.GetOk("notification"); ok { - if err := resourceVaultNotificationUpdate(ctx, conn, d); err != nil { - return sdkdiag.AppendErrorf(diags, "updating Glacier Vault (%s) notification: %s", d.Id(), err) + if v, ok := d.GetOk("notification"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + input := &glacier.SetVaultNotificationsInput{ + VaultName: aws.String(d.Id()), + VaultNotificationConfig: expandVaultNotificationConfig(v.([]interface{})[0].(map[string]interface{})), + } + + _, err := conn.SetVaultNotifications(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "setting Glacier Vault (%s) notifications: %s", d.Id(), err) } } @@ -140,58 +160,65 @@ func resourceVaultCreate(ctx context.Context, d *schema.ResourceData, meta inter func resourceVaultRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlacierConn() + conn := meta.(*conns.AWSClient).GlacierClient() - input := &glacier.DescribeVaultInput{ - VaultName: aws.String(d.Id()), - } + output, err := findVaultByName(ctx, conn, d.Id()) - out, err := conn.DescribeVaultWithContext(ctx, input) - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { + if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Glaier Vault (%s) not found, removing from state", d.Id()) d.SetId("") return diags } - if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Glacier Vault (%s): %s", d.Id(), err) - } - - awsClient := meta.(*conns.AWSClient) - d.Set("name", out.VaultName) - d.Set("arn", out.VaultARN) - location, err := buildVaultLocation(awsClient.AccountID, d.Id()) if err != nil { return sdkdiag.AppendErrorf(diags, "reading Glacier Vault (%s): %s", d.Id(), err) } - d.Set("location", location) - log.Printf("[DEBUG] Getting the access_policy for Vault %s", d.Id()) - pol, err := conn.GetVaultAccessPolicyWithContext(ctx, &glacier.GetVaultAccessPolicyInput{ - VaultName: aws.String(d.Id()), - }) + d.Set("access_policy", nil) + d.Set("arn", output.VaultARN) + d.Set("location", fmt.Sprintf("/%s/vaults/%s", meta.(*conns.AWSClient).AccountID, d.Id())) + d.Set("name", output.VaultName) + d.Set("notification", nil) - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { - d.Set("access_policy", "") - } else if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Glacier Vault (%s): reading policy: %s", d.Id(), err) - } else if pol != nil && pol.Policy != nil { - policy, err := verify.PolicyToSet(d.Get("access_policy").(string), aws.StringValue(pol.Policy.Policy)) + if output, err := conn.GetVaultAccessPolicy(ctx, &glacier.GetVaultAccessPolicyInput{ + VaultName: aws.String(d.Id()), + }); err != nil { + // "An error occurred (ResourceNotFoundException) when calling the GetVaultAccessPolicy operation: No vault access policy is set for: ..." + if !errs.IsA[*types.ResourceNotFoundException](err) { + return sdkdiag.AppendErrorf(diags, "reading Glacier Vault (%s) access policy: %s", d.Id(), err) + } + } else if output != nil && output.Policy != nil { + policy, err := verify.PolicyToSet(d.Get("access_policy").(string), aws.ToString(output.Policy.Policy)) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Glacier Vault (%s): setting policy: %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("access_policy", policy) } - notifications, err := getVaultNotification(ctx, conn, d.Id()) - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { - d.Set("notification", []map[string]interface{}{}) - } else if pol != nil { - d.Set("notification", notifications) - } else { - return sdkdiag.AppendErrorf(diags, "setting notification: %s", err) + if output, err := conn.GetVaultNotifications(ctx, &glacier.GetVaultNotificationsInput{ + VaultName: aws.String(d.Id()), + }); err != nil { + // "An error occurred (ResourceNotFoundException) when calling the GetVaultNotifications operation: No notification configuration is set for vault: ..." + if !errs.IsA[*types.ResourceNotFoundException](err) { + return sdkdiag.AppendErrorf(diags, "reading Glacier Vault (%s) notifications: %s", d.Id(), err) + } + } else if output != nil && output.VaultNotificationConfig != nil { + apiObject := output.VaultNotificationConfig + tfMap := map[string]interface{}{} + + if v := apiObject.Events; v != nil { + tfMap["events"] = v + } + + if v := apiObject.SNSTopic; v != nil { + tfMap["sns_topic"] = aws.ToString(v) + } + + if err := d.Set("notification", []interface{}{tfMap}); err != nil { + return sdkdiag.AppendErrorf(diags, "setting notification: %s", err) + } } return diags @@ -199,17 +226,63 @@ func resourceVaultRead(ctx context.Context, d *schema.ResourceData, meta interfa func resourceVaultUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlacierConn() + conn := meta.(*conns.AWSClient).GlacierClient() if d.HasChange("access_policy") { - if err := resourceVaultPolicyUpdate(ctx, conn, d); err != nil { - return sdkdiag.AppendErrorf(diags, "updating Glacier Vault (%s) access policy: %s", d.Id(), err) + if v, ok := d.GetOk("access_policy"); ok { + policy, err := structure.NormalizeJsonString(v.(string)) + + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + + input := &glacier.SetVaultAccessPolicyInput{ + Policy: &types.VaultAccessPolicy{ + Policy: aws.String(policy), + }, + VaultName: aws.String(d.Id()), + } + + _, err = conn.SetVaultAccessPolicy(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "setting Glacier Vault (%s) access policy: %s", d.Id(), err) + } + } else { + input := &glacier.DeleteVaultAccessPolicyInput{ + VaultName: aws.String(d.Id()), + } + + _, err := conn.DeleteVaultAccessPolicy(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "deleting Glacier Vault (%s) access policy: %s", d.Id(), err) + } } } if d.HasChange("notification") { - if err := resourceVaultNotificationUpdate(ctx, conn, d); err != nil { - return sdkdiag.AppendErrorf(diags, "updating Glacier Vault (%s) notification: %s", d.Id(), err) + if v, ok := d.GetOk("notification"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + input := &glacier.SetVaultNotificationsInput{ + VaultName: aws.String(d.Id()), + VaultNotificationConfig: expandVaultNotificationConfig(v.([]interface{})[0].(map[string]interface{})), + } + + _, err := conn.SetVaultNotifications(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "setting Glacier Vault (%s) notifications: %s", d.Id(), err) + } + } else { + input := &glacier.DeleteVaultNotificationsInput{ + VaultName: aws.String(d.Id()), + } + + _, err := conn.DeleteVaultNotifications(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "deleting Glacier Vault (%s) notifications: %s", d.Id(), err) + } } } @@ -218,108 +291,59 @@ func resourceVaultUpdate(ctx context.Context, d *schema.ResourceData, meta inter func resourceVaultDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlacierConn() + conn := meta.(*conns.AWSClient).GlacierClient() log.Printf("[DEBUG] Deleting Glacier Vault: %s", d.Id()) - _, err := conn.DeleteVaultWithContext(ctx, &glacier.DeleteVaultInput{ + _, err := conn.DeleteVault(ctx, &glacier.DeleteVaultInput{ VaultName: aws.String(d.Id()), }) + if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting Glacier Vault: %s", err) + return sdkdiag.AppendErrorf(diags, "deleting Glacier Vault (%s): %s", d.Id(), err) } + return diags } -func resourceVaultNotificationUpdate(ctx context.Context, conn *glacier.Glacier, d *schema.ResourceData) error { - if v, ok := d.GetOk("notification"); ok { - settings := v.([]interface{}) - - s := settings[0].(map[string]interface{}) - - _, err := conn.SetVaultNotificationsWithContext(ctx, &glacier.SetVaultNotificationsInput{ - VaultName: aws.String(d.Id()), - VaultNotificationConfig: &glacier.VaultNotificationConfig{ - SNSTopic: aws.String(s["sns_topic"].(string)), - Events: flex.ExpandStringSet(s["events"].(*schema.Set)), - }, - }) +func findVaultByName(ctx context.Context, conn *glacier.Client, name string) (*glacier.DescribeVaultOutput, error) { + input := &glacier.DescribeVaultInput{ + VaultName: aws.String(name), + } - if err != nil { - return fmt.Errorf("Updating Glacier Vault Notifications: %w", err) - } - } else { - _, err := conn.DeleteVaultNotificationsWithContext(ctx, &glacier.DeleteVaultNotificationsInput{ - VaultName: aws.String(d.Id()), - }) + output, err := conn.DescribeVault(ctx, input) - if err != nil { - return fmt.Errorf("Removing Glacier Vault Notifications: %w", err) + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, } } - return nil -} - -func resourceVaultPolicyUpdate(ctx context.Context, conn *glacier.Glacier, d *schema.ResourceData) error { - vaultName := d.Id() - policyContents, err := structure.NormalizeJsonString(d.Get("access_policy").(string)) - if err != nil { - return fmt.Errorf("policy (%s) is invalid JSON: %w", policyContents, err) + return nil, err } - policy := &glacier.VaultAccessPolicy{ - Policy: aws.String(policyContents), - } - - if policyContents != "" { - log.Printf("[DEBUG] Glacier Vault: %s, put policy", vaultName) - - _, err := conn.SetVaultAccessPolicyWithContext(ctx, &glacier.SetVaultAccessPolicyInput{ - VaultName: aws.String(d.Id()), - Policy: policy, - }) - - if err != nil { - return fmt.Errorf("putting Glacier Vault policy: %w", err) - } - } else { - log.Printf("[DEBUG] Glacier Vault: %s, delete policy: %s", vaultName, policy) - _, err := conn.DeleteVaultAccessPolicyWithContext(ctx, &glacier.DeleteVaultAccessPolicyInput{ - VaultName: aws.String(d.Id()), - }) - - if err != nil { - return fmt.Errorf("deleting Glacier Vault policy: %w", err) - } + if output == nil { + return nil, tfresource.NewEmptyResultError(input) } - return nil + return output, nil } -func buildVaultLocation(accountId, vaultName string) (string, error) { - if accountId == "" { - return "", errors.New("AWS account ID unavailable - failed to construct Vault location") +func expandVaultNotificationConfig(tfMap map[string]interface{}) *types.VaultNotificationConfig { + if tfMap == nil { + return nil } - return fmt.Sprintf("/" + accountId + "/vaults/" + vaultName), nil -} -func getVaultNotification(ctx context.Context, conn *glacier.Glacier, vaultName string) ([]map[string]interface{}, error) { - request := &glacier.GetVaultNotificationsInput{ - VaultName: aws.String(vaultName), - } + apiObject := &types.VaultNotificationConfig{} - response, err := conn.GetVaultNotificationsWithContext(ctx, request) - if err != nil { - return nil, fmt.Errorf("reading Glacier Vault Notifications: %w", err) + if v, ok := tfMap["events"].(*schema.Set); ok && v.Len() > 0 { + apiObject.Events = flex.ExpandStringValueSet(v) } - notifications := make(map[string]interface{}) - - log.Print("[DEBUG] Flattening Glacier Vault Notifications") - - notifications["events"] = aws.StringValueSlice(response.VaultNotificationConfig.Events) - notifications["sns_topic"] = aws.StringValue(response.VaultNotificationConfig.SNSTopic) + if v, ok := tfMap["sns_topic"].(string); ok && v != "" { + apiObject.SNSTopic = aws.String(v) + } - return []map[string]interface{}{notifications}, nil + return apiObject } diff --git a/internal/service/glacier/vault_lock.go b/internal/service/glacier/vault_lock.go index 98d90958bdd6..895d255e6669 100644 --- a/internal/service/glacier/vault_lock.go +++ b/internal/service/glacier/vault_lock.go @@ -2,31 +2,32 @@ package glacier import ( "context" - "fmt" "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/glacier" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/glacier" + "github.com/aws/aws-sdk-go-v2/service/glacier/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "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/structure" "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" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) // @SDKResource("aws_glacier_vault_lock") -func ResourceVaultLock() *schema.Resource { +func resourceVaultLock() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceVaultLockCreate, ReadWithoutTimeout: resourceVaultLockRead, - // Allow ignore_deletion_error update - UpdateWithoutTimeout: schema.NoopContext, + UpdateWithoutTimeout: schema.NoopContext, // Allow ignore_deletion_error update. DeleteWithoutTimeout: resourceVaultLockDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -64,49 +65,53 @@ func ResourceVaultLock() *schema.Resource { } } +const ( + lockStateInProgress = "InProgress" + lockStateLocked = "Locked" +) + func resourceVaultLockCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlacierConn() - vaultName := d.Get("vault_name").(string) + conn := meta.(*conns.AWSClient).GlacierClient() policy, err := structure.NormalizeJsonString(d.Get("policy").(string)) if err != nil { - return sdkdiag.AppendErrorf(diags, "policy is invalid JSON: %s", err) + return sdkdiag.AppendFromErr(diags, err) } + vaultName := d.Get("vault_name").(string) input := &glacier.InitiateVaultLockInput{ AccountId: aws.String("-"), - Policy: &glacier.VaultLockPolicy{ + Policy: &types.VaultLockPolicy{ Policy: aws.String(policy), }, VaultName: aws.String(vaultName), } - log.Printf("[DEBUG] Initiating Glacier Vault Lock: %s", input) - output, err := conn.InitiateVaultLockWithContext(ctx, input) + output, err := conn.InitiateVaultLock(ctx, input) + if err != nil { - return sdkdiag.AppendErrorf(diags, "initiating Glacier Vault Lock: %s", err) + return sdkdiag.AppendErrorf(diags, "creating Glacier Vault Lock (%s): %s", vaultName, err) } d.SetId(vaultName) - if !d.Get("complete_lock").(bool) { - return append(diags, resourceVaultLockRead(ctx, d, meta)...) - } + if d.Get("complete_lock").(bool) { + input := &glacier.CompleteVaultLockInput{ + LockId: output.LockId, + VaultName: aws.String(vaultName), + } - completeLockInput := &glacier.CompleteVaultLockInput{ - LockId: output.LockId, - VaultName: aws.String(vaultName), - } + _, err := conn.CompleteVaultLock(ctx, input) - log.Printf("[DEBUG] Completing Glacier Vault (%s) Lock: %s", vaultName, completeLockInput) - if _, err := conn.CompleteVaultLockWithContext(ctx, completeLockInput); err != nil { - return sdkdiag.AppendErrorf(diags, "completing Glacier Vault (%s) Lock: %s", vaultName, err) - } + if err != nil { + return sdkdiag.AppendErrorf(diags, "completing Glacier Vault Lock (%s): %s", d.Id(), err) + } - if err := waitVaultLockCompletion(ctx, conn, vaultName); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Glacier Vault Lock (%s) completion: %s", d.Id(), err) + if err := waitVaultLockComplete(ctx, conn, d.Id()); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Glacier Vault Lock (%s) completion: %s", d.Id(), err) + } } return append(diags, resourceVaultLockRead(ctx, d, meta)...) @@ -114,18 +119,12 @@ func resourceVaultLockCreate(ctx context.Context, d *schema.ResourceData, meta i func resourceVaultLockRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlacierConn() - - input := &glacier.GetVaultLockInput{ - AccountId: aws.String("-"), - VaultName: aws.String(d.Id()), - } + conn := meta.(*conns.AWSClient).GlacierClient() - log.Printf("[DEBUG] Reading Glacier Vault Lock (%s): %s", d.Id(), input) - output, err := conn.GetVaultLockWithContext(ctx, input) + output, err := findVaultLockByName(ctx, conn, d.Id()) - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { - log.Printf("[WARN] Glacier Vault Lock (%s) not found, removing from state", d.Id()) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Glaier Vault Lock (%s) not found, removing from state", d.Id()) d.SetId("") return diags } @@ -134,19 +133,13 @@ func resourceVaultLockRead(ctx context.Context, d *schema.ResourceData, meta int return sdkdiag.AppendErrorf(diags, "reading Glacier Vault Lock (%s): %s", d.Id(), err) } - if output == nil { - log.Printf("[WARN] Glacier Vault Lock (%s) not found, removing from state", d.Id()) - d.SetId("") - return diags - } - - d.Set("complete_lock", aws.StringValue(output.State) == "Locked") + d.Set("complete_lock", aws.ToString(output.State) == lockStateLocked) d.Set("vault_name", d.Id()) - policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.StringValue(output.Policy)) + policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.ToString(output.Policy)) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Glacier Vault Lock (%s): setting policy: %s", d.Id(), err) + return sdkdiag.AppendFromErr(diags, err) } d.Set("policy", policyToSet) @@ -156,61 +149,74 @@ func resourceVaultLockRead(ctx context.Context, d *schema.ResourceData, meta int func resourceVaultLockDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).GlacierConn() + conn := meta.(*conns.AWSClient).GlacierClient() - input := &glacier.AbortVaultLockInput{ + log.Printf("[DEBUG] Deleting Glacier Vault Lock: %s", d.Id()) + _, err := conn.AbortVaultLock(ctx, &glacier.AbortVaultLockInput{ VaultName: aws.String(d.Id()), - } - - log.Printf("[DEBUG] Aborting Glacier Vault Lock (%s): %s", d.Id(), input) - _, err := conn.AbortVaultLockWithContext(ctx, input) + }) - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { + if errs.IsA[*types.ResourceNotFoundException](err) { return diags } if err != nil && !d.Get("ignore_deletion_error").(bool) { - return sdkdiag.AppendErrorf(diags, "aborting Glacier Vault Lock (%s): %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "deleting Glacier Vault Lock (%s): %s", d.Id(), err) } return diags } -func vaultLockRefreshFunc(ctx context.Context, conn *glacier.Glacier, vaultName string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - input := &glacier.GetVaultLockInput{ - AccountId: aws.String("-"), - VaultName: aws.String(vaultName), +func findVaultLockByName(ctx context.Context, conn *glacier.Client, name string) (*glacier.GetVaultLockOutput, error) { + input := &glacier.GetVaultLockInput{ + AccountId: aws.String("-"), + VaultName: aws.String(name), + } + + output, err := conn.GetVaultLock(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, } + } - log.Printf("[DEBUG] Reading Glacier Vault Lock (%s): %s", vaultName, input) - output, err := conn.GetVaultLockWithContext(ctx, input) + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { +func statusLockState(ctx context.Context, conn *glacier.Client, name string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := findVaultLockByName(ctx, conn, name) + + if tfresource.NotFound(err) { return nil, "", nil } if err != nil { - return nil, "", fmt.Errorf("reading Glacier Vault Lock (%s): %s", vaultName, err) - } - - if output == nil { - return nil, "", nil + return nil, "", err } - return output, aws.StringValue(output.State), nil + return output, aws.ToString(output.State), nil } } -func waitVaultLockCompletion(ctx context.Context, conn *glacier.Glacier, vaultName string) error { +func waitVaultLockComplete(ctx context.Context, conn *glacier.Client, name string) error { stateConf := &retry.StateChangeConf{ - Pending: []string{"InProgress"}, - Target: []string{"Locked"}, - Refresh: vaultLockRefreshFunc(ctx, conn, vaultName), + Pending: []string{lockStateInProgress}, + Target: []string{lockStateLocked}, + Refresh: statusLockState(ctx, conn, name), Timeout: 5 * time.Minute, } - log.Printf("[DEBUG] Waiting for Glacier Vault Lock (%s) completion", vaultName) _, err := stateConf.WaitForStateContext(ctx) return err diff --git a/internal/service/glacier/vault_lock_test.go b/internal/service/glacier/vault_lock_test.go index 91122ed54209..83dcc8da49dd 100644 --- a/internal/service/glacier/vault_lock_test.go +++ b/internal/service/glacier/vault_lock_test.go @@ -5,14 +5,15 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/glacier" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/service/glacier" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfglacier "github.com/hashicorp/terraform-provider-aws/internal/service/glacier" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccGlacierVaultLock_basic(t *testing.T) { @@ -24,7 +25,7 @@ func TestAccGlacierVaultLock_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultLockDestroy(ctx), Steps: []resource.TestStep{ @@ -57,7 +58,7 @@ func TestAccGlacierVaultLock_completeLock(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultLockDestroy(ctx), Steps: []resource.TestStep{ @@ -90,7 +91,7 @@ func TestAccGlacierVaultLock_ignoreEquivalentPolicy(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultLockDestroy(ctx), Steps: []resource.TestStep{ @@ -112,33 +113,26 @@ func TestAccGlacierVaultLock_ignoreEquivalentPolicy(t *testing.T) { }) } -func testAccCheckVaultLockExists(ctx context.Context, resourceName string, getVaultLockOutput *glacier.GetVaultLockOutput) resource.TestCheckFunc { +func testAccCheckVaultLockExists(ctx context.Context, n string, v *glacier.GetVaultLockOutput) 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) } if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") + return fmt.Errorf("No Glacier Vault Lock ID is set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierConn() + conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierClient() - input := &glacier.GetVaultLockInput{ - VaultName: aws.String(rs.Primary.ID), - } - output, err := conn.GetVaultLockWithContext(ctx, input) + output, err := tfglacier.FindVaultLockByName(ctx, conn, rs.Primary.ID) if err != nil { - return fmt.Errorf("error reading Glacier Vault Lock (%s): %s", rs.Primary.ID, err) - } - - if output == nil { - return fmt.Errorf("error reading Glacier Vault Lock (%s): empty response", rs.Primary.ID) + return err } - *getVaultLockOutput = *output + *v = *output return nil } @@ -146,29 +140,24 @@ func testAccCheckVaultLockExists(ctx context.Context, resourceName string, getVa func testAccCheckVaultLockDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierConn() + conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierClient() for _, rs := range s.RootModule().Resources { if rs.Type != "aws_glacier_vault_lock" { continue } - input := &glacier.GetVaultLockInput{ - VaultName: aws.String(rs.Primary.ID), - } - output, err := conn.GetVaultLockWithContext(ctx, input) + _, err := tfglacier.FindVaultLockByName(ctx, conn, rs.Primary.ID) - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { + if tfresource.NotFound(err) { continue } if err != nil { - return fmt.Errorf("error reading Glacier Vault Lock (%s): %s", rs.Primary.ID, err) + return err } - if output != nil { - return fmt.Errorf("Glacier Vault Lock (%s) still exists", rs.Primary.ID) - } + return fmt.Errorf("Glacier Vault Lock %s still exists", rs.Primary.ID) } return nil diff --git a/internal/service/glacier/vault_test.go b/internal/service/glacier/vault_test.go index 6b3e517f7d14..7c295d4d2cad 100644 --- a/internal/service/glacier/vault_test.go +++ b/internal/service/glacier/vault_test.go @@ -6,15 +6,15 @@ import ( "regexp" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/glacier" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/service/glacier" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfglacier "github.com/hashicorp/terraform-provider-aws/internal/service/glacier" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccGlacierVault_basic(t *testing.T) { @@ -25,7 +25,7 @@ func TestAccGlacierVault_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultDestroy(ctx), Steps: []resource.TestStep{ @@ -58,7 +58,7 @@ func TestAccGlacierVault_notification(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultDestroy(ctx), Steps: []resource.TestStep{ @@ -81,7 +81,6 @@ func TestAccGlacierVault_notification(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckVaultExists(ctx, resourceName, &vault), resource.TestCheckResourceAttr(resourceName, "notification.#", "0"), - testAccCheckVaultNotificationsMissing(ctx, resourceName), ), }, { @@ -105,7 +104,7 @@ func TestAccGlacierVault_policy(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultDestroy(ctx), Steps: []resource.TestStep{ @@ -114,8 +113,7 @@ func TestAccGlacierVault_policy(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckVaultExists(ctx, resourceName, &vault), resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestMatchResourceAttr(resourceName, "access_policy", - regexp.MustCompile(`"Sid":"cross-account-upload".+`)), + resource.TestMatchResourceAttr(resourceName, "access_policy", regexp.MustCompile(`"Sid":"cross-account-upload".+`)), ), }, { @@ -128,8 +126,7 @@ func TestAccGlacierVault_policy(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckVaultExists(ctx, resourceName, &vault), resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestMatchResourceAttr(resourceName, "access_policy", - regexp.MustCompile(`"Sid":"cross-account-upload1".+`)), + resource.TestMatchResourceAttr(resourceName, "access_policy", regexp.MustCompile(`"Sid":"cross-account-upload1".+`)), ), }, { @@ -151,7 +148,7 @@ func TestAccGlacierVault_tags(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultDestroy(ctx), Steps: []resource.TestStep{ @@ -197,7 +194,7 @@ func TestAccGlacierVault_disappears(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultDestroy(ctx), Steps: []resource.TestStep{ @@ -221,7 +218,7 @@ func TestAccGlacierVault_ignoreEquivalent(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, glacier.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.GlacierEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckVaultDestroy(ctx), Steps: []resource.TestStep{ @@ -244,64 +241,26 @@ func TestAccGlacierVault_ignoreEquivalent(t *testing.T) { }) } -func testAccCheckVaultExists(ctx context.Context, name string, vault *glacier.DescribeVaultOutput) resource.TestCheckFunc { +func testAccCheckVaultExists(ctx context.Context, n string, v *glacier.DescribeVaultOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", name) + return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") + return fmt.Errorf("No Glacier Vault ID is set") } - conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierConn() - out, err := conn.DescribeVaultWithContext(ctx, &glacier.DescribeVaultInput{ - VaultName: aws.String(rs.Primary.ID), - }) + conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierClient() + + output, err := tfglacier.FindVaultByName(ctx, conn, rs.Primary.ID) if err != nil { return err } - if out.VaultARN == nil { - return fmt.Errorf("No Glacier Vault Found") - } - - if *out.VaultName != rs.Primary.ID { - return fmt.Errorf("Glacier Vault Mismatch - existing: %q, state: %q", - *out.VaultName, rs.Primary.ID) - } - - *vault = *out - - return nil - } -} - -func testAccCheckVaultNotificationsMissing(ctx context.Context, name string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] - if !ok { - return fmt.Errorf("Not found: %s", name) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierConn() - out, err := conn.GetVaultNotificationsWithContext(ctx, &glacier.GetVaultNotificationsInput{ - VaultName: aws.String(rs.Primary.ID), - }) - - if !tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { - return fmt.Errorf("Expected ResourceNotFoundException for Vault %s Notification Block but got %s", rs.Primary.ID, err) - } - - if out.VaultNotificationConfig != nil { - return fmt.Errorf("Vault Notification Block has been found for %s", rs.Primary.ID) - } + *v = *output return nil } @@ -309,25 +268,24 @@ func testAccCheckVaultNotificationsMissing(ctx context.Context, name string) res func testAccCheckVaultDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierConn() + conn := acctest.Provider.Meta().(*conns.AWSClient).GlacierClient() for _, rs := range s.RootModule().Resources { if rs.Type != "aws_glacier_vault" { continue } - input := &glacier.DescribeVaultInput{ - VaultName: aws.String(rs.Primary.ID), + _, err := tfglacier.FindVaultByName(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue } - if _, err := conn.DescribeVaultWithContext(ctx, input); err != nil { - // Verify the error is what we want - if tfawserr.ErrCodeEquals(err, glacier.ErrCodeResourceNotFoundException) { - continue - } + if err != nil { return err } - return fmt.Errorf("still exists") + + return fmt.Errorf("Glacier Vault %s still exists", rs.Primary.ID) } return nil } diff --git a/names/names.go b/names/names.go index d68b0da5c917..4a6c9c23925c 100644 --- a/names/names.go +++ b/names/names.go @@ -30,6 +30,7 @@ const ( ComprehendEndpointID = "comprehend" ComputeOptimizerEndpointID = "computeoptimizer" DSEndpointID = "ds" + GlacierEndpointID = "glacier" IdentityStoreEndpointID = "identitystore" Inspector2EndpointID = "inspector2" IVSChatEndpointID = "ivschat" diff --git a/names/names_data.csv b/names/names_data.csv index f0b1ffdc34b1..0c106d06be41 100644 --- a/names/names_data.csv +++ b/names/names_data.csv @@ -304,7 +304,7 @@ route53-recovery-readiness,route53recoveryreadiness,route53recoveryreadiness,rou route53resolver,route53resolver,route53resolver,route53resolver,,route53resolver,,,Route53Resolver,Route53Resolver,,1,,aws_route53_resolver_,aws_route53resolver_,,route53_resolver_,Route 53 Resolver,Amazon,,,,, s3api,s3api,s3,s3,,s3,,s3api,S3,S3,x,1,,aws_(canonical_user_id|s3_bucket|s3_object),aws_s3_,,s3_bucket;s3_object;canonical_user_id,S3 (Simple Storage),Amazon,,,AWS_S3_ENDPOINT,TF_AWS_S3_ENDPOINT, s3control,s3control,s3control,s3control,,s3control,,,S3Control,S3Control,,1,2,aws_(s3_account_|s3control_|s3_access_),aws_s3control_,,s3control;s3_account_;s3_access_,S3 Control,Amazon,,,,, -glacier,glacier,glacier,glacier,,glacier,,,Glacier,Glacier,,1,,,aws_glacier_,,glacier_,S3 Glacier,Amazon,,,,, +glacier,glacier,glacier,glacier,,glacier,,,Glacier,Glacier,,,2,,aws_glacier_,,glacier_,S3 Glacier,Amazon,,,,, s3outposts,s3outposts,s3outposts,s3outposts,,s3outposts,,,S3Outposts,S3Outposts,,1,,,aws_s3outposts_,,s3outposts_,S3 on Outposts,Amazon,,,,, sagemaker,sagemaker,sagemaker,sagemaker,,sagemaker,,,SageMaker,SageMaker,,1,,,aws_sagemaker_,,sagemaker_,SageMaker,Amazon,,,,, sagemaker-a2i-runtime,sagemakera2iruntime,augmentedairuntime,sagemakera2iruntime,,sagemakera2iruntime,,augmentedairuntime,SageMakerA2IRuntime,AugmentedAIRuntime,,1,,,aws_sagemakera2iruntime_,,sagemakera2iruntime_,SageMaker A2I (Augmented AI),Amazon,,,,,