diff --git a/.changelog/44445.txt b/.changelog/44445.txt new file mode 100644 index 000000000000..49041231ec1c --- /dev/null +++ b/.changelog/44445.txt @@ -0,0 +1,3 @@ +```release-note:new-action +aws_transcribe_start_transcription_job +``` diff --git a/internal/service/transcribe/service_package_gen.go b/internal/service/transcribe/service_package_gen.go index 2a2667ced41c..6e52d43f88bc 100644 --- a/internal/service/transcribe/service_package_gen.go +++ b/internal/service/transcribe/service_package_gen.go @@ -17,6 +17,17 @@ import ( type servicePackage struct{} +func (p *servicePackage) Actions(ctx context.Context) []*inttypes.ServicePackageAction { + return []*inttypes.ServicePackageAction{ + { + Factory: newStartTranscriptionJobAction, + TypeName: "aws_transcribe_start_transcription_job", + Name: "Start Transcription Job", + Region: unique.Make(inttypes.ResourceRegionDefault()), + }, + } +} + func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*inttypes.ServicePackageFrameworkDataSource { return []*inttypes.ServicePackageFrameworkDataSource{} } diff --git a/internal/service/transcribe/start_transcription_job_action.go b/internal/service/transcribe/start_transcription_job_action.go new file mode 100644 index 000000000000..7ca04345ba7d --- /dev/null +++ b/internal/service/transcribe/start_transcription_job_action.go @@ -0,0 +1,284 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package transcribe + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/transcribe" + awstypes "github.com/aws/aws-sdk-go-v2/service/transcribe/types" + "github.com/hashicorp/terraform-plugin-framework/action" + "github.com/hashicorp/terraform-plugin-framework/action/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-provider-aws/internal/actionwait" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +const ( + transcriptionJobPollInterval = 5 * time.Second + transcriptionJobProgressInterval = 30 * time.Second +) + +// @Action(aws_transcribe_start_transcription_job, name="Start Transcription Job") +func newStartTranscriptionJobAction(_ context.Context) (action.ActionWithConfigure, error) { + return &startTranscriptionJobAction{}, nil +} + +var ( + _ action.Action = (*startTranscriptionJobAction)(nil) +) + +type startTranscriptionJobAction struct { + framework.ActionWithModel[startTranscriptionJobActionModel] +} + +type startTranscriptionJobActionModel struct { + framework.WithRegionModel + TranscriptionJobName types.String `tfsdk:"transcription_job_name"` + MediaFileUri types.String `tfsdk:"media_file_uri"` + LanguageCode fwtypes.StringEnum[awstypes.LanguageCode] `tfsdk:"language_code"` + IdentifyLanguage types.Bool `tfsdk:"identify_language"` + IdentifyMultipleLanguages types.Bool `tfsdk:"identify_multiple_languages"` + MediaFormat fwtypes.StringEnum[awstypes.MediaFormat] `tfsdk:"media_format"` + MediaSampleRateHertz types.Int64 `tfsdk:"media_sample_rate_hertz"` + OutputBucketName types.String `tfsdk:"output_bucket_name"` + OutputKey types.String `tfsdk:"output_key"` + Timeout types.Int64 `tfsdk:"timeout"` +} + +func (a *startTranscriptionJobAction) Schema(ctx context.Context, req action.SchemaRequest, resp *action.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Starts an Amazon Transcribe transcription job to transcribe audio from a media file. The media file must be uploaded to an Amazon S3 bucket before starting the transcription job.", + Attributes: map[string]schema.Attribute{ + "transcription_job_name": schema.StringAttribute{ + Description: "A unique name for the transcription job within your AWS account.", + Required: true, + }, + "media_file_uri": schema.StringAttribute{ + Description: "The Amazon S3 location of the media file to transcribe (e.g., s3://bucket-name/file.mp3).", + Required: true, + }, + names.AttrLanguageCode: schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.LanguageCode](), + Description: "The language code for the language used in the input media file. Required if identify_language and identify_multiple_languages are both false.", + Optional: true, + }, + "identify_language": schema.BoolAttribute{ + Description: "Enable automatic language identification for single-language media files. Cannot be used with identify_multiple_languages.", + Optional: true, + }, + "identify_multiple_languages": schema.BoolAttribute{ + Description: "Enable automatic language identification for multi-language media files. Cannot be used with identify_language.", + Optional: true, + }, + "media_format": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.MediaFormat](), + Description: "The format of the input media file. If not specified, Amazon Transcribe will attempt to determine the format automatically.", + Optional: true, + }, + "media_sample_rate_hertz": schema.Int64Attribute{ + Description: "The sample rate of the input media file in Hertz. If not specified, Amazon Transcribe will attempt to determine the sample rate automatically.", + Optional: true, + }, + "output_bucket_name": schema.StringAttribute{ + Description: "The name of the Amazon S3 bucket where you want your transcription output stored. If not specified, output is stored in a service-managed bucket.", + Optional: true, + }, + "output_key": schema.StringAttribute{ + Description: "The Amazon S3 object key for your transcription output. If not specified, a default key is generated.", + Optional: true, + }, + names.AttrTimeout: schema.Int64Attribute{ + Description: "Maximum time in seconds to wait for the transcription job to start. Defaults to 300 seconds (5 minutes).", + Optional: true, + }, + }, + } +} + +func (a *startTranscriptionJobAction) Invoke(ctx context.Context, req action.InvokeRequest, resp *action.InvokeResponse) { + var config startTranscriptionJobActionModel + + // Parse configuration + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + // Get AWS client + conn := a.Meta().TranscribeClient(ctx) + + transcriptionJobName := config.TranscriptionJobName.ValueString() + mediaFileUri := config.MediaFileUri.ValueString() + + // Set default timeout + timeout := 5 * time.Minute + if !config.Timeout.IsNull() { + timeout = time.Duration(config.Timeout.ValueInt64()) * time.Second + } + + tflog.Info(ctx, "Starting transcription job action", map[string]any{ + "transcription_job_name": transcriptionJobName, + "media_file_uri": mediaFileUri, + "timeout_seconds": int64(timeout.Seconds()), + }) + + // Send initial progress update + resp.SendProgress(action.InvokeProgressEvent{ + Message: fmt.Sprintf("Starting transcription job %s...", transcriptionJobName), + }) + + // Build the start transcription job input + input := &transcribe.StartTranscriptionJobInput{ + TranscriptionJobName: aws.String(transcriptionJobName), + Media: &awstypes.Media{ + MediaFileUri: aws.String(mediaFileUri), + }, + } + + // Validate language configuration - exactly one must be specified + languageOptions := []bool{ + !config.LanguageCode.IsNull() && !config.LanguageCode.IsUnknown(), + !config.IdentifyLanguage.IsNull() && config.IdentifyLanguage.ValueBool(), + !config.IdentifyMultipleLanguages.IsNull() && config.IdentifyMultipleLanguages.ValueBool(), + } + + activeCount := 0 + for _, active := range languageOptions { + if active { + activeCount++ + } + } + + switch activeCount { + case 0: + resp.Diagnostics.AddError( + "Missing Language Configuration", + "You must specify exactly one of: language_code, identify_language, or identify_multiple_languages", + ) + return + case 1: + // Valid - continue + default: + resp.Diagnostics.AddError( + "Conflicting Language Configuration", + "You can only specify one of: language_code, identify_language, or identify_multiple_languages", + ) + return + } + + // Set language configuration + if languageOptions[0] { + input.LanguageCode = config.LanguageCode.ValueEnum() + } + if languageOptions[1] { + input.IdentifyLanguage = aws.Bool(true) + } + if languageOptions[2] { + input.IdentifyMultipleLanguages = aws.Bool(true) + } + + // Set optional parameters + if !config.MediaFormat.IsNull() && !config.MediaFormat.IsUnknown() { + input.MediaFormat = config.MediaFormat.ValueEnum() + } + + if !config.MediaSampleRateHertz.IsNull() { + input.MediaSampleRateHertz = aws.Int32(int32(config.MediaSampleRateHertz.ValueInt64())) + } + + if !config.OutputBucketName.IsNull() { + input.OutputBucketName = config.OutputBucketName.ValueStringPointer() + } + + if !config.OutputKey.IsNull() { + input.OutputKey = config.OutputKey.ValueStringPointer() + } + + // Start the transcription job + _, err := conn.StartTranscriptionJob(ctx, input) + if err != nil { + resp.Diagnostics.AddError( + "Failed to Start Transcription Job", + fmt.Sprintf("Could not start transcription job %s: %s", transcriptionJobName, err), + ) + return + } + + // Wait for job to move beyond QUEUED: treat IN_PROGRESS or COMPLETED as success, FAILED as failure, QUEUED transitional. + fr, err := actionwait.WaitForStatus(ctx, func(ctx context.Context) (actionwait.FetchResult[*awstypes.TranscriptionJob], error) { + input := transcribe.GetTranscriptionJobInput{TranscriptionJobName: aws.String(transcriptionJobName)} + getOutput, gerr := conn.GetTranscriptionJob(ctx, &input) + if gerr != nil { + return actionwait.FetchResult[*awstypes.TranscriptionJob]{}, fmt.Errorf("get transcription job: %w", gerr) + } + if getOutput.TranscriptionJob == nil { + return actionwait.FetchResult[*awstypes.TranscriptionJob]{}, fmt.Errorf("transcription job %s not found", transcriptionJobName) + } + status := getOutput.TranscriptionJob.TranscriptionJobStatus + return actionwait.FetchResult[*awstypes.TranscriptionJob]{Status: actionwait.Status(status), Value: getOutput.TranscriptionJob}, nil + }, actionwait.Options[*awstypes.TranscriptionJob]{ + Timeout: timeout, + Interval: actionwait.FixedInterval(transcriptionJobPollInterval), + ProgressInterval: transcriptionJobProgressInterval, + SuccessStates: []actionwait.Status{ + actionwait.Status(awstypes.TranscriptionJobStatusInProgress), + actionwait.Status(awstypes.TranscriptionJobStatusCompleted), + }, + TransitionalStates: []actionwait.Status{ + actionwait.Status(awstypes.TranscriptionJobStatusQueued), + }, + FailureStates: []actionwait.Status{ + actionwait.Status(awstypes.TranscriptionJobStatusFailed), + }, + ProgressSink: func(fr actionwait.FetchResult[any], meta actionwait.ProgressMeta) { + resp.SendProgress(action.InvokeProgressEvent{Message: fmt.Sprintf("Transcription job %s is currently %s", transcriptionJobName, fr.Status)}) + }, + }) + if err != nil { + var timeoutErr *actionwait.TimeoutError + var failureErr *actionwait.FailureStateError + var unexpectedErr *actionwait.UnexpectedStateError + + if errors.As(err, &timeoutErr) { + resp.Diagnostics.AddError( + "Timeout Waiting for Transcription Job", + fmt.Sprintf("Transcription job %s did not reach a running state within %v", transcriptionJobName, timeout), + ) + } else if errors.As(err, &failureErr) { + resp.Diagnostics.AddError( + "Transcription Job Failed", + fmt.Sprintf("Transcription job %s failed: %s", transcriptionJobName, failureErr.Status), + ) + } else if errors.As(err, &unexpectedErr) { + resp.Diagnostics.AddError( + "Unexpected Transcription Job Status", + fmt.Sprintf("Transcription job %s entered unexpected status: %s", transcriptionJobName, unexpectedErr.Status), + ) + } else { + resp.Diagnostics.AddError( + "Error Waiting for Transcription Job", + fmt.Sprintf("Error while waiting for transcription job %s: %s", transcriptionJobName, err), + ) + } + return + } + + resp.SendProgress(action.InvokeProgressEvent{Message: fmt.Sprintf("Transcription job %s started successfully and is %s", transcriptionJobName, fr.Status)}) + logFields := map[string]any{ + "transcription_job_name": transcriptionJobName, + "job_status": fr.Status, + } + if fr.Value != nil { + logFields[names.AttrCreationTime] = fr.Value.CreationTime + } + tflog.Info(ctx, "Transcription job started successfully", logFields) +} diff --git a/internal/service/transcribe/start_transcription_job_action_test.go b/internal/service/transcribe/start_transcription_job_action_test.go new file mode 100644 index 000000000000..3ca225096593 --- /dev/null +++ b/internal/service/transcribe/start_transcription_job_action_test.go @@ -0,0 +1,270 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package transcribe_test + +import ( + "context" + "fmt" + "slices" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/transcribe" + "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" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccTranscribeStartTranscriptionJobAction_basic(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + bucketName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccStartTranscriptionJobActionConfig_basic(rName, bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTranscriptionJobExists(ctx, rName), + testAccCheckTranscriptionJobStatus(ctx, rName, "IN_PROGRESS", "COMPLETED"), + ), + }, + }, + }) +} + +func TestAccTranscribeStartTranscriptionJobAction_identifyLanguage(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + bucketName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccStartTranscriptionJobActionConfig_identifyLanguage(rName, bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTranscriptionJobExists(ctx, rName), + testAccCheckTranscriptionJobStatus(ctx, rName, "IN_PROGRESS", "COMPLETED"), + testAccCheckTranscriptionJobIdentifyLanguage(ctx, rName, true), + ), + }, + }, + }) +} + +func TestAccTranscribeStartTranscriptionJobAction_withOutputLocation(t *testing.T) { + ctx := acctest.Context(t) + rName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + bucketName := acctest.RandomWithPrefix(t, acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TranscribeServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccStartTranscriptionJobActionConfig_withOutputLocation(rName, bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTranscriptionJobExists(ctx, rName), + testAccCheckTranscriptionJobStatus(ctx, rName, "IN_PROGRESS", "COMPLETED"), + ), + }, + }, + }) +} + +func testAccCheckTranscriptionJobExists(ctx context.Context, jobName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeClient(ctx) + + input := &transcribe.GetTranscriptionJobInput{ + TranscriptionJobName: &jobName, + } + + _, err := conn.GetTranscriptionJob(ctx, input) + if err != nil { + return fmt.Errorf("transcription job %s not found: %w", jobName, err) + } + + return nil + } +} + +func testAccCheckTranscriptionJobStatus(ctx context.Context, jobName string, expectedStatuses ...string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeClient(ctx) + + input := &transcribe.GetTranscriptionJobInput{ + TranscriptionJobName: &jobName, + } + + output, err := conn.GetTranscriptionJob(ctx, input) + if err != nil { + return fmt.Errorf("error getting transcription job %s: %w", jobName, err) + } + + if output.TranscriptionJob == nil { + return fmt.Errorf("transcription job %s not found", jobName) + } + + actualStatus := string(output.TranscriptionJob.TranscriptionJobStatus) + if slices.Contains(expectedStatuses, actualStatus) { + return nil + } + + return fmt.Errorf("expected transcription job %s status to be one of %v, got %s", jobName, expectedStatuses, actualStatus) + } +} + +func testAccCheckTranscriptionJobIdentifyLanguage(ctx context.Context, jobName string, expected bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TranscribeClient(ctx) + + input := &transcribe.GetTranscriptionJobInput{ + TranscriptionJobName: &jobName, + } + + output, err := conn.GetTranscriptionJob(ctx, input) + if err != nil { + return fmt.Errorf("error getting transcription job %s: %w", jobName, err) + } + + if output.TranscriptionJob == nil { + return fmt.Errorf("transcription job %s not found", jobName) + } + + actual := output.TranscriptionJob.IdentifyLanguage != nil && *output.TranscriptionJob.IdentifyLanguage + if actual != expected { + return fmt.Errorf("expected transcription job %s identify_language to be %t, got %t", jobName, expected, actual) + } + + return nil + } +} + +func testAccStartTranscriptionJobActionConfig_basic(rName, bucketName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[2]q + force_destroy = true +} + +resource "aws_s3_object" "test" { + bucket = aws_s3_bucket.test.bucket + key = "test-audio.wav" + source = "test-fixtures/test-audio.wav" +} + +action "aws_transcribe_start_transcription_job" "test" { + config { + transcription_job_name = %[1]q + media_file_uri = "s3://${aws_s3_bucket.test.bucket}/${aws_s3_object.test.key}" + language_code = "en-US" + timeout = 600 + } +} + +resource "terraform_data" "test" { + triggers_replace = [ + aws_s3_object.test.etag + ] + + input = "completed" + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.test] + } + } +} +`, rName, bucketName) +} + +func testAccStartTranscriptionJobActionConfig_identifyLanguage(rName, bucketName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[2]q + force_destroy = true +} + +resource "aws_s3_object" "test" { + bucket = aws_s3_bucket.test.bucket + key = "test-audio.wav" + source = "test-fixtures/test-audio.wav" +} + +action "aws_transcribe_start_transcription_job" "test" { + config { + transcription_job_name = %[1]q + media_file_uri = "s3://${aws_s3_bucket.test.bucket}/${aws_s3_object.test.key}" + identify_language = true + timeout = 600 + } +} + +resource "terraform_data" "test" { + triggers_replace = [ + aws_s3_object.test.etag + ] + + input = "completed" + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.test] + } + } +} +`, rName, bucketName) +} + +func testAccStartTranscriptionJobActionConfig_withOutputLocation(rName, bucketName string) string { + return fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[2]q + force_destroy = true +} + +resource "aws_s3_object" "test" { + bucket = aws_s3_bucket.test.bucket + key = "test-audio.wav" + source = "test-fixtures/test-audio.wav" +} + +action "aws_transcribe_start_transcription_job" "test" { + config { + transcription_job_name = %[1]q + media_file_uri = "s3://${aws_s3_bucket.test.bucket}/${aws_s3_object.test.key}" + language_code = "en-US" + output_bucket_name = aws_s3_bucket.test.bucket + output_key = "transcripts/%[1]s.json" + timeout = 600 + } +} + +resource "terraform_data" "test" { + triggers_replace = [ + aws_s3_object.test.etag + ] + + input = "completed" + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.test] + } + } +} +`, rName, bucketName) +} diff --git a/internal/service/transcribe/test-fixtures/test-audio.wav b/internal/service/transcribe/test-fixtures/test-audio.wav new file mode 100644 index 000000000000..b33814b96b91 Binary files /dev/null and b/internal/service/transcribe/test-fixtures/test-audio.wav differ diff --git a/website/docs/actions/codebuild_start_build.html.markdown b/website/docs/actions/codebuild_start_build.html.markdown index 1af14b039162..a8b0c14ef0d2 100644 --- a/website/docs/actions/codebuild_start_build.html.markdown +++ b/website/docs/actions/codebuild_start_build.html.markdown @@ -89,6 +89,7 @@ The following arguments are required: The following arguments are optional: +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `source_version` - (Optional) Version of the build input to be built. For GitHub, this can be a commit SHA, branch name, or tag name. * `timeout` - (Optional) Timeout in seconds for the build operation. Defaults to 1800 seconds (30 minutes). * `environment_variables_override` - (Optional) Environment variables to override for this build. See [Environment Variables Override](#environment-variables-override) below. diff --git a/website/docs/actions/ec2_stop_instance.html.markdown b/website/docs/actions/ec2_stop_instance.html.markdown index cddaf8cca36d..8220cf22872b 100644 --- a/website/docs/actions/ec2_stop_instance.html.markdown +++ b/website/docs/actions/ec2_stop_instance.html.markdown @@ -90,4 +90,5 @@ This action supports the following arguments: * `instance_id` - (Required) ID of the EC2 instance to stop. Must be a valid EC2 instance ID (e.g., i-1234567890abcdef0). * `force` - (Optional) Forces the instance to stop. The instance does not have an opportunity to flush file system caches or file system metadata. If you use this option, you must perform file system check and repair procedures. This option is not recommended for Windows instances. Default: `false`. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `timeout` - (Optional) Timeout in seconds to wait for the instance to stop. Must be between 30 and 3600 seconds. Default: `600`. diff --git a/website/docs/actions/events_put_events.html.markdown b/website/docs/actions/events_put_events.html.markdown index 9a111e3ae24f..1dde36fd87dd 100644 --- a/website/docs/actions/events_put_events.html.markdown +++ b/website/docs/actions/events_put_events.html.markdown @@ -132,7 +132,7 @@ action "aws_events_put_events" "deployment" { This action supports the following arguments: * `entry` - (Required) One or more `entry` blocks defining events to send. Multiple blocks may be specified. See [below](#entry-block). -* `region` - (Optional) AWS region override. Defaults to the provider region if omitted. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). ### `entry` Block diff --git a/website/docs/actions/lambda_invoke.html.markdown b/website/docs/actions/lambda_invoke.html.markdown index 4a048c106e8f..4372d8008799 100644 --- a/website/docs/actions/lambda_invoke.html.markdown +++ b/website/docs/actions/lambda_invoke.html.markdown @@ -218,4 +218,5 @@ This action supports the following arguments: * `invocation_type` - (Optional) Invocation type. Valid values are `RequestResponse` (default) for synchronous invocation that waits for the function to complete and returns the response, `Event` for asynchronous invocation that returns immediately after the request is accepted, and `DryRun` to validate parameters and verify permissions without actually executing the function. * `log_type` - (Optional) Set to `Tail` to include the execution log in the response. Only applies to synchronous invocations (`RequestResponse` invocation type). Defaults to `None`. When set to `Tail`, the last 4 KB of the execution log is included in the response. * `payload` - (Required) JSON payload to send to the Lambda function. This should be a valid JSON string that represents the event data for your function. The payload size limit is 6 MB for synchronous invocations and 256 KB for asynchronous invocations. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `qualifier` - (Optional) Version or alias of the Lambda function to invoke. If not specified, the `$LATEST` version will be invoked. Can be a version number (e.g., `1`) or an alias (e.g., `PROD`). diff --git a/website/docs/actions/ses_send_email.html.markdown b/website/docs/actions/ses_send_email.html.markdown index 4f1bd36adae0..9311d0a810fe 100644 --- a/website/docs/actions/ses_send_email.html.markdown +++ b/website/docs/actions/ses_send_email.html.markdown @@ -169,6 +169,7 @@ This action supports the following arguments: * `cc_addresses` - (Optional) List of email addresses for the CC: field of the message. Recipients in this list will receive the email and their addresses will be visible to all recipients. * `html_body` - (Optional) Message body in HTML format. Either `text_body` or `html_body` (or both) must be specified. HTML content allows for rich formatting including links, images, and styling. * `reply_to_addresses` - (Optional) List of reply-to email addresses for the message. If the recipient replies to the message, each reply-to address will receive the reply. If not specified, replies will go to the source address. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `return_path` - (Optional) Email address that bounces and complaints will be forwarded to when feedback forwarding is enabled. This is useful for handling delivery failures and spam complaints. * `source` - (Required) Email address that is sending the email. This address must be either individually verified with Amazon SES, or from a domain that has been verified with Amazon SES. * `subject` - (Required) Subject of the message: A short summary of the content, which will appear in the recipient's inbox. diff --git a/website/docs/actions/sfn_start_execution.html.markdown b/website/docs/actions/sfn_start_execution.html.markdown index e7e207c1c00a..37ac7cc2cee4 100644 --- a/website/docs/actions/sfn_start_execution.html.markdown +++ b/website/docs/actions/sfn_start_execution.html.markdown @@ -233,5 +233,6 @@ This action supports the following arguments: * `input` - (Optional) JSON input data for the execution. Must be valid JSON. Defaults to `{}` if not specified. The input size limit is 256 KB. * `name` - (Optional) Name of the execution. Must be unique within the account/region/state machine for 90 days. If not provided, Step Functions automatically generates a UUID. Names must not contain whitespace, brackets, wildcards, or special characters. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `state_machine_arn` - (Required) ARN of the state machine to execute. Can be an unqualified ARN, version-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:version`), or alias-qualified ARN (e.g., `arn:aws:states:region:account:stateMachine:name:alias`). * `trace_header` - (Optional) AWS X-Ray trace header for distributed tracing. Used to correlate execution traces across services. diff --git a/website/docs/actions/sns_publish.html.markdown b/website/docs/actions/sns_publish.html.markdown index dfc2206e68b2..c238419bf170 100644 --- a/website/docs/actions/sns_publish.html.markdown +++ b/website/docs/actions/sns_publish.html.markdown @@ -138,6 +138,7 @@ This action supports the following arguments: * `message` - (Required) Message to publish. For JSON message structure, this should be a JSON object with protocol-specific messages. Maximum size is 256 KB. * `message_attributes` - (Optional) Message attributes to include with the message. Each attribute consists of a name, data type, and value. Up to 10 attributes are allowed. [See below.](#message-attributes) * `message_structure` - (Optional) Set to `json` if you want to send different messages for each protocol. If not specified, the message will be sent as-is to all protocols. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). * `subject` - (Optional) Optional subject for the message. Only used for email and email-json protocols. Maximum length is 100 characters. * `topic_arn` - (Required) ARN of the SNS topic to publish the message to. diff --git a/website/docs/actions/transcribe_start_transcription_job.html.markdown b/website/docs/actions/transcribe_start_transcription_job.html.markdown new file mode 100644 index 000000000000..0feb65ab3a99 --- /dev/null +++ b/website/docs/actions/transcribe_start_transcription_job.html.markdown @@ -0,0 +1,124 @@ +--- +subcategory: "Transcribe" +layout: "aws" +page_title: "AWS: aws_transcribe_start_transcription_job" +description: |- + Starts an Amazon Transcribe transcription job. +--- + +# Action: aws_transcribe_start_transcription_job + +~> **Note:** `aws_transcribe_start_transcription_job` is in beta. Its interface and behavior may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available. + +Starts an Amazon Transcribe transcription job to transcribe audio from a media file. The media file must be uploaded to an Amazon S3 bucket before starting the transcription job. + +For information about Amazon Transcribe, see the [Amazon Transcribe Developer Guide](https://docs.aws.amazon.com/transcribe/latest/dg/). For specific information about starting transcription jobs, see the [StartTranscriptionJob](https://docs.aws.amazon.com/transcribe/latest/APIReference/API_StartTranscriptionJob.html) page in the Amazon Transcribe API Reference. + +~> **Note:** This action starts the transcription job and waits for it to begin processing, but does not wait for the transcription to complete. The job will continue running asynchronously after the action completes. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_s3_bucket" "example" { + bucket = "my-transcription-bucket" +} + +resource "aws_s3_object" "audio" { + bucket = aws_s3_bucket.example.bucket + key = "audio/meeting.mp3" + source = "path/to/meeting.mp3" +} + +action "aws_transcribe_start_transcription_job" "example" { + config { + transcription_job_name = "meeting-transcription-${timestamp()}" + media_file_uri = "s3://${aws_s3_bucket.example.bucket}/${aws_s3_object.audio.key}" + language_code = "en-US" + } +} +``` + +### Automatic Language Detection + +```terraform +action "aws_transcribe_start_transcription_job" "auto_detect" { + config { + transcription_job_name = "auto-detect-transcription" + media_file_uri = "s3://my-bucket/audio/multilingual-meeting.mp3" + identify_language = true + timeout = 600 + } +} +``` + +### Multiple Language Detection + +```terraform +action "aws_transcribe_start_transcription_job" "multilingual" { + config { + transcription_job_name = "multilingual-transcription" + media_file_uri = "s3://my-bucket/audio/conference-call.mp3" + identify_multiple_languages = true + media_format = "mp3" + media_sample_rate_hertz = 44100 + } +} +``` + +### Custom Output Location + +```terraform +action "aws_transcribe_start_transcription_job" "custom_output" { + config { + transcription_job_name = "custom-output-transcription" + media_file_uri = "s3://my-bucket/audio/interview.wav" + language_code = "en-US" + output_bucket_name = aws_s3_bucket.transcripts.bucket + output_key = "transcripts/interview-transcript.json" + } +} +``` + +### CI/CD Pipeline Integration + +```terraform +resource "terraform_data" "process_audio" { + input = var.audio_files + + lifecycle { + action_trigger { + events = [before_create, before_update] + actions = [action.aws_transcribe_start_transcription_job.batch_process] + } + } + + depends_on = [aws_s3_object.uploaded_audio] +} + +action "aws_transcribe_start_transcription_job" "batch_process" { + config { + transcription_job_name = "batch-${formatdate("YYYY-MM-DD-hhmm", timestamp())}" + media_file_uri = "s3://${aws_s3_bucket.audio.bucket}/${aws_s3_object.uploaded_audio.key}" + language_code = var.audio_language + timeout = 900 + } +} +``` + +## Argument Reference + +This action supports the following arguments: + +* `transcription_job_name` - (Required) Unique name for the transcription job within your AWS account. Must be 1-200 characters and contain only alphanumeric characters, hyphens, periods, and underscores. +* `media_file_uri` - (Required) S3 location of the media file to transcribe (e.g., `s3://bucket-name/file.mp3`). The file must be accessible to Amazon Transcribe. +* `language_code` - (Optional) Language code for the language used in the input media file. Required if `identify_language` and `identify_multiple_languages` are both false. Valid values can be found in the [Amazon Transcribe supported languages documentation](https://docs.aws.amazon.com/transcribe/latest/dg/supported-languages.html). +* `identify_language` - (Optional) Enable automatic language identification for single-language media files. Cannot be used with `identify_multiple_languages`. Default: `false`. +* `identify_multiple_languages` - (Optional) Enable automatic language identification for multi-language media files. Cannot be used with `identify_language`. Default: `false`. +* `media_format` - (Optional) Format of the input media file. If not specified, Amazon Transcribe will attempt to determine the format automatically. Valid values: `mp3`, `mp4`, `wav`, `flac`, `ogg`, `amr`, `webm`, `m4a`. +* `media_sample_rate_hertz` - (Optional) Sample rate of the input media file in Hertz. If not specified, Amazon Transcribe will attempt to determine the sample rate automatically. Valid range: 8000-48000. +* `output_bucket_name` - (Optional) Name of the S3 bucket where you want your transcription output stored. If not specified, output is stored in a service-managed bucket. +* `output_key` - (Optional) S3 object key for your transcription output. If not specified, a default key is generated. +* `region` - (Optional) Region where this action should be [run](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `timeout` - (Optional) Maximum time in seconds to wait for the transcription job to start. Must be between 60 and 3600 seconds. Default: `300`.