Skip to content

Commit 373a0fd

Browse files
authored
Merge pull request #213 from controlplane-com/majid/workload-updates-20251208
Draft: Add Allow as an option to workload job concurrency policy
2 parents cd50105 + dff00c7 commit 373a0fd

File tree

8 files changed

+189
-20
lines changed

8 files changed

+189
-20
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"args": [
2121
//
2222
"-test.run",
23-
"TestAccControlPlaneMk8s_basic",
23+
"TestAccControlPlaneWorkload_basic",
2424
"-test.v"
2525
]
2626
}

docs/data-sources/workload.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,12 @@ KEDA (Kubernetes-based Event Driven Autoscaling) configuration.
333333

334334
Read-Only:
335335

336+
- **trigger** (Block List) ([see below](#nestedblock--options--autoscaling--keda--trigger)).
337+
- **advanced** (Block List) ([see below](#nestedblock--options--autoscaling--keda--advanced)).
338+
- **fallback** (Block List, Max: 1) ([see below](#nestedblock--options--autoscaling--keda--fallback)).
336339
- **polling_interval** (Number) Seconds between KEDA polling cycles.
337340
- **cooldown_period** (Number) Cooldown seconds after scaling to zero before scaling up again.
338341
- **initial_cooldown_period** (Number) Initial cooldown after scaling to zero.
339-
- **trigger** (Block List) ([see below](#nestedblock--options--autoscaling--keda--trigger)).
340-
- **advanced** (Block List) ([see below](#nestedblock--options--autoscaling--keda--advanced)).
341342

342343
<a id="nestedblock--options--autoscaling--keda--trigger"></a>
343344

@@ -383,6 +384,19 @@ Read-Only:
383384
- **metric_type** (String) Metric type used for the composed metric.
384385
- **formula** (String) Expression that combines or transforms metrics.
385386

387+
<a id="nestedblock--options--autoscaling--keda--fallback"></a>
388+
389+
### `options.autoscaling.keda.fallback`
390+
391+
Required:
392+
393+
- **failure_threshold** (Number) Number of consecutive failures required to trigger fallback behavior.
394+
- **replicas** (Number) Number of replicas to scale to when fallback is triggered.
395+
396+
Optional:
397+
398+
- **behavior** (String) Behavior to apply when fallback is triggered. Valid values: `static`, `currentReplicas`, `currentReplicasIfHigher`, `currentReplicasIfLower`.
399+
386400
<a id="nestedblock--options--multi_zone"></a>
387401

388402
### `options.multi_zone`
@@ -411,7 +425,7 @@ Exports cron workload settings.
411425
Read-Only:
412426

413427
- **schedule** (String) Cron schedule expression determining job execution times.
414-
- **concurrency_policy** (String) Either `Forbid` or `Replace`. Determines how overlapping jobs are handled.
428+
- **concurrency_policy** (String) Either `Forbid`, `Replace` or `Allow`. Determines how overlapping jobs are handled.
415429
- **history_limit** (Number) Maximum completed job instances retained. Integer between `1` and `10`. Default: `5`.
416430
- **restart_policy** (String) Either `OnFailure` or `Never`. Default: `Never`.
417431
- **active_deadline_seconds** (Number) Maximum seconds a job can run before it is forcibly stopped.

docs/resources/workload.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,12 @@ KEDA (Kubernetes-based Event Driven Autoscaling) allows for advanced autoscaling
388388

389389
Optional:
390390

391+
- **trigger** (Block List) ([see below](#nestedblock--options--autoscaling--keda--trigger))
392+
- **advanced** (Block List) ([see below](#nestedblock--options--autoscaling--keda--advanced))
393+
- **fallback** (Block List, Max: 1) ([see below](#nestedblock--options--autoscaling--keda--fallback))
391394
- **polling_interval** (Number) The interval in seconds at which KEDA will poll the external metrics to determine if scaling is required.
392395
- **cooldown_period** (Number) The cooldown period in seconds after scaling down to 0 replicas before KEDA will allow scaling up again.
393396
- **initial_cooldown_period** (Number) The initial cooldown period in seconds after scaling down to 0 replicas before KEDA will allow scaling up again.
394-
- **trigger** (Block List) ([see below](#nestedblock--options--autoscaling--keda--trigger))
395-
- **advanced** (Block List) ([see below](#nestedblock--options--autoscaling--keda--advanced))
396397

397398
<a id="nestedblock--options--autoscaling--keda--trigger"></a>
398399

@@ -443,6 +444,19 @@ Optional:
443444
- **metric_type** (String) Defines metric type used for this new composite-metric.
444445
- **formula** (String) Composes metrics together and allows them to be modified/manipulated. It accepts mathematical/conditional statements.
445446

447+
<a id="nestedblock--options--autoscaling--keda--fallback"></a>
448+
449+
### `options.autoscaling.keda.fallback`
450+
451+
Required:
452+
453+
- **failure_threshold** (Number) Number of consecutive failures required to trigger fallback behavior.
454+
- **replicas** (Number) Number of replicas to scale to when fallback is triggered.
455+
456+
Optional:
457+
458+
- **behavior** (String) Behavior to apply when fallback is triggered. Valid values: `static`, `currentReplicas`, `currentReplicasIfHigher`, `currentReplicasIfLower`.
459+
446460
<a id="nestedblock--options--multi_zone"></a>
447461

448462
### `options.multi_zone`
@@ -461,7 +475,7 @@ Required:
461475

462476
Optional:
463477

464-
- **concurrency_policy** (String) Either 'Forbid' or 'Replace'. This determines what Control Plane will do when the schedule requires a job to start, while a prior instance of the job is still running. Enum: [ Forbid, Replace ] Default: `Forbid`
478+
- **concurrency_policy** (String) Either `Forbid`, `Replace`, or `Allow`. This determines what Control Plane will do when the schedule requires a job to start, while a prior instance of the job is still running.
465479
- **history_limit** (Number) The maximum number of completed job instances to display. This should be an integer between 1 and 10. Default: `5`
466480
- **restart_policy** (String) Either 'OnFailure' or 'Never'. This determines what Control Plane will do when a job instance fails. Enum: [ OnFailure, Never ] Default: `Never`
467481
- **active_deadline_seconds** (Number) The maximum number of seconds Control Plane will wait for the job to complete. If a job does not succeed or fail in the allotted time, Control Plane will stop the job, moving it into the Removed status.
@@ -1011,6 +1025,12 @@ resource "cpln_workload" "new" {
10111025
formula = "m * 2"
10121026
}
10131027
}
1028+
1029+
fallback {
1030+
failure_threshold = 3
1031+
replicas = 1
1032+
behavior = "static"
1033+
}
10141034
}
10151035
}
10161036
}
@@ -1964,6 +1984,12 @@ resource "cpln_workload" "new" {
19641984
formula = "m * 2"
19651985
}
19661986
}
1987+
1988+
fallback {
1989+
failure_threshold = 3
1990+
replicas = 1
1991+
behavior = "static"
1992+
}
19671993
}
19681994
}
19691995
}

internal/provider/client/workload.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,12 @@ type WorkloadOptionsAutoscalingMulti struct {
219219
}
220220

221221
type WorkloadOptionsAutoscalingKeda struct {
222+
Triggers *[]WorkloadOptionsAutoscalingKedaTrigger `json:"triggers,omitempty"`
223+
Advanced *WorkloadOptionsAutoscalingKedaAdvanced `json:"advanced,omitempty"`
224+
Fallback *WorkloadOptionsAutoscalingKedaFallback `json:"fallback,omitempty"`
222225
PollingInterval *int `json:"pollingInterval,omitempty"`
223226
CooldownPeriod *int `json:"cooldownPeriod,omitempty"`
224227
InitialCooldownPeriod *int `json:"initialCooldownPeriod,omitempty"`
225-
Triggers *[]WorkloadOptionsAutoscalingKedaTrigger `json:"triggers,omitempty"`
226-
Advanced *WorkloadOptionsAutoscalingKedaAdvanced `json:"advanced,omitempty"`
227228
}
228229

229230
type WorkloadOptionsAutoscalingKedaTrigger struct {
@@ -250,6 +251,12 @@ type WorkloadOptionsAutoscalingKedaAdvancedScalingModifiers struct {
250251
Formula *string `json:"formula,omitempty"`
251252
}
252253

254+
type WorkloadOptionsAutoscalingKedaFallback struct {
255+
FailureThreshold *int `json:"failureThreshold,omitempty"`
256+
Replicas *int `json:"replicas,omitempty"`
257+
Behavior *string `json:"behavior,omitempty"`
258+
}
259+
253260
type WorkloadOptionsMultiZone struct {
254261
Enabled *bool `json:"enabled,omitempty"`
255262
}

internal/provider/data_source_workload.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ func (d *WorkloadDataSource) Schema(ctx context.Context, req datasource.SchemaRe
511511
Computed: true,
512512
},
513513
"concurrency_policy": schema.StringAttribute{
514-
Description: "Either 'Forbid' or 'Replace'. This determines what Control Plane will do when the schedule requires a job to start, while a prior instance of the job is still running. Enum: [ Forbid, Replace ] Default: `Forbid`.",
514+
Description: "Either 'Forbid', 'Replace', or 'Allow'. This determines what Control Plane will do when the schedule requires a job to start, while a prior instance of the job is still running.",
515515
Computed: true,
516516
},
517517
"history_limit": schema.Int32Attribute{
@@ -1011,6 +1011,25 @@ func (d *WorkloadDataSource) OptionsSchema(description string) schema.ListNested
10111011
},
10121012
},
10131013
},
1014+
"fallback": schema.ListNestedBlock{
1015+
Description: "Fallback configuration for KEDA.",
1016+
NestedObject: schema.NestedBlockObject{
1017+
Attributes: map[string]schema.Attribute{
1018+
"failure_threshold": schema.Int32Attribute{
1019+
Description: "Number of consecutive failures required to trigger fallback behavior.",
1020+
Computed: true,
1021+
},
1022+
"replicas": schema.Int32Attribute{
1023+
Description: "Number of replicas to scale to when fallback is triggered.",
1024+
Computed: true,
1025+
},
1026+
"behavior": schema.StringAttribute{
1027+
Description: "Behavior to apply when fallback is triggered.",
1028+
Computed: true,
1029+
},
1030+
},
1031+
},
1032+
},
10141033
},
10151034
},
10161035
},

internal/provider/models/workload/workload.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,21 +448,23 @@ func (o OptionsAutoscalingMultiModel) AttributeTypes() attr.Type {
448448
// Options -> Autoscaling -> Keda //
449449

450450
type OptionsAutoscalingKedaModel struct {
451+
Triggers types.List `tfsdk:"trigger"`
452+
Advanced types.List `tfsdk:"advanced"`
453+
Fallback types.List `tfsdk:"fallback"`
451454
PollingInterval types.Int32 `tfsdk:"polling_interval"`
452455
CooldownPeriod types.Int32 `tfsdk:"cooldown_period"`
453456
InitialCooldownPeriod types.Int32 `tfsdk:"initial_cooldown_period"`
454-
Triggers types.List `tfsdk:"trigger"`
455-
Advanced types.List `tfsdk:"advanced"`
456457
}
457458

458459
func (o OptionsAutoscalingKedaModel) AttributeTypes() attr.Type {
459460
return types.ObjectType{
460461
AttrTypes: map[string]attr.Type{
462+
"trigger": types.ListType{ElemType: OptionsAutoscalingKedaTriggerModel{}.AttributeTypes()},
463+
"advanced": types.ListType{ElemType: OptionsAutoscalingKedaAdvancedModel{}.AttributeTypes()},
464+
"fallback": types.ListType{ElemType: OptionsAutoscalingKedaFallbackModel{}.AttributeTypes()},
461465
"polling_interval": types.Int32Type,
462466
"cooldown_period": types.Int32Type,
463467
"initial_cooldown_period": types.Int32Type,
464-
"trigger": types.ListType{ElemType: OptionsAutoscalingKedaTriggerModel{}.AttributeTypes()},
465-
"advanced": types.ListType{ElemType: OptionsAutoscalingKedaAdvancedModel{}.AttributeTypes()},
466468
},
467469
}
468470
}
@@ -539,6 +541,24 @@ func (o OptionsAutoscalingKedaAdvancedScalingModifiersModel) AttributeTypes() at
539541
}
540542
}
541543

544+
// Options -> Autoscaling -> Keda -> Fallback //
545+
546+
type OptionsAutoscalingKedaFallbackModel struct {
547+
FailureThreshold types.Int32 `tfsdk:"failure_threshold"`
548+
Replicas types.Int32 `tfsdk:"replicas"`
549+
Behavior types.String `tfsdk:"behavior"`
550+
}
551+
552+
func (o OptionsAutoscalingKedaFallbackModel) AttributeTypes() attr.Type {
553+
return types.ObjectType{
554+
AttrTypes: map[string]attr.Type{
555+
"failure_threshold": types.Int32Type,
556+
"replicas": types.Int32Type,
557+
"behavior": types.StringType,
558+
},
559+
}
560+
}
561+
542562
// Options -> Muli Zone //
543563

544564
type OptionsMultiZoneModel struct {

internal/provider/resource_workload.go

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -760,12 +760,12 @@ func (wr *WorkloadResource) Schema(ctx context.Context, req resource.SchemaReque
760760
Required: true,
761761
},
762762
"concurrency_policy": schema.StringAttribute{
763-
Description: "Either 'Forbid' or 'Replace'. This determines what Control Plane will do when the schedule requires a job to start, while a prior instance of the job is still running. Enum: [ Forbid, Replace ] Default: `Forbid`.",
763+
Description: "Either 'Forbid', 'Replace', or 'Allow'. This determines what Control Plane will do when the schedule requires a job to start, while a prior instance of the job is still running.",
764764
Optional: true,
765765
Computed: true,
766766
Default: stringdefault.StaticString("Forbid"),
767767
Validators: []validator.String{
768-
stringvalidator.OneOf("Forbid", "Replace"),
768+
stringvalidator.OneOf("Forbid", "Replace", "Allow"),
769769
},
770770
},
771771
"history_limit": schema.Int32Attribute{
@@ -1593,6 +1593,31 @@ func (wr *WorkloadResource) OptionsSchema(description string) schema.ListNestedB
15931593
listvalidator.SizeAtMost(1),
15941594
},
15951595
},
1596+
"fallback": schema.ListNestedBlock{
1597+
Description: "Fallback configuration for KEDA.",
1598+
NestedObject: schema.NestedBlockObject{
1599+
Attributes: map[string]schema.Attribute{
1600+
"failure_threshold": schema.Int32Attribute{
1601+
Description: "Number of consecutive failures required to trigger fallback behavior.",
1602+
Required: true,
1603+
},
1604+
"replicas": schema.Int32Attribute{
1605+
Description: "Number of replicas to scale to when fallback is triggered.",
1606+
Required: true,
1607+
},
1608+
"behavior": schema.StringAttribute{
1609+
Description: "Behavior to apply when fallback is triggered.",
1610+
Optional: true,
1611+
Validators: []validator.String{
1612+
stringvalidator.OneOf("static", "currentReplicas", "currentReplicasIfHigher", "currentReplicasIfLower"),
1613+
},
1614+
},
1615+
},
1616+
},
1617+
Validators: []validator.List{
1618+
listvalidator.SizeAtMost(1),
1619+
},
1620+
},
15961621
},
15971622
},
15981623
Validators: []validator.List{
@@ -2783,11 +2808,12 @@ func (wro *WorkloadResourceOperator) buildOptionsAutoscalingKeda(state types.Lis
27832808

27842809
// Construct and return the output
27852810
return &client.WorkloadOptionsAutoscalingKeda{
2811+
Triggers: wro.buildOptionsAutoscalingKedaTrigger(block.Triggers),
2812+
Advanced: wro.buildOptionsAutoscalingKedaAdvanced(block.Advanced),
2813+
Fallback: wro.buildOptionsAutoscalingKedaFallback(block.Fallback),
27862814
PollingInterval: BuildInt(block.PollingInterval),
27872815
CooldownPeriod: BuildInt(block.CooldownPeriod),
27882816
InitialCooldownPeriod: BuildInt(block.InitialCooldownPeriod),
2789-
Triggers: wro.buildOptionsAutoscalingKedaTrigger(block.Triggers),
2790-
Advanced: wro.buildOptionsAutoscalingKedaAdvanced(block.Advanced),
27912817
}
27922818
}
27932819

@@ -2884,6 +2910,27 @@ func (wro *WorkloadResourceOperator) buildOptionsAutoscalingKedaAdvancedScalingM
28842910
}
28852911
}
28862912

2913+
// buildOptionsAutoscalingKedaFallback constructs a WorkloadOptionsAutoscalingKedaFallback from the given Terraform state.
2914+
func (wro *WorkloadResourceOperator) buildOptionsAutoscalingKedaFallback(state types.List) *client.WorkloadOptionsAutoscalingKedaFallback {
2915+
// Convert Terraform list into model blocks using generic helper
2916+
blocks, ok := BuildList[models.OptionsAutoscalingKedaFallbackModel](wro.Ctx, wro.Diags, state)
2917+
2918+
// Return nil if conversion failed or list was empty
2919+
if !ok {
2920+
return nil
2921+
}
2922+
2923+
// Take the first (and only) block
2924+
block := blocks[0]
2925+
2926+
// Construct and return the output
2927+
return &client.WorkloadOptionsAutoscalingKedaFallback{
2928+
FailureThreshold: BuildInt(block.FailureThreshold),
2929+
Replicas: BuildInt(block.Replicas),
2930+
Behavior: BuildString(block.Behavior),
2931+
}
2932+
}
2933+
28872934
// buildOptionsMultiZone constructs a WorkloadOptionsMultiZone from the given Terraform state.
28882935
func (wro *WorkloadResourceOperator) buildOptionsMultiZone(state types.List) *client.WorkloadOptionsMultiZone {
28892936
// Convert Terraform list into model blocks using generic helper
@@ -3907,11 +3954,12 @@ func (wro *WorkloadResourceOperator) flattenOptionsAutoscalingKeda(input *client
39073954

39083955
// Build a single block
39093956
block := models.OptionsAutoscalingKedaModel{
3957+
Triggers: wro.flattenOptionsAutoscalingKedaTrigger(input.Triggers),
3958+
Advanced: wro.flattenOptionsAutoscalingKedaAdvanced(input.Advanced),
3959+
Fallback: wro.flattenOptionsAutoscalingKedaFallback(input.Fallback),
39103960
PollingInterval: FlattenInt(input.PollingInterval),
39113961
CooldownPeriod: FlattenInt(input.CooldownPeriod),
39123962
InitialCooldownPeriod: FlattenInt(input.InitialCooldownPeriod),
3913-
Triggers: wro.flattenOptionsAutoscalingKedaTrigger(input.Triggers),
3914-
Advanced: wro.flattenOptionsAutoscalingKedaAdvanced(input.Advanced),
39153963
}
39163964

39173965
// Return the successfully created types.List
@@ -4015,6 +4063,28 @@ func (wro *WorkloadResourceOperator) flattenOptionsAutoscalingKedaAdvancedScalin
40154063
return FlattenList(wro.Ctx, wro.Diags, []models.OptionsAutoscalingKedaAdvancedScalingModifiersModel{block})
40164064
}
40174065

4066+
// flattenOptionsAutoscalingKedaFallback transforms *client.WorkloadOptionsAutoscalingKedaFallback into a types.List.
4067+
func (wro *WorkloadResourceOperator) flattenOptionsAutoscalingKedaFallback(input *client.WorkloadOptionsAutoscalingKedaFallback) types.List {
4068+
// Get attribute types
4069+
elementType := models.OptionsAutoscalingKedaFallbackModel{}.AttributeTypes()
4070+
4071+
// Check if the input is nil
4072+
if input == nil {
4073+
// Return a null list
4074+
return types.ListNull(elementType)
4075+
}
4076+
4077+
// Build a single block
4078+
block := models.OptionsAutoscalingKedaFallbackModel{
4079+
FailureThreshold: FlattenInt(input.FailureThreshold),
4080+
Replicas: FlattenInt(input.Replicas),
4081+
Behavior: types.StringPointerValue(input.Behavior),
4082+
}
4083+
4084+
// Return the successfully created types.List
4085+
return FlattenList(wro.Ctx, wro.Diags, []models.OptionsAutoscalingKedaFallbackModel{block})
4086+
}
4087+
40184088
// flattenOptionsMultiZone transforms *client.WorkloadOptionsMultiZone into a types.List.
40194089
func (wro *WorkloadResourceOperator) flattenOptionsMultiZone(input *client.WorkloadOptionsMultiZone) types.List {
40204090
// Get attribute types

internal/provider/resource_workload_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,13 @@ func (wrt *WorkloadResourceTest) BuildStandardUpdate1TestStep(initialCase Provid
16571657
},
16581658
},
16591659
},
1660+
"fallback": []map[string]interface{}{
1661+
{
1662+
"failure_threshold": "3",
1663+
"replicas": "1",
1664+
"behavior": "static",
1665+
},
1666+
},
16601667
},
16611668
},
16621669
},
@@ -3972,6 +3979,12 @@ resource "cpln_workload" "%s" {
39723979
formula = "m * 2"
39733980
}
39743981
}
3982+
3983+
fallback {
3984+
failure_threshold = 3
3985+
replicas = 1
3986+
behavior = "static"
3987+
}
39753988
}
39763989
}
39773990
}

0 commit comments

Comments
 (0)