diff --git a/.changelog/25698.txt b/.changelog/25698.txt new file mode 100644 index 00000000000..b83c7c521fb --- /dev/null +++ b/.changelog/25698.txt @@ -0,0 +1,3 @@ +```release-note:new-resource + aws_transcribe_language_model +``` \ No newline at end of file diff --git a/internal/provider/provider.go b/internal/provider/provider.go index c65e2386c81..3f407e408e9 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -2054,6 +2054,7 @@ func New(_ context.Context) (*schema.Provider, error) { "aws_timestreamwrite_database": timestreamwrite.ResourceDatabase(), "aws_timestreamwrite_table": timestreamwrite.ResourceTable(), + "aws_transcribe_language_model": transcribe.ResourceLanguageModel(), "aws_transcribe_medical_vocabulary": transcribe.ResourceMedicalVocabulary(), "aws_transcribe_vocabulary": transcribe.ResourceVocabulary(), "aws_transcribe_vocabulary_filter": transcribe.ResourceVocabularyFilter(), diff --git a/internal/service/transcribe/language_model.go b/internal/service/transcribe/language_model.go new file mode 100644 index 00000000000..5ce03e10292 --- /dev/null +++ b/internal/service/transcribe/language_model.go @@ -0,0 +1,337 @@ +package transcribe + +import ( + "context" + "errors" + "fmt" + "log" + "strings" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/arn" + "github.com/aws/aws-sdk-go-v2/service/transcribe" + "github.com/aws/aws-sdk-go-v2/service/transcribe/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "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/enum" + 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" +) + +func ResourceLanguageModel() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceLanguageModelCreate, + ReadWithoutTimeout: resourceLanguageModelRead, + UpdateWithoutTimeout: resourceLanguageModelUpdate, + DeleteWithoutTimeout: resourceLanguageModelDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(600 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "base_model_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[types.BaseModelName](), + }, + "input_data_config": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "data_access_role_arn": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: validation.ToDiagFunc(verify.ValidARN), + }, + "s3_uri": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "tuning_data_s3_uri": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + }, + }, + }, + "language_code": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateDiagFunc: enum.Validate[types.LanguageCode](), + }, + "model_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "tags": tftags.TagsSchema(), + "tags_all": tftags.TagsSchemaComputed(), + }, + + CustomizeDiff: verify.SetTagsDiff, + } +} + +const ( + ResNameLanguageModel = "Language Model" + + propagationTimeout = 2 * time.Minute +) + +func resourceLanguageModelCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).TranscribeConn + + in := &transcribe.CreateLanguageModelInput{ + BaseModelName: types.BaseModelName(d.Get("base_model_name").(string)), + LanguageCode: types.CLMLanguageCode(d.Get("language_code").(string)), + ModelName: aws.String(d.Get("model_name").(string)), + } + + if v, ok := d.GetOk("input_data_config"); ok && len(v.([]interface{})) > 0 { + in.InputDataConfig = expandInputDataConfig(v.([]interface{})) + } + + defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig + tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))) + + if len(tags) > 0 { + in.Tags = Tags(tags.IgnoreAWS()) + } + + outputRaw, err := tfresource.RetryWhen(propagationTimeout, + func() (interface{}, error) { + return conn.CreateLanguageModel(ctx, in) + }, + func(err error) (bool, error) { + var bre *types.BadRequestException + if errors.As(err, &bre) { + return strings.Contains(bre.ErrorMessage(), "Make sure that you have read permission"), err + } + return false, err + }, + ) + + if err != nil { + return names.DiagError(names.Transcribe, names.ErrActionCreating, ResNameLanguageModel, d.Get("model_name").(string), err) + } + + d.SetId(aws.ToString(outputRaw.(*transcribe.CreateLanguageModelOutput).ModelName)) + + if _, err := waitLanguageModelCreated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { + return names.DiagError(names.Transcribe, names.ErrActionWaitingForCreation, ResNameLanguageModel, d.Get("model_name").(string), err) + } + + return resourceLanguageModelRead(ctx, d, meta) +} + +func resourceLanguageModelRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).TranscribeConn + + out, err := FindLanguageModelByName(ctx, conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Transcribe LanguageModel (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return names.DiagError(names.Transcribe, names.ErrActionReading, ResNameLanguageModel, d.Id(), err) + } + + arn := arn.ARN{ + AccountID: meta.(*conns.AWSClient).AccountID, + Partition: meta.(*conns.AWSClient).Partition, + Service: "transcribe", + Region: meta.(*conns.AWSClient).Region, + Resource: fmt.Sprintf("language-model/%s", d.Id()), + }.String() + + d.Set("arn", arn) + d.Set("base_model_name", out.BaseModelName) + d.Set("language_code", out.LanguageCode) + d.Set("model_name", out.ModelName) + + if err := d.Set("input_data_config", flattenInputDataConfig(out.InputDataConfig)); err != nil { + return names.DiagError(names.Transcribe, names.ErrActionSetting, ResNameLanguageModel, d.Id(), err) + } + + tags, err := ListTags(ctx, conn, arn) + if err != nil { + return names.DiagError(names.Transcribe, names.ErrActionReading, ResNameLanguageModel, d.Id(), err) + } + + defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig + ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig + tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig) + + //lintignore:AWSR002 + if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { + return names.DiagError(names.Transcribe, names.ErrActionSetting, ResNameLanguageModel, d.Id(), err) + } + + if err := d.Set("tags_all", tags.Map()); err != nil { + return names.DiagError(names.Transcribe, names.ErrActionSetting, ResNameLanguageModel, d.Id(), err) + } + + return nil +} + +func resourceLanguageModelUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).TranscribeConn + + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") + + if err := UpdateTags(ctx, conn, d.Get("arn").(string), o, n); err != nil { + return names.DiagError(names.Transcribe, names.ErrActionUpdating, ResNameLanguageModel, d.Id(), err) + } + } + + return resourceLanguageModelRead(ctx, d, meta) +} + +func resourceLanguageModelDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).TranscribeConn + + log.Printf("[INFO] Deleting Transcribe LanguageModel %s", d.Id()) + + _, err := conn.DeleteLanguageModel(ctx, &transcribe.DeleteLanguageModelInput{ + ModelName: aws.String(d.Id()), + }) + + var resourceNotFoundException *types.NotFoundException + if errors.As(err, &resourceNotFoundException) { + return nil + } + + if err != nil { + return names.DiagError(names.Transcribe, names.ErrActionDeleting, ResNameLanguageModel, d.Id(), err) + } + + return nil +} + +func waitLanguageModelCreated(ctx context.Context, conn *transcribe.Client, id string, timeout time.Duration) (*types.LanguageModel, error) { + stateConf := &resource.StateChangeConf{ + Pending: enum.Slice(types.ModelStatusInProgress), + Target: enum.Slice(types.ModelStatusCompleted), + Refresh: statusLanguageModel(ctx, conn, id), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*types.LanguageModel); ok { + return out, err + } + + return nil, err +} + +func statusLanguageModel(ctx context.Context, conn *transcribe.Client, name string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := FindLanguageModelByName(ctx, conn, name) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return out, string(out.ModelStatus), nil + } +} + +func FindLanguageModelByName(ctx context.Context, conn *transcribe.Client, id string) (*types.LanguageModel, error) { + in := &transcribe.DescribeLanguageModelInput{ + ModelName: aws.String(id), + } + + out, err := conn.DescribeLanguageModel(ctx, in) + + var bre *types.BadRequestException + if errors.As(err, &bre) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + if out == nil || out.LanguageModel == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out.LanguageModel, nil +} + +func flattenInputDataConfig(apiObjects *types.InputDataConfig) []interface{} { + if apiObjects == nil { + return nil + } + + m := map[string]interface{}{ + "data_access_role_arn": apiObjects.DataAccessRoleArn, + "s3_uri": apiObjects.S3Uri, + } + + if aws.ToString(apiObjects.TuningDataS3Uri) != "" { + m["tuning_data_s3_uri"] = apiObjects.TuningDataS3Uri + } + + return []interface{}{m} +} + +func expandInputDataConfig(tfList []interface{}) *types.InputDataConfig { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + s := &types.InputDataConfig{} + + i := tfList[0].(map[string]interface{}) + + if val, ok := i["data_access_role_arn"]; ok { + s.DataAccessRoleArn = aws.String(val.(string)) + } + + if val, ok := i["s3_uri"]; ok { + s.S3Uri = aws.String(val.(string)) + } + + if val, ok := i["tuning_data_s3_uri"]; ok && val != "" { + s.TuningDataS3Uri = aws.String(val.(string)) + } + + return s +} diff --git a/internal/service/transcribe/language_model_test.go b/internal/service/transcribe/language_model_test.go new file mode 100644 index 00000000000..bccdbccdd19 --- /dev/null +++ b/internal/service/transcribe/language_model_test.go @@ -0,0 +1,313 @@ +package transcribe_test + +import ( + "context" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/transcribe" + "github.com/aws/aws-sdk-go-v2/service/transcribe/types" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tftranscribe "github.com/hashicorp/terraform-provider-aws/internal/service/transcribe" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccTranscribeLanguageModel_basic(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var languageModel types.LanguageModel + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_transcribe_language_model.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(t) + acctest.PreCheckPartitionHasService(names.TranscribeEndpointID, t) + testAccLanguageModelsPreCheck(t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLanguageModelDestroy, + Steps: []resource.TestStep{ + { + Config: testAccLanguageModelConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckLanguageModelExists(resourceName, &languageModel), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "base_model_name", "NarrowBand"), + resource.TestCheckResourceAttr(resourceName, "language_code", "en-US"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccTranscribeLanguageModel_updateTags(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var languageModel types.LanguageModel + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_transcribe_language_model.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(t) + acctest.PreCheckPartitionHasService(names.TranscribeEndpointID, t) + testAccLanguageModelsPreCheck(t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLanguageModelDestroy, + Steps: []resource.TestStep{ + { + Config: testAccLanguageModelConfig_tags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckLanguageModelExists(resourceName, &languageModel), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + Config: testAccLanguageModelConfig_tags2(rName, "key1", "value1", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckLanguageModelExists(resourceName, &languageModel), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccLanguageModelConfig_tags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckLanguageModelExists(resourceName, &languageModel), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + +func TestAccTranscribeLanguageModel_disappears(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var languageModel types.LanguageModel + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_transcribe_language_model.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(t) + acctest.PreCheckPartitionHasService(names.TranscribeEndpointID, t) + testAccLanguageModelsPreCheck(t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLanguageModelDestroy, + Steps: []resource.TestStep{ + { + Config: testAccLanguageModelConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckLanguageModelExists(resourceName, &languageModel), + acctest.CheckResourceDisappears(acctest.Provider, tftranscribe.ResourceLanguageModel(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckLanguageModelDestroy(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeConn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_transcribe_language_model" { + continue + } + + _, err := tftranscribe.FindLanguageModelByName(context.Background(), conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + } + + return nil +} + +func testAccCheckLanguageModelExists(name string, languageModel *types.LanguageModel) 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 Transcribe LanguageModel is set") + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeConn + resp, err := tftranscribe.FindLanguageModelByName(context.Background(), conn, rs.Primary.ID) + + if err != nil { + return fmt.Errorf("Error describing Transcribe LanguageModel: %s", err.Error()) + } + + *languageModel = *resp + + return nil + } +} + +func testAccLanguageModelsPreCheck(t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeConn + + input := &transcribe.ListLanguageModelsInput{} + + _, err := conn.ListLanguageModels(context.Background(), input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccLanguageModelBaseConfig(rName string) string { + return fmt.Sprintf(` +data "aws_iam_policy_document" "test" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["transcribe.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = data.aws_iam_policy_document.test.json +} + +resource "aws_iam_role_policy" "test_policy" { + name = %[1]q + role = aws_iam_role.test.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = [ + "s3:GetObject", + "s3:ListBucket", + ] + Effect = "Allow" + Resource = ["*"] + }, + ] + }) +} + +resource "aws_s3_bucket" "test" { + bucket = %[1]q + force_destroy = true +} + +resource "aws_s3_object" "object" { + bucket = aws_s3_bucket.test.id + key = "transcribe/test1.txt" + source = "test-fixtures/language_model_test1.txt" +} +`, rName) +} + +func testAccLanguageModelConfig_basic(rName string) string { + return acctest.ConfigCompose( + testAccLanguageModelBaseConfig(rName), + fmt.Sprintf(` +resource "aws_transcribe_language_model" "test" { + model_name = %[1]q + base_model_name = "NarrowBand" + + input_data_config { + data_access_role_arn = aws_iam_role.test.arn + s3_uri = "s3://${aws_s3_bucket.test.id}/transcribe/" + } + + language_code = "en-US" + + tags = { + tag1 = "value1" + } +} +`, rName)) +} + +func testAccLanguageModelConfig_tags1(rName, key1, value1 string) string { + return acctest.ConfigCompose( + testAccLanguageModelBaseConfig(rName), + fmt.Sprintf(` +resource "aws_transcribe_language_model" "test" { + model_name = %[1]q + base_model_name = "NarrowBand" + + input_data_config { + data_access_role_arn = aws_iam_role.test.arn + s3_uri = "s3://${aws_s3_bucket.test.id}/transcribe/" + } + + language_code = "en-US" + + tags = { + %[2]q = %[3]q + } +} +`, rName, key1, value1)) +} + +func testAccLanguageModelConfig_tags2(rName, key1, value1, key2, value2 string) string { + return acctest.ConfigCompose( + testAccLanguageModelBaseConfig(rName), + fmt.Sprintf(` +resource "aws_transcribe_language_model" "test" { + model_name = %[1]q + base_model_name = "NarrowBand" + + input_data_config { + data_access_role_arn = aws_iam_role.test.arn + s3_uri = "s3://${aws_s3_bucket.test.id}/transcribe/" + } + + language_code = "en-US" + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, key1, value1, key2, value2)) +} diff --git a/internal/service/transcribe/sweep.go b/internal/service/transcribe/sweep.go index e695d8e0111..e19fb74a16f 100644 --- a/internal/service/transcribe/sweep.go +++ b/internal/service/transcribe/sweep.go @@ -17,6 +17,15 @@ import ( ) func init() { + resource.AddTestSweepers("aws_transcribe_language_model", &resource.Sweeper{ + Name: "aws_transcribe_language_model", + F: sweepLanguageModels, + Dependencies: []string{ + "aws_s3_bucket", + "aws_iam_role", + }, + }) + resource.AddTestSweepers("aws_transcribe_medical_vocabulary", &resource.Sweeper{ Name: "aws_transcribe_medical_vocabulary", F: sweepMedicalVocabularies, @@ -42,6 +51,56 @@ func init() { }) } +func sweepLanguageModels(region string) error { + client, err := sweep.SharedRegionalSweepClient(region) + if err != nil { + fmt.Errorf("error getting client: %s", err) + } + + ctx := context.Background() + conn := client.(*conns.AWSClient).TranscribeConn + sweepResources := make([]*sweep.SweepResource, 0) + in := &transcribe.ListLanguageModelsInput{} + var errs *multierror.Error + + pages := transcribe.NewListLanguageModelsPaginator(conn, in) + + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if sweep.SkipSweepError(err) { + log.Println("[WARN] Skipping Transcribe Language Models sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error retrieving Transcribe Language Models: %w", err) + } + + for _, model := range page.Models { + name := aws.ToString(model.ModelName) + log.Printf("[INFO] Deleting Transcribe Language Model: %s", name) + + r := ResourceLanguageModel() + d := r.Data(nil) + d.SetId(name) + + sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) + } + } + + if err := sweep.SweepOrchestrator(sweepResources); err != nil { + errs = multierror.Append(errs, fmt.Errorf("error sweeping Transcribe Language Models for %s: %w", region, err)) + } + + if sweep.SkipSweepError(err) { + log.Printf("[WARN] Skipping Transcribe Language Models sweep for %s: %s", region, errs) + return nil + } + + return errs.ErrorOrNil() +} + func sweepMedicalVocabularies(region string) error { client, err := sweep.SharedRegionalSweepClient(region) if err != nil { diff --git a/internal/service/transcribe/test-fixtures/language_model_test1.txt b/internal/service/transcribe/test-fixtures/language_model_test1.txt new file mode 100644 index 00000000000..f03f1b5ed9c --- /dev/null +++ b/internal/service/transcribe/test-fixtures/language_model_test1.txt @@ -0,0 +1,11 @@ +The PS5 will feature a custom eight-core AMD Zen 2 CPU clocked at 3.5GHz (variable frequency) and a custom GPU based on AMD’s RDNA 2 architecture hardware that promises 10.28 teraflops and 36 compute units clocked at 2.23GHz (also variable frequency). + +It’ll also have 16GB of GDDR6 RAM and a custom 825GB SSD that Sony has previously promised will offer super-fast loading times in gameplay, via Eurogamer. + +One of the biggest technical updates in the PS5 was already announced last year: a switch to SSD storage for the console’s main hard drive, which Sony says will result in dramatically faster load times. + +A previous demo showed Spider-Man loading levels in less than a second on the PS5, compared to the roughly eight seconds it took on a PS4.PlayStation hardware lead Mark Cerny dove into some of the details about those SSD goals at the announcement. + +Where it took a PS4 around 20 seconds to load a single gigabyte of data, the goal with the PS5’s SSD was to enable loading + +five gigabytes of data in a single second. diff --git a/website/docs/r/transcribe_language_model.html.markdown b/website/docs/r/transcribe_language_model.html.markdown new file mode 100644 index 00000000000..664350bfcf0 --- /dev/null +++ b/website/docs/r/transcribe_language_model.html.markdown @@ -0,0 +1,122 @@ +--- +subcategory: "Transcribe" +layout: "aws" +page_title: "AWS: aws_transcribe_language_model" +description: |- + Terraform resource for managing an AWS Transcribe LanguageModel. +--- + +# Resource: aws_transcribe_language_model + +Terraform resource for managing an AWS Transcribe LanguageModel. + +-> This resource can take a significant amount of time to provision. See Language Model [FAQ](https://aws.amazon.com/transcribe/faqs/) for more details. + +## Example Usage + +### Basic Usage + +```terraform +data "aws_iam_policy_document" "example" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["transcribe.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "example" { + name = "example" + assume_role_policy = data.aws_iam_policy_document.example.json +} + +resource "aws_iam_role_policy" "test_policy" { + name = "example" + role = aws_iam_role.example.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = [ + "s3:GetObject", + "s3:ListBucket", + ] + Effect = "Allow" + Resource = ["*"] + }, + ] + }) +} + +resource "aws_s3_bucket" "example" { + bucket = "example-transcribe" + force_destroy = true +} + +resource "aws_s3_object" "object" { + bucket = aws_s3_bucket.example.id + key = "transcribe/test1.txt" + source = "test1.txt" +} + +resource "aws_transcribe_language_model" "example" { + model_name = "example" + base_model_name = "NarrowBand" + + input_data_config { + data_access_role_arn = aws_iam_role.example.arn + s3_uri = "s3://${aws_s3_bucket.example.id}/transcribe/" + } + + language_code = "en-US" + + tags = { + ENVIRONMENT = "development" + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `base_model_name` - (Required) Name of reference base model. +* `input_data_config` - (Required) The input data config for the LanguageModel. See [Input Data Config](#input-data-config) for more details. +* `language_code` - (Required) The language code you selected for your language model. Refer to the [supported languages](https://docs.aws.amazon.com/transcribe/latest/dg/supported-languages.html) page for accepted codes. +* `model_name` - (Required) The model name. + +### Input Data Config + +* `data_access_role_arn` - (Required) IAM role with access to S3 bucket. +* `s3_uri` - (Required) S3 URI where training data is located. +* `tuning_data_s3_uri` - (Optional) S3 URI where tuning data is located. + + +The following arguments are optional: + +* `tags` - (Optional) A map of tags to assign to the LanguageModel. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - LanguageModel name. +* `arn` - ARN of the LanguageModel. + +## Timeouts + +`aws_transcribe_language_model` provides the following [Timeouts](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts) configuration options: + +* `create` - (Optional, Default: `600m`) + +## Import + +Transcribe LanguageModel can be imported using the `model_name`, e.g., + +``` +$ terraform import aws_transcribe_language_model.example example-name +```