Skip to content

Commit

Permalink
d/aws_polly_voices: new data source (#34916)
Browse files Browse the repository at this point in the history
This data source will allow practitioners to list available voices from AWS Polly.
  • Loading branch information
jar-b authored Dec 14, 2023
1 parent 1e55ca6 commit de5e8e5
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/34916.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_polly_voices
```
7 changes: 6 additions & 1 deletion internal/service/polly/service_package_gen.go

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

153 changes: 153 additions & 0 deletions internal/service/polly/voices_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package polly

import (
"context"

"github.com/aws/aws-sdk-go-v2/service/polly"
awstypes "github.com/aws/aws-sdk-go-v2/service/polly/types"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"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(name="Voices")
func newDataSourceVoices(context.Context) (datasource.DataSourceWithConfigure, error) {
return &dataSourceVoices{}, nil
}

const (
DSNameVoices = "Voices Data Source"
)

type dataSourceVoices struct {
framework.DataSourceWithConfigure
}

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

func (d *dataSourceVoices) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"engine": schema.StringAttribute{
CustomType: fwtypes.StringEnumType[awstypes.Engine](),
Optional: true,
},
"id": framework.IDAttribute(),
"include_additional_language_codes": schema.BoolAttribute{
Optional: true,
},
"language_code": schema.StringAttribute{
CustomType: fwtypes.StringEnumType[awstypes.LanguageCode](),
Optional: true,
},
},
Blocks: map[string]schema.Block{
"voices": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[voicesData](ctx),
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"additional_language_codes": schema.ListAttribute{
CustomType: fwtypes.ListOfStringType,
ElementType: types.StringType,
Computed: true,
},
"gender": schema.StringAttribute{
Computed: true,
},
"id": schema.StringAttribute{
Computed: true,
},
"language_code": schema.StringAttribute{
Computed: true,
},
"language_name": schema.StringAttribute{
Computed: true,
},
"name": schema.StringAttribute{
Computed: true,
},
"supported_engines": schema.ListAttribute{
CustomType: fwtypes.ListOfStringType,
ElementType: types.StringType,
Computed: true,
},
},
},
},
},
}
}
func (d *dataSourceVoices) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
conn := d.Meta().PollyClient(ctx)

var data dataSourceVoicesData
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
data.ID = types.StringValue(d.Meta().AccountID)

input := &polly.DescribeVoicesInput{}
resp.Diagnostics.Append(flex.Expand(ctx, data, input)...)
if resp.Diagnostics.HasError() {
return
}

// No paginator helper so pagination must be done manually
out := &polly.DescribeVoicesOutput{}
for {
page, err := conn.DescribeVoices(ctx, input)
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.Polly, create.ErrActionReading, DSNameVoices, data.ID.String(), err),
err.Error(),
)
return
}

if page == nil {
break
}

if len(page.Voices) > 0 {
out.Voices = append(out.Voices, page.Voices...)
}

input.NextToken = page.NextToken
if page.NextToken == nil {
break
}
}

resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...)

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

type dataSourceVoicesData struct {
Engine fwtypes.StringEnum[awstypes.Engine] `tfsdk:"engine"`
ID types.String `tfsdk:"id"`
IncludeAdditionalLanguageCodes types.Bool `tfsdk:"include_additional_language_codes"`
LanguageCode fwtypes.StringEnum[awstypes.LanguageCode] `tfsdk:"language_code"`
Voices fwtypes.ListNestedObjectValueOf[voicesData] `tfsdk:"voices"`
}

type voicesData struct {
AdditionalLanguageCodes fwtypes.ListValueOf[types.String] `tfsdk:"additional_language_codes"`
Gender types.String `tfsdk:"gender"`
ID types.String `tfsdk:"id"`
LanguageCode types.String `tfsdk:"language_code"`
LanguageName types.String `tfsdk:"language_name"`
Name types.String `tfsdk:"name"`
SupportedEngines fwtypes.ListValueOf[types.String] `tfsdk:"supported_engines"`
}
84 changes: 84 additions & 0 deletions internal/service/polly/voices_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package polly_test

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go-v2/service/polly/types"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/names"
)

func TestAccPollyVoicesDataSource_basic(t *testing.T) {
ctx := acctest.Context(t)
dataSourceName := "data.aws_polly_voices.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, names.PollyEndpointID)
},
ErrorCheck: acctest.ErrorCheck(t, names.PollyEndpointID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccVoicesDataSourceConfig_basic(),
Check: resource.ComposeTestCheckFunc(
// verify a known voice is returned in the results
resource.TestCheckTypeSetElemNestedAttrs(dataSourceName, "voices.*", map[string]string{
"gender": "Female",
"language_code": "en-US",
"name": "Kendra",
}),
),
},
},
})
}

func TestAccPollyVoicesDataSource_languageCode(t *testing.T) {
ctx := acctest.Context(t)
dataSourceName := "data.aws_polly_voices.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, names.PollyEndpointID)
},
ErrorCheck: acctest.ErrorCheck(t, names.PollyEndpointID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccVoicesDataSourceConfig_languageCode(string(types.LanguageCodeEnUs)),
Check: resource.ComposeTestCheckFunc(
// verify a known voice is returned in the results
resource.TestCheckTypeSetElemNestedAttrs(dataSourceName, "voices.*", map[string]string{
"gender": "Female",
"language_code": "en-US",
"name": "Kendra",
}),
),
},
},
})
}

func testAccVoicesDataSourceConfig_basic() string {
return `
data "aws_polly_voices" "test" {}
`
}

func testAccVoicesDataSourceConfig_languageCode(languageCode string) string {
return fmt.Sprintf(`
data "aws_polly_voices" "test" {
language_code = %[1]q
}
`, languageCode)
}
1 change: 1 addition & 0 deletions names/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const (
ObservabilityAccessManagerEndpointID = "oam"
OpenSearchServerlessEndpointID = "aoss"
PipesEndpointID = "pipes"
PollyEndpointID = "polly"
PricingEndpointID = "pricing"
QLDBEndpointID = "qldb"
RedshiftDataEndpointID = "redshift-data"
Expand Down
54 changes: 54 additions & 0 deletions website/docs/d/polly_voices.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
subcategory: "Polly"
layout: "aws"
page_title: "AWS: aws_polly_voices"
description: |-
Terraform data source for managing an AWS Polly Voices.
---

# Data Source: aws_polly_voices

Terraform data source for managing an AWS Polly Voices.

## Example Usage

### Basic Usage

```terraform
data "aws_polly_voices" "example" {}
```

### With Language Code

```terraform
data "aws_polly_voices" "example" {
language_code = "en-GB"
}
```

## Argument Reference

The following arguments are optional:

* `engine` - (Optional) Engine used by Amazon Polly when processing input text for speech synthesis. Valid values are `standard`, `neural`, and `long-form`.
* `include_additional_language_codes` - (Optional) Whether to return any bilingual voices that use the specified language as an additional language.
* `language_code` - (Optional) Language identification tag for filtering the list of voices returned. If not specified, all available voices are returned.

## Attribute Reference

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

* `id` - AWS account ID.
* `voices` - List of voices with their properties. See [`voices` Attribute Reference](#voices-attribute-reference) below.

### `voices` Attribute Reference

See the [AWS Polly Voice documentation](https://docs.aws.amazon.com/polly/latest/dg/API_Voice.html) for additional details.

* `additional_language_codes` - Additional codes for languages available for the specified voice in addition to its default language.
* `gender` - Gender of the voice.
* `id` - Amazon Polly assigned voice ID.
* `language_code` - Language code of the voice.
* `language_name` - Human readable name of the language in English.
* `name` - Name of the voice.
* `supported_engines` - Specifies which engines are supported by a given voice.

0 comments on commit de5e8e5

Please sign in to comment.