diff --git a/castai/resource_workload_scaling_policy.go b/castai/resource_workload_scaling_policy.go
index 9f6f0a1a..fc5f6c1c 100644
--- a/castai/resource_workload_scaling_policy.go
+++ b/castai/resource_workload_scaling_policy.go
@@ -125,6 +125,21 @@ func resourceWorkloadScalingPolicy() *schema.Resource {
},
},
},
+ "anti_affinity": {
+ Type: schema.TypeList,
+ Optional: true,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "consider_anti_affinity": {
+ Type: schema.TypeBool,
+ Optional: true,
+ Description: `Defines if anti-affinity should be considered when scaling the workload.
+ If enabled, requiring host ports, or having anti-affinity on hostname will force all recommendations to be deferred.`,
+ },
+ },
+ },
+ },
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(15 * time.Second),
@@ -218,6 +233,8 @@ func resourceWorkloadScalingPolicyCreate(ctx context.Context, d *schema.Resource
req.RecommendationPolicies.MemoryEvent = toMemoryEvent(toSection(d, "memory_event"))
+ req.RecommendationPolicies.AntiAffinity = toAntiAffinity(toSection(d, "anti_affinity"))
+
resp, err := client.WorkloadOptimizationAPICreateWorkloadScalingPolicyWithResponse(ctx, clusterID, req)
if checkErr := sdk.CheckOKResponse(resp, err); checkErr != nil {
return diag.FromErr(checkErr)
@@ -272,6 +289,9 @@ func resourceWorkloadScalingPolicyRead(ctx context.Context, d *schema.ResourceDa
if err := d.Set("memory_event", toMemoryEventMap(sp.RecommendationPolicies.MemoryEvent)); err != nil {
return diag.FromErr(fmt.Errorf("setting memory event: %w", err))
}
+ if err := d.Set("anti_affinity", toAntiAffinityMap(sp.RecommendationPolicies.AntiAffinity)); err != nil {
+ return diag.FromErr(fmt.Errorf("setting anti-affinity: %w", err))
+ }
return nil
}
@@ -286,6 +306,7 @@ func resourceWorkloadScalingPolicyUpdate(ctx context.Context, d *schema.Resource
"startup",
"downscaling",
"memory_event",
+ "anti_affinity",
) {
tflog.Info(ctx, "scaling policy up to date")
return nil
@@ -303,6 +324,7 @@ func resourceWorkloadScalingPolicyUpdate(ctx context.Context, d *schema.Resource
Startup: toStartup(toSection(d, "startup")),
Downscaling: toDownscaling(toSection(d, "downscaling")),
MemoryEvent: toMemoryEvent(toSection(d, "memory_event")),
+ AntiAffinity: toAntiAffinity(toSection(d, "anti_affinity")),
},
}
@@ -542,3 +564,35 @@ func toMemoryEventMap(s *sdk.WorkloadoptimizationV1MemoryEventSettings) []map[st
return []map[string]any{m}
}
+
+func toAntiAffinity(antiAffinity map[string]any) *sdk.WorkloadoptimizationV1AntiAffinitySettings {
+ if len(antiAffinity) == 0 {
+ return nil
+ }
+
+ result := &sdk.WorkloadoptimizationV1AntiAffinitySettings{}
+
+ if v, ok := antiAffinity["consider_anti_affinity"].(bool); ok {
+ result.ConsiderAntiAffinity = lo.ToPtr(v)
+ }
+
+ return result
+}
+
+func toAntiAffinityMap(s *sdk.WorkloadoptimizationV1AntiAffinitySettings) []map[string]any {
+ if s == nil {
+ return nil
+ }
+
+ m := map[string]any{}
+
+ if s.ConsiderAntiAffinity != nil {
+ m["consider_anti_affinity"] = *s.ConsiderAntiAffinity
+ }
+
+ if len(m) == 0 {
+ return nil
+ }
+
+ return []map[string]any{m}
+}
diff --git a/castai/resource_workload_scaling_policy_test.go b/castai/resource_workload_scaling_policy_test.go
index 50f9e5f4..26e26be9 100644
--- a/castai/resource_workload_scaling_policy_test.go
+++ b/castai/resource_workload_scaling_policy_test.go
@@ -76,6 +76,7 @@ func TestAccResourceWorkloadScalingPolicy(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "startup.0.period_seconds", "123"),
resource.TestCheckResourceAttr(resourceName, "downscaling.0.apply_type", "DEFERRED"),
resource.TestCheckResourceAttr(resourceName, "memory_event.0.apply_type", "DEFERRED"),
+ resource.TestCheckResourceAttr(resourceName, "anti_affinity.0.consider_anti_affinity", "true"),
),
},
},
@@ -151,6 +152,9 @@ func scalingPolicyConfigUpdated(clusterName, projectID, name string) string {
}
memory_event {
apply_type = "DEFERRED"
+ }
+ anti_affinity {
+ consider_anti_affinity = true
}
}`, updatedName)
diff --git a/castai/sdk/api.gen.go b/castai/sdk/api.gen.go
index 4f7b641e..f9737981 100644
--- a/castai/sdk/api.gen.go
+++ b/castai/sdk/api.gen.go
@@ -1429,7 +1429,9 @@ type CastaiUsersV1beta1Organization struct {
// OrganizationMetadata describes organization metadata.
Metadata *CastaiUsersV1beta1OrganizationMetadata `json:"metadata,omitempty"`
- // name of the organization.
+ // name of the organization. Name of the organization must start with a
+ // letter or a number, followed by letters, numbers, underscores, hyphens,
+ // spaces and periods. The name must end with a letter or a number.
Name string `json:"name"`
}
@@ -3282,6 +3284,13 @@ type WorkloadoptimizationV1AggregatedMetrics struct {
P75 float64 `json:"p75"`
}
+// WorkloadoptimizationV1AntiAffinitySettings defines model for workloadoptimization.v1.AntiAffinitySettings.
+type WorkloadoptimizationV1AntiAffinitySettings struct {
+ // Defines if anti-affinity should be considered when scaling the workload.
+ // When true, requiring host ports, or having anti-affinity on hostname will force all recommendations to be deferred.
+ ConsiderAntiAffinity *bool `json:"considerAntiAffinity"`
+}
+
// WorkloadoptimizationV1ApplyType defines model for workloadoptimization.v1.ApplyType.
type WorkloadoptimizationV1ApplyType string
@@ -3560,8 +3569,9 @@ type WorkloadoptimizationV1RecommendationEventType string
// WorkloadoptimizationV1RecommendationPolicies defines model for workloadoptimization.v1.RecommendationPolicies.
type WorkloadoptimizationV1RecommendationPolicies struct {
- Cpu WorkloadoptimizationV1ResourcePolicies `json:"cpu"`
- Downscaling *WorkloadoptimizationV1DownscalingSettings `json:"downscaling,omitempty"`
+ AntiAffinity *WorkloadoptimizationV1AntiAffinitySettings `json:"antiAffinity,omitempty"`
+ Cpu WorkloadoptimizationV1ResourcePolicies `json:"cpu"`
+ Downscaling *WorkloadoptimizationV1DownscalingSettings `json:"downscaling,omitempty"`
// Defines possible options for workload management.
// READ_ONLY - workload watched (metrics collected), but no actions may be performed by CAST AI.
@@ -3770,6 +3780,7 @@ type WorkloadoptimizationV1UpdateWorkloadV2 struct {
// WorkloadoptimizationV1VPAConfig defines model for workloadoptimization.v1.VPAConfig.
type WorkloadoptimizationV1VPAConfig struct {
+ AntiAffinity WorkloadoptimizationV1AntiAffinitySettings `json:"antiAffinity"`
ContainerConstraints []WorkloadoptimizationV1ContainerConstraints `json:"containerConstraints"`
Cpu WorkloadoptimizationV1ResourceConfig `json:"cpu"`
@@ -3783,6 +3794,7 @@ type WorkloadoptimizationV1VPAConfig struct {
// WorkloadoptimizationV1VPAConfigUpdate defines model for workloadoptimization.v1.VPAConfigUpdate.
type WorkloadoptimizationV1VPAConfigUpdate struct {
+ AntiAffinity *WorkloadoptimizationV1AntiAffinitySettings `json:"antiAffinity,omitempty"`
ContainerConfig *[]WorkloadoptimizationV1ContainerConfigUpdate `json:"containerConfig,omitempty"`
Cpu *WorkloadoptimizationV1WorkloadResourceConfigUpdate `json:"cpu,omitempty"`
@@ -3843,6 +3855,7 @@ type WorkloadoptimizationV1Workload struct {
// WorkloadoptimizationV1WorkloadConfig defines model for workloadoptimization.v1.WorkloadConfig.
type WorkloadoptimizationV1WorkloadConfig struct {
+ AntiAffinity WorkloadoptimizationV1AntiAffinitySettings `json:"antiAffinity"`
ContainerConstraints []WorkloadoptimizationV1ContainerConstraints `json:"containerConstraints"`
Cpu WorkloadoptimizationV1ResourceConfig `json:"cpu"`
@@ -3856,6 +3869,7 @@ type WorkloadoptimizationV1WorkloadConfig struct {
// WorkloadoptimizationV1WorkloadConfigUpdate defines model for workloadoptimization.v1.WorkloadConfigUpdate.
type WorkloadoptimizationV1WorkloadConfigUpdate struct {
+ AntiAffinity *WorkloadoptimizationV1AntiAffinitySettings `json:"antiAffinity,omitempty"`
ContainerConfig *[]WorkloadoptimizationV1ContainerConfigUpdate `json:"containerConfig,omitempty"`
Cpu *WorkloadoptimizationV1WorkloadResourceConfigUpdate `json:"cpu,omitempty"`
diff --git a/docs/resources/workload_scaling_policy.md b/docs/resources/workload_scaling_policy.md
index f796ccd3..2aca9004 100644
--- a/docs/resources/workload_scaling_policy.md
+++ b/docs/resources/workload_scaling_policy.md
@@ -40,9 +40,12 @@ resource "castai_workload_scaling_policy" "services" {
downscaling {
apply_type = "DEFERRED"
}
- downscaling {
+ memory_event {
apply_type = "IMMEDIATE"
}
+ anti_affinity {
+ consider_anti_affinity = "IMMEDIATE"
+ }
}
```
@@ -64,6 +67,7 @@ resource "castai_workload_scaling_policy" "services" {
### Optional
+- `anti_affinity` (Block List, Max: 1) (see [below for nested schema](#nestedblock--anti_affinity))
- `downscaling` (Block List, Max: 1) (see [below for nested schema](#nestedblock--downscaling))
- `memory_event` (Block List, Max: 1) (see [below for nested schema](#nestedblock--memory_event))
- `startup` (Block List, Max: 1) (see [below for nested schema](#nestedblock--startup))
@@ -101,6 +105,15 @@ Optional:
- `overhead` (Number) Overhead for the recommendation, e.g. `0.1` will result in 10% higher recommendation
+
+### Nested Schema for `anti_affinity`
+
+Optional:
+
+- `consider_anti_affinity` (Boolean) Defines if anti-affinity should be considered when scaling the workload.
+ If enabled, requiring host ports, or having anti-affinity on hostname will force all recommendations to be deferred.
+
+
### Nested Schema for `downscaling`
diff --git a/examples/resources/castai_workload_scaling_policy/resource.tf b/examples/resources/castai_workload_scaling_policy/resource.tf
index 64df008f..e07c1118 100644
--- a/examples/resources/castai_workload_scaling_policy/resource.tf
+++ b/examples/resources/castai_workload_scaling_policy/resource.tf
@@ -23,7 +23,10 @@ resource "castai_workload_scaling_policy" "services" {
downscaling {
apply_type = "DEFERRED"
}
- downscaling {
+ memory_event {
apply_type = "IMMEDIATE"
}
+ anti_affinity {
+ consider_anti_affinity = "IMMEDIATE"
+ }
}
\ No newline at end of file