Skip to content

Commit

Permalink
Merge pull request #35411 from wcmjunior/f-aws_secretsmanager_secret_…
Browse files Browse the repository at this point in the history
…versions

Data source aws_secretsmanager_secret_versions
  • Loading branch information
nam054 authored Aug 8, 2024
2 parents 2dc6a2c + b3a2baa commit a1d361f
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .changelog/35411.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_secretsmanager_secret_versions
```
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ func TestAccSecretsManagerSecretVersionDataSource_versionStage(t *testing.T) {

func testAccSecretVersionCheckDataSource(datasourceName, resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
resource, ok := s.RootModule().Resources[datasourceName]
dataSource, ok := s.RootModule().Resources[datasourceName]
if !ok {
return fmt.Errorf("root module has no resource called %s", datasourceName)
return fmt.Errorf("root module has no data source called %s", datasourceName)
}

dataSource, ok := s.RootModule().Resources[resourceName]
resource, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("root module has no resource called %s", resourceName)
}
Expand Down
123 changes: 123 additions & 0 deletions internal/service/secretsmanager/secret_versions_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package secretsmanager

import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-provider-aws/internal/create"
"github.com/hashicorp/terraform-provider-aws/internal/framework"
"github.com/hashicorp/terraform-provider-aws/internal/framework/flex"
fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @FrameworkDataSource("aws_secretsmanager_secret_versions, name="Secret Versions")
func newDataSourceSecretVersions(context.Context) (datasource.DataSourceWithConfigure, error) {
return &dataSourceSecretVersions{}, nil
}

const (
DSNameSecretVersions = "Secret Versions Data Source"
)

type dataSourceSecretVersions struct {
framework.DataSourceWithConfigure
}

func (d *dataSourceSecretVersions) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name
resp.TypeName = "aws_secretsmanager_secret_versions"
}

func (d *dataSourceSecretVersions) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
names.AttrARN: schema.StringAttribute{
Computed: true,
Validators: []validator.String{
stringvalidator.LengthBetween(20, 2048),
},
},
names.AttrName: schema.StringAttribute{
Computed: true,
},
"include_deprecated": schema.BoolAttribute{
Optional: true,
},
"secret_id": schema.StringAttribute{
Required: true,
},
"versions": schema.ListAttribute{
Computed: true,
CustomType: fwtypes.NewListNestedObjectTypeOf[dsVersionsData](ctx),
},
},
}
}

func (d *dataSourceSecretVersions) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
conn := d.Meta().SecretsManagerClient(ctx)

var data dsSecretVersionsData
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

paginator := secretsmanager.NewListSecretVersionIdsPaginator(conn, &secretsmanager.ListSecretVersionIdsInput{
SecretId: aws.String(data.SecretID.ValueString()),
})

var out secretsmanager.ListSecretVersionIdsOutput
commonFieldsSet := false
for paginator.HasMorePages() {
page, err := paginator.NextPage(ctx)
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.SecretsManager, create.ErrActionReading, DSNameSecretVersions, data.Arn.String(), err),
err.Error(),
)
return
}

if page != nil && len(page.Versions) > 0 {
if !commonFieldsSet {
out.ARN = page.ARN
out.Name = page.Name
commonFieldsSet = true
}
out.Versions = append(out.Versions, page.Versions...)
}
}

resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

type dsSecretVersionsData struct {
Arn types.String `tfsdk:"arn"`
Name types.String `tfsdk:"name"`
IncludeDeprecated types.Bool `tfsdk:"include_deprecated"`
SecretID types.String `tfsdk:"secret_id"`
Versions fwtypes.ListNestedObjectValueOf[dsVersionsData] `tfsdk:"versions"`
}

type dsVersionsData struct {
CreatedDate timetypes.RFC3339 `tfsdk:"created_time"`
LastAccessedDate types.String `tfsdk:"last_accessed_date"`
VersionID types.String `tfsdk:"version_id"`
VersionStages fwtypes.ListValueOf[types.String] `tfsdk:"version_stages"`
}
100 changes: 100 additions & 0 deletions internal/service/secretsmanager/secret_versions_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package secretsmanager_test

import (
"fmt"
"testing"

sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/names"
)

func TestAccSecretsManagerSecretVersionsDataSource_basic(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resource1Name := "aws_secretsmanager_secret_version.test"
dataSourceName := "data.aws_secretsmanager_secret_versions.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSecretVersionsDataSourceConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "secret_id", resource1Name, "secret_id"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.#"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.0.%"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.0.created_time"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.0.version_id"),
),
},
},
})
}

func TestAccSecretsManagerSecretVersionsDataSource_emptyVer(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceName := "data.aws_secretsmanager_secret_versions.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSecretVersionsDataSourceConfig_emptyVersion(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "versions.#", acctest.Ct0),
),
},
},
})
}

func testAccSecretVersionsDataSourceConfig_basic(rName string) string {
return fmt.Sprintf(`
resource "aws_secretsmanager_secret" "test" {
name = %[1]q
}
resource "aws_secretsmanager_secret_version" "test" {
secret_id = aws_secretsmanager_secret.test.id
secret_string = "test-string"
}
resource "aws_secretsmanager_secret_version" "test2" {
depends_on = [aws_secretsmanager_secret_version.test]
secret_id = aws_secretsmanager_secret.test.id
secret_string = "test-string2"
}
data "aws_secretsmanager_secret_versions" "test" {
depends_on = [aws_secretsmanager_secret_version.test]
secret_id = aws_secretsmanager_secret.test.id
}
`, rName)
}

func testAccSecretVersionsDataSourceConfig_emptyVersion(rName string) string {
return fmt.Sprintf(`
resource "aws_secretsmanager_secret" "test" {
name = "%[1]s"
}
data "aws_secretsmanager_secret_versions" "test" {
secret_id = aws_secretsmanager_secret.test.id
}
`, rName)
}
7 changes: 6 additions & 1 deletion internal/service/secretsmanager/service_package_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions website/docs/d/secretsmanager_secret_versions.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
subcategory: "Secrets Manager"
layout: "aws"
page_title: "AWS: aws_secretsmanager_secret_versions"
description: |-
Retrieve the versions of a Secrets Manager secret
---

# Data Source: aws_secretsmanager_secret_versions

Retrieve the versions of a Secrets Manager secret. To retrieve secret metadata, see the data sources [`aws_secretsmanager_secret`](/docs/providers/aws/d/secretsmanager_secret.html) and [`aws_secretsmanager_secret_version`](/docs/providers/aws/d/secretsmanager_secret_version.html).

## Example Usage

### Retrieve All Versions of a Secret

By default, this data sources retrieves all versions of a secret.

```terraform
data "aws_secretsmanager_secret_versions" "secret-versions" {
secret_id = data.aws_secretsmanager_secret.example.id
}
```

### Retrieve Specific Secret Version

```terraform
data "aws_secretsmanager_secret_version" "by-version-stage" {
secret_id = data.aws_secretsmanager_secret.example.id
version_stage = "example"
}
```

### Handling Key-Value Secret Strings in JSON

Reading key-value pairs from JSON back into a native Terraform map can be accomplished in Terraform 0.12 and later with the [`jsondecode()` function](https://www.terraform.io/docs/configuration/functions/jsondecode.html):

```terraform
output "example" {
value = jsondecode(data.aws_secretsmanager_secret_version.example.secret_string)["key1"]
}
```

## Argument Reference

* `secret_id` - (Required) Specifies the secret containing the version that you want to retrieve. You can specify either the ARN or the friendly name of the secret.
* `include_deprecated` - (Optional) If true, all deprecated secret versions are included in the response.
If false, no deprecated secret versions are included in the response. If no value is specified, the default value is `false`.

## Attribute Reference

This data source exports the following attributes in addition to the arguments above:

* `arn` - ARN of the secret.
* `id` - Secret id.
* `versions` - List of the versions of the secret. Attributes are specified below.

### versions

* `created_date` - Date and time this version of the secret was created.
* `last_accessed_date` - Date that this version of the secret was last accessed.
* `version_id` - Unique version identifier of this version of the secret.
* `version_stage` - Staging label attached to the version.

0 comments on commit a1d361f

Please sign in to comment.