Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[36384] Add job state time limit actions to batch queue #38784

Merged
merged 11 commits into from
Aug 16, 2024
7 changes: 7 additions & 0 deletions .changelog/36658.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_batch_job_queue: Add `job_state_time_limit_action` argument
```

```release-note:enhancement
data-source/aws_batch_job_queue: Add `job_state_time_limit_action` attribute
```
52 changes: 52 additions & 0 deletions internal/service/batch/job_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go/service/batch"
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
"github.com/hashicorp/terraform-plugin-framework-validators/resourcevalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/diag"
Expand Down Expand Up @@ -133,6 +134,34 @@ func (r *resourceJobQueue) Schema(ctx context.Context, request resource.SchemaRe
},
},
},
"job_state_time_limit_action": schema.ListNestedBlock{
CustomType: fwtypes.NewListNestedObjectTypeOf[jobStateTimeLimitAction](ctx),
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"action": schema.StringAttribute{
Required: true,
Validators: []validator.String{
stringvalidator.OneOf(batch.JobStateTimeLimitActionsAction_Values()...),
},
},
"max_time_seconds": schema.Int64Attribute{
Required: true,
Validators: []validator.Int64{
int64validator.Between(600, 86400),
},
},
"reason": schema.StringAttribute{
Required: true,
},
"state": schema.StringAttribute{
Required: true,
Validators: []validator.String{
stringvalidator.OneOf(batch.JobStateTimeLimitActionsState_Values()...),
},
},
},
},
},
}

response.Schema = s
Expand Down Expand Up @@ -193,6 +222,11 @@ func (r *resourceJobQueue) Create(ctx context.Context, request resource.CreateRe
} else {
state.ComputeEnvironments = flex.FlattenFrameworkStringValueListLegacy(ctx, flattenComputeEnvironments(out.ComputeEnvironmentOrder))
}

if !data.JobStateTimeLimitAction.IsNull() {
flex.Flatten(ctx, out.JobStateTimeLimitActions, &data.JobStateTimeLimitAction)
}

response.Diagnostics.Append(state.refreshFromOutput(ctx, out)...)
response.Diagnostics.Append(response.State.Set(ctx, &state)...)
}
Expand Down Expand Up @@ -228,6 +262,11 @@ func (r *resourceJobQueue) Read(ctx context.Context, request resource.ReadReques
} else {
data.ComputeEnvironments = flex.FlattenFrameworkStringValueListLegacy(ctx, flattenComputeEnvironments(out.ComputeEnvironmentOrder))
}

if !data.JobStateTimeLimitAction.IsNull() {
flex.Flatten(ctx, out.JobStateTimeLimitActions, &data.JobStateTimeLimitAction)
}

response.Diagnostics.Append(data.refreshFromOutput(ctx, out)...)
response.Diagnostics.Append(response.State.Set(ctx, &data)...)
}
Expand Down Expand Up @@ -259,6 +298,11 @@ func (r *resourceJobQueue) Update(ctx context.Context, request resource.UpdateRe
}
}

if !plan.JobStateTimeLimitAction.IsNull() && !plan.JobStateTimeLimitAction.Equal(state.JobStateTimeLimitAction) {
flex.Expand(ctx, plan.JobStateTimeLimitAction, &input.JobStateTimeLimitActions)
update = true
}

if !plan.Priority.Equal(state.Priority) {
input.Priority = flex.Int64FromFramework(ctx, plan.Priority)

Expand Down Expand Up @@ -393,6 +437,7 @@ type resourceJobQueueData struct {
JobQueueName types.String `tfsdk:"name"`
Priority types.Int64 `tfsdk:"priority"`
SchedulingPolicyARN fwtypes.ARN `tfsdk:"scheduling_policy_arn"`
JobStateTimeLimitAction fwtypes.ListNestedObjectValueOf[jobStateTimeLimitAction] `tfsdk:"job_state_time_limit_action"`
State types.String `tfsdk:"state"`
Tags types.Map `tfsdk:"tags"`
TagsAll types.Map `tfsdk:"tags_all"`
Expand All @@ -404,6 +449,13 @@ type computeEnvironmentOrder struct {
Order types.Int64 `tfsdk:"order"`
}

type jobStateTimeLimitAction struct {
Action types.String `tfsdk:"action"`
MaxTimeSeconds types.Int64 `tfsdk:"max_time_seconds"`
Reason types.String `tfsdk:"reason"`
State types.String `tfsdk:"state"`
}

func (r *resourceJobQueueData) refreshFromOutput(ctx context.Context, out *batch.JobQueueDetail) diag.Diagnostics { //nolint:unparam
var diags diag.Diagnostics

Expand Down
38 changes: 38 additions & 0 deletions internal/service/batch/job_queue_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,31 @@ func DataSourceJobQueue() *schema.Resource {
},
},
},

"job_state_time_limit_action": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"action": {
Type: schema.TypeString,
Computed: true,
},
"max_time_seconds": {
Type: schema.TypeInt,
Computed: true,
},
"reason": {
Type: schema.TypeString,
Computed: true,
},
"state": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}
Expand Down Expand Up @@ -122,6 +147,19 @@ func dataSourceJobQueueRead(ctx context.Context, d *schema.ResourceData, meta in
return sdkdiag.AppendErrorf(diags, "setting compute_environment_order: %s", err)
}

jobStateTimeLimitActions := make([]map[string]interface{}, 0)
for _, v := range jobQueue.JobStateTimeLimitActions {
jobStateTimeLimitAction := map[string]interface{}{}
jobStateTimeLimitAction["action"] = aws.StringValue(v.Action)
jobStateTimeLimitAction["max_time_seconds"] = aws.Int64Value(v.MaxTimeSeconds)
jobStateTimeLimitAction["reason"] = aws.StringValue(v.Reason)
jobStateTimeLimitAction["state"] = aws.StringValue(v.State)
jobStateTimeLimitActions = append(jobStateTimeLimitActions, jobStateTimeLimitAction)
}
if err := d.Set("job_state_time_limit_action", jobStateTimeLimitActions); err != nil {
return sdkdiag.AppendErrorf(diags, "setting job_state_time_limit_action: %s", err)
}

setTagsOut(ctx, jobQueue.Tags)

return diags
Expand Down
8 changes: 8 additions & 0 deletions internal/service/batch/job_queue_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func TestAccBatchJobQueueDataSource_schedulingPolicy(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, names.AttrARN, resourceName, names.AttrARN),
resource.TestCheckResourceAttrPair(dataSourceName, "compute_environment_order.#", resourceName, "compute_environments.#"),
resource.TestCheckResourceAttrPair(datasourceName, "job_state_time_limit_action.#", resourceName, "job_state_time_limit_action.#"),
resource.TestCheckResourceAttrPair(dataSourceName, names.AttrName, resourceName, names.AttrName),
resource.TestCheckResourceAttrPair(dataSourceName, names.AttrPriority, resourceName, names.AttrPriority),
resource.TestCheckResourceAttrPair(dataSourceName, "scheduling_policy_arn", resourceName, "scheduling_policy_arn"),
Expand Down Expand Up @@ -225,6 +226,13 @@ resource "aws_batch_job_queue" "test" {
state = "ENABLED"
priority = 1
compute_environments = [aws_batch_compute_environment.sample.arn]

job_state_time_limit_action {
action = "CANCEL"
max_time_seconds = 123
reason = "foobar"
state = "RUNNABLE"
}
}

data "aws_batch_job_queue" "test" {
Expand Down
2 changes: 2 additions & 0 deletions internal/service/batch/job_queue_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func upgradeJobQueueResourceStateV0toV1(ctx context.Context, req resource.Upgrad
return
}
ceo := fwtypes.NewListNestedObjectValueOfNull[computeEnvironmentOrder](ctx)
jobStateTimeLimitActions := fwtypes.NewListNestedObjectValueOfNull[jobStateTimeLimitAction](ctx)

jobQueueDataV2 := resourceJobQueueData{
ComputeEnvironments: jobQueueDataV0.ComputeEnvironments,
Expand All @@ -99,6 +100,7 @@ func upgradeJobQueueResourceStateV0toV1(ctx context.Context, req resource.Upgrad
JobQueueName: jobQueueDataV0.Name,
Priority: jobQueueDataV0.Priority,
State: jobQueueDataV0.State,
JobStateTimeLimitAction: jobStateTimeLimitActions,
Tags: jobQueueDataV0.Tags,
TagsAll: jobQueueDataV0.TagsAll,
Timeouts: jobQueueDataV0.Timeouts,
Expand Down
93 changes: 93 additions & 0 deletions internal/service/batch/job_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,99 @@ func testAccCheckJobQueueExists(ctx context.Context, n string, jq *batch.JobQueu
}
}

func TestAccBatchJobQueue_JobStateTimeLimitActionsMultiple(t *testing.T) {
ctx := acctest.Context(t)
var jobQueue1 batch.JobQueueDetail
resourceName := "aws_batch_job_queue.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.BatchServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckJobQueueDestroy(ctx),
Steps: []resource.TestStep{
{
Config: acctest.ConfigCompose(
testAccJobQueueConfig_Base(rName),
fmt.Sprintf(`
resource "aws_batch_job_queue" "test" {
compute_environments = [aws_batch_compute_environment.test.arn]
name = %[1]q
priority = 1
state = "DISABLED"
job_state_time_limit_action {
action = "CANCEL"
max_time_seconds = 600
reason = "MISCONFIGURATION:JOB_RESOURCE_REQUIREMENT"
state = "RUNNABLE"
}
job_state_time_limit_action {
action = "CANCEL"
max_time_seconds = 605
reason = "CAPACITY:INSUFFICIENT_INSTANCE_CAPACITY"
state = "RUNNABLE"
}
}
`, rName)),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckJobQueueExists(ctx, resourceName, &jobQueue1),
resource.TestCheckResourceAttr(resourceName, "job_state_time_limit_action.#", "2"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.action", "CANCEL"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.max_time_seconds", "600"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.reason", "MISCONFIGURATION:JOB_RESOURCE_REQUIREMENT"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.state", "RUNNABLE"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.action", "CANCEL"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.max_time_seconds", "605"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.reason", "CAPACITY:INSUFFICIENT_INSTANCE_CAPACITY"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.state", "RUNNABLE"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: acctest.ConfigCompose(
testAccJobQueueConfig_Base(rName),
fmt.Sprintf(`
resource "aws_batch_job_queue" "test" {
compute_environments = [aws_batch_compute_environment.test.arn]
name = %[1]q
priority = 1
state = "DISABLED"
job_state_time_limit_action {
action = "CANCEL"
max_time_seconds = 610
reason = "MISCONFIGURATION:JOB_RESOURCE_REQUIREMENT"
state = "RUNNABLE"
}
job_state_time_limit_action {
action = "CANCEL"
max_time_seconds = 605
reason = "MISCONFIGURATION:COMPUTE_ENVIRONMENT_MAX_RESOURCE"
state = "RUNNABLE"
}
}
`, rName)),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckJobQueueExists(ctx, resourceName, &jobQueue1),
resource.TestCheckResourceAttr(resourceName, "job_state_time_limit_action.#", "2"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.action", "CANCEL"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.max_time_seconds", "610"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.reason", "MISCONFIGURATION:JOB_RESOURCE_REQUIREMENT"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.0", "job_state_time_limit_action.state", "RUNNABLE"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.action", "CANCEL"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.max_time_seconds", "605"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.reason", "MISCONFIGURATION:COMPUTE_ENVIRONMENT_MAX_RESOURCE"),
resource.TestCheckResourceAttrPair(resourceName, "job_state_time_limit_action.1", "job_state_time_limit_action.state", "RUNNABLE"),
),
},
},
})
}

func testAccCheckJobQueueDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
Expand Down
5 changes: 5 additions & 0 deletions website/docs/d/batch_job_queue.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ This data source exports the following attributes in addition to the arguments a
which job placement is preferred. Compute environments are selected for job placement in ascending order.
* `compute_environment_order.#.order` - The order of the compute environment.
* `compute_environment_order.#.compute_environment` - The ARN of the compute environment.
* `job_state_time_limit_action` - Specifies an action that AWS Batch will take after the job has remained at the head of the queue in the specified state for longer than the specified time.
* `job_state_time_limit_action.#.action` - The action to take when a job is at the head of the job queue in the specified state for the specified period of time.
* `job_state_time_limit_action.#.max_time_seconds` - The approximate amount of time, in seconds, that must pass with the job in the specified state before the action is taken.
* `job_state_time_limit_action.#.reason` - The reason to log for the action being taken.
* `job_state_time_limit_action.#.state` - The state of the job needed to trigger the action.
8 changes: 8 additions & 0 deletions website/docs/r/batch_job_queue.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ This resource supports the following arguments:
* `name` - (Required) Specifies the name of the job queue.
* `compute_environments` - (Deprecated) (Optional) This parameter is deprecated, please use `compute_environment_order` instead. List of compute environment ARNs mapped to a job queue. The position of the compute environments in the list will dictate the order. When importing a AWS Batch Job Queue, the parameter `compute_environments` will always be used over `compute_environment_order`. Please adjust your HCL accordingly.
* `compute_environment_order` - (Optional) The set of compute environments mapped to a job queue and their order relative to each other. The job scheduler uses this parameter to determine which compute environment runs a specific job. Compute environments must be in the VALID state before you can associate them with a job queue. You can associate up to three compute environments with a job queue.
* `job_state_time_limit_action` - (Optional) The set of job state time limit actions mapped to a job queue. Specifies an action that AWS Batch will take after the job has remained at the head of the queue in the specified state for longer than the specified time.
* `priority` - (Required) The priority of the job queue. Job queues with a higher priority
are evaluated first when associated with the same compute environment.
* `scheduling_policy_arn` - (Optional) The ARN of the fair share scheduling policy. If this parameter is specified, the job queue uses a fair share scheduling policy. If this parameter isn't specified, the job queue uses a first in, first out (FIFO) scheduling policy. After a job queue is created, you can replace but can't remove the fair share scheduling policy.
Expand All @@ -86,6 +87,13 @@ This resource supports the following arguments:
* `compute_environment` - (Required) The Amazon Resource Name (ARN) of the compute environment.
* `order` - (Required) The order of the compute environment. Compute environments are tried in ascending order. For example, if two compute environments are associated with a job queue, the compute environment with a lower order integer value is tried for job placement first.

### job_state_time_limit_action

* `action` - (Required) The action to take when a job is at the head of the job queue in the specified state for the specified period of time. Valid values include `"CANCEL"`
* `job_state_time_limit_action.#.max_time_seconds` - The approximate amount of time, in seconds, that must pass with the job in the specified state before the action is taken. Valid values include integers between `600` & `86400`
* `reason` - (Required) The reason to log for the action being taken.
* `state` - (Required) The state of the job needed to trigger the action. Valid values include `"RUNNABLE"`.

## Attribute Reference

This resource exports the following attributes in addition to the arguments above:
Expand Down