Skip to content

Commit 75da873

Browse files
authored
feat: Add missing topologySpreadConstraints (#2429)
* Add minDomains topologySpreadConstraint * Add node affinity and taints policy * Add match_label_keys to topologySpreadConstraint
1 parent 06a0123 commit 75da873

File tree

6 files changed

+130
-4
lines changed

6 files changed

+130
-4
lines changed

.changelog/2429.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
`resource/kubernetes_pod_v1`: add missing `topology_spread_constraints`: `node_affinity_policy`, `node_taints_policy`, `match_label_keys`, `min_domains`
3+
```

kubernetes/resource_kubernetes_pod_v1_test.go

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,7 +1440,6 @@ func TestAccKubernetesPodV1_topologySpreadConstraint(t *testing.T) {
14401440
resource.ParallelTest(t, resource.TestCase{
14411441
PreCheck: func() {
14421442
testAccPreCheck(t)
1443-
skipIfClusterVersionGreaterThanOrEqual(t, "1.17.0")
14441443
},
14451444
ProviderFactories: testAccProviderFactories,
14461445
CheckDestroy: testAccCheckKubernetesPodV1Destroy,
@@ -1450,7 +1449,10 @@ func TestAccKubernetesPodV1_topologySpreadConstraint(t *testing.T) {
14501449
Check: resource.ComposeAggregateTestCheckFunc(
14511450
testAccCheckKubernetesPodV1Exists(resourceName, &conf1),
14521451
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.#", "1"),
1452+
resource.TestCheckTypeSetElemAttr(resourceName, "spec.0.topology_spread_constraint.0.match_label_keys.*", "pod-template-hash"),
14531453
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.0.max_skew", "1"),
1454+
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.0.node_affinity_policy", "Ignore"),
1455+
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.0.node_taints_policy", "Honor"),
14541456
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.0.topology_key", "topology.kubernetes.io/zone"),
14551457
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.0.when_unsatisfiable", "ScheduleAnyway"),
14561458
),
@@ -1465,6 +1467,38 @@ func TestAccKubernetesPodV1_topologySpreadConstraint(t *testing.T) {
14651467
})
14661468
}
14671469

1470+
func TestAccKubernetesPodV1_topologySpreadConstraintMinDomains(t *testing.T) {
1471+
var conf1 api.Pod
1472+
1473+
podName := acctest.RandomWithPrefix("tf-acc-test")
1474+
resourceName := "kubernetes_pod_v1.test"
1475+
imageName := busyboxImage
1476+
1477+
resource.ParallelTest(t, resource.TestCase{
1478+
PreCheck: func() {
1479+
testAccPreCheck(t)
1480+
},
1481+
ProviderFactories: testAccProviderFactories,
1482+
CheckDestroy: testAccCheckKubernetesPodV1Destroy,
1483+
Steps: []resource.TestStep{
1484+
{
1485+
Config: testAccKubernetesPodV1TopologySpreadConstraintConfigMinDomains(podName, imageName),
1486+
Check: resource.ComposeAggregateTestCheckFunc(
1487+
testAccCheckKubernetesPodV1Exists(resourceName, &conf1),
1488+
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.#", "1"),
1489+
resource.TestCheckResourceAttr(resourceName, "spec.0.topology_spread_constraint.0.min_domains", "1"),
1490+
),
1491+
},
1492+
{
1493+
ResourceName: resourceName,
1494+
ImportState: true,
1495+
ImportStateVerify: true,
1496+
ImportStateVerifyIgnore: []string{"metadata.0.resource_version"},
1497+
},
1498+
},
1499+
})
1500+
}
1501+
14681502
func TestAccKubernetesPodV1_runtimeClassName(t *testing.T) {
14691503
var conf1 api.Pod
14701504

@@ -3219,9 +3253,12 @@ func testAccKubernetesPodV1TopologySpreadConstraintConfig(podName, imageName str
32193253
name = "containername"
32203254
}
32213255
topology_spread_constraint {
3222-
max_skew = 1
3223-
topology_key = "topology.kubernetes.io/zone"
3224-
when_unsatisfiable = "ScheduleAnyway"
3256+
match_label_keys = ["pod-template-hash"]
3257+
max_skew = 1
3258+
node_affinity_policy = "Ignore"
3259+
node_taints_policy = "Honor"
3260+
topology_key = "topology.kubernetes.io/zone"
3261+
when_unsatisfiable = "ScheduleAnyway"
32253262
label_selector {
32263263
match_labels = {
32273264
"app.kubernetes.io/instance" = "terraform-example"
@@ -3233,6 +3270,30 @@ func testAccKubernetesPodV1TopologySpreadConstraintConfig(podName, imageName str
32333270
`, podName, imageName)
32343271
}
32353272

3273+
func testAccKubernetesPodV1TopologySpreadConstraintConfigMinDomains(podName, imageName string) string {
3274+
return fmt.Sprintf(`resource "kubernetes_pod_v1" "test" {
3275+
metadata {
3276+
name = "%s"
3277+
}
3278+
spec {
3279+
container {
3280+
image = "%s"
3281+
name = "containername"
3282+
}
3283+
topology_spread_constraint {
3284+
min_domains = 1
3285+
topology_key = "kubernetes.io/hostname"
3286+
label_selector {
3287+
match_labels = {
3288+
"test" = "test"
3289+
}
3290+
}
3291+
}
3292+
}
3293+
}
3294+
`, podName, imageName)
3295+
}
3296+
32363297
func testAccKubernetesPodV1ConfigRuntimeClassName(name, imageName, runtimeHandler string) string {
32373298
return fmt.Sprintf(`resource "kubernetes_runtime_class_v1" "test" {
32383299
metadata {

kubernetes/schema_pod_spec.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,13 +497,43 @@ func podSpecFields(isUpdatable, isComputed bool) map[string]*schema.Schema {
497497
Description: "describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints.",
498498
Elem: &schema.Resource{
499499
Schema: map[string]*schema.Schema{
500+
"match_label_keys": {
501+
Type: schema.TypeSet,
502+
Description: "is a set of pod label keys to select the pods over which spreading will be calculated.",
503+
Optional: true,
504+
ForceNew: !isUpdatable,
505+
Elem: &schema.Schema{
506+
Type: schema.TypeString,
507+
},
508+
},
500509
"max_skew": {
501510
Type: schema.TypeInt,
502511
Description: "describes the degree to which pods may be unevenly distributed.",
503512
Optional: true,
504513
Default: 1,
505514
ValidateFunc: validation.IntAtLeast(1),
506515
},
516+
"min_domains": {
517+
Type: schema.TypeInt,
518+
Description: "indicates a minimum number of eligible domains.",
519+
Optional: true,
520+
ForceNew: !isUpdatable,
521+
ValidateFunc: validation.IntAtLeast(1),
522+
},
523+
"node_affinity_policy": {
524+
Type: schema.TypeString,
525+
Description: "indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew.",
526+
Optional: true,
527+
ForceNew: !isUpdatable,
528+
ValidateFunc: validation.StringInSlice([]string{string(corev1.NodeInclusionPolicyHonor), string(corev1.NodeInclusionPolicyIgnore)}, false),
529+
},
530+
"node_taints_policy": {
531+
Type: schema.TypeString,
532+
Description: "indicates how we will treat node taints when calculating pod topology spread skew.",
533+
Optional: true,
534+
ForceNew: !isUpdatable,
535+
ValidateFunc: validation.StringInSlice([]string{string(corev1.NodeInclusionPolicyHonor), string(corev1.NodeInclusionPolicyIgnore)}, false),
536+
},
507537
"topology_key": {
508538
Type: schema.TypeString,
509539
Description: "the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology.",

kubernetes/structures_pod.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,21 @@ func flattenTopologySpreadConstraints(tsc []v1.TopologySpreadConstraint) []inter
331331
if v.TopologyKey != "" {
332332
obj["topology_key"] = v.TopologyKey
333333
}
334+
if len(v.MatchLabelKeys) != 0 {
335+
obj["match_label_keys"] = newStringSet(schema.HashString, v.MatchLabelKeys)
336+
}
334337
if v.MaxSkew != 0 {
335338
obj["max_skew"] = v.MaxSkew
336339
}
340+
if v.MinDomains != nil && *v.MinDomains != 0 {
341+
obj["min_domains"] = int(*v.MinDomains)
342+
}
343+
if v.NodeAffinityPolicy != nil && *v.NodeAffinityPolicy != "" {
344+
obj["node_affinity_policy"] = string(*v.NodeAffinityPolicy)
345+
}
346+
if v.NodeTaintsPolicy != nil && *v.NodeAffinityPolicy != "" {
347+
obj["node_taints_policy"] = string(*v.NodeTaintsPolicy)
348+
}
337349
if v.WhenUnsatisfiable != "" {
338350
obj["when_unsatisfiable"] = string(v.WhenUnsatisfiable)
339351
}
@@ -1493,9 +1505,21 @@ func expandTopologySpreadConstraints(tsc []interface{}) []v1.TopologySpreadConst
14931505
ts[i].WhenUnsatisfiable = v1.UnsatisfiableConstraintAction(value)
14941506
}
14951507

1508+
if value, ok := m["match_label_keys"].(*schema.Set); ok && value != nil {
1509+
ts[i].MatchLabelKeys = sliceOfString(value.List())
1510+
}
14961511
if value, ok := m["max_skew"].(int); ok {
14971512
ts[i].MaxSkew = int32(value)
14981513
}
1514+
if value, ok := m["min_domains"].(int); ok && value != 0 {
1515+
ts[i].MinDomains = ptr.To(int32(value))
1516+
}
1517+
if value, ok := m["node_affinity_policy"].(string); ok && value != "" {
1518+
ts[i].NodeAffinityPolicy = ptr.To(v1.NodeInclusionPolicy(value))
1519+
}
1520+
if value, ok := m["node_taints_policy"].(string); ok && value != "" {
1521+
ts[i].NodeTaintsPolicy = ptr.To(v1.NodeInclusionPolicy(value))
1522+
}
14991523

15001524
}
15011525
return ts

website/docs/r/pod.html.markdown

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,11 @@ The `items` block supports the following:
863863

864864
#### Arguments
865865

866+
* `match_label_keys` - (Optional) Is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both `match_label_keys` and `label_selector`. `match_label_keys` cannot be set when `label_selector` isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against `label_selector`.
866867
* `max_skew` - (Optional) Describes the degree to which pods may be unevenly distributed. Default value is `1`.
868+
* `min_domains` - (Optional) Indicates a minimum number of eligible domains. Must be number greater than `0`. When set, `when_unsatisfiable` must be set to `DoNotSchedule`.
869+
* `node_affinity_policy` - (Optional) Indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Valid values are `Honor` and `Ignore`. When unset, behavior defaults to `Honor`.
870+
* `node_taints_policy` - (Optional) Indicates how we will treat node taints when calculating pod topology spread skew. Valid values are `Honor` and `Ignore`. When unset, behavior defaults to `Ignore`.
867871
* `topology_key` - (Optional) The key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology.
868872
* `when_unsatisfiable` - (Optional) Indicates how to deal with a pod if it doesn't satisfy the spread constraint. Valid values are `DoNotSchedule` and `ScheduleAnyway`. Default value is `DoNotSchedule`.
869873
* `label_selector` - (Optional) A label query over a set of resources, in this case pods.

website/docs/r/pod_v1.html.markdown

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,11 @@ The `items` block supports the following:
852852

853853
#### Arguments
854854

855+
* `match_label_keys` - (Optional) Is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both `match_label_keys` and `label_selector`. `match_label_keys` cannot be set when `label_selector` isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against `label_selector`.
855856
* `max_skew` - (Optional) Describes the degree to which pods may be unevenly distributed. Default value is `1`.
857+
* `min_domains` - (Optional) Indicates a minimum number of eligible domains. Must be number greater than `0`. When set, `when_unsatisfiable` must be set to `DoNotSchedule`.
858+
* `node_affinity_policy` - (Optional) Indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Valid values are `Honor` and `Ignore`. When unset, behavior defaults to `Honor`.
859+
* `node_taints_policy` - (Optional) Indicates how we will treat node taints when calculating pod topology spread skew. Valid values are `Honor` and `Ignore`. When unset, behavior defaults to `Ignore`.
856860
* `topology_key` - (Optional) The key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology.
857861
* `when_unsatisfiable` - (Optional) Indicates how to deal with a pod if it doesn't satisfy the spread constraint. Valid values are `DoNotSchedule` and `ScheduleAnyway`. Default value is `DoNotSchedule`.
858862
* `label_selector` - (Optional) A label query over a set of resources, in this case pods.

0 commit comments

Comments
 (0)