From d419bdfcd94e4bd2d1218bdcd9461f0f6b810b62 Mon Sep 17 00:00:00 2001 From: Tim Allclair Date: Mon, 6 May 2019 18:38:56 -0700 Subject: [PATCH] Validate topology --- pkg/apis/node/validation/BUILD | 2 + pkg/apis/node/validation/validation.go | 14 ++++ pkg/apis/node/validation/validation_test.go | 89 +++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/pkg/apis/node/validation/BUILD b/pkg/apis/node/validation/BUILD index 7d7345099df..0633424f1c6 100644 --- a/pkg/apis/node/validation/BUILD +++ b/pkg/apis/node/validation/BUILD @@ -6,6 +6,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/apis/node/validation", visibility = ["//visibility:public"], deps = [ + "//pkg/apis/core/validation:go_default_library", "//pkg/apis/node:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", @@ -17,6 +18,7 @@ go_test( srcs = ["validation_test.go"], embed = [":go_default_library"], deps = [ + "//pkg/apis/core:go_default_library", "//pkg/apis/node:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/pkg/apis/node/validation/validation.go b/pkg/apis/node/validation/validation.go index b89a01ff58d..a8cc562ed07 100644 --- a/pkg/apis/node/validation/validation.go +++ b/pkg/apis/node/validation/validation.go @@ -19,6 +19,7 @@ package validation import ( apivalidation "k8s.io/apimachinery/pkg/api/validation" "k8s.io/apimachinery/pkg/util/validation/field" + corevalidation "k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/apis/node" ) @@ -30,6 +31,10 @@ func ValidateRuntimeClass(rc *node.RuntimeClass) field.ErrorList { allErrs = append(allErrs, field.Invalid(field.NewPath("handler"), rc.Handler, msg)) } + if rc.Topology != nil { + allErrs = append(allErrs, validateTopology(rc.Topology, field.NewPath("topology"))...) + } + return allErrs } @@ -41,3 +46,12 @@ func ValidateRuntimeClassUpdate(new, old *node.RuntimeClass) field.ErrorList { return allErrs } + +func validateTopology(t *node.Topology, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + if t.NodeSelector != nil { + allErrs = append(allErrs, corevalidation.ValidateNodeSelector(t.NodeSelector, fldPath.Child("nodeSelector"))...) + } + allErrs = append(allErrs, corevalidation.ValidateTolerations(t.Tolerations, fldPath.Child("tolerations"))...) + return allErrs +} diff --git a/pkg/apis/node/validation/validation_test.go b/pkg/apis/node/validation/validation_test.go index fcbdc0e9a1d..aafe677763b 100644 --- a/pkg/apis/node/validation/validation_test.go +++ b/pkg/apis/node/validation/validation_test.go @@ -20,6 +20,7 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/node" "github.com/stretchr/testify/assert" @@ -126,3 +127,91 @@ func TestValidateRuntimeUpdate(t *testing.T) { }) } } + +func TestValidateTopology(t *testing.T) { + tests := []struct { + name string + topology *node.Topology + expectErrs int + }{{ + name: "valid topology", + topology: &node.Topology{ + NodeSelector: &core.NodeSelector{ + NodeSelectorTerms: []core.NodeSelectorTerm{{ + MatchExpressions: []core.NodeSelectorRequirement{{ + Key: "valid", + Operator: core.NodeSelectorOpExists, + }}, + }}, + }, + Tolerations: []core.Toleration{{ + Key: "valid", + Operator: core.TolerationOpExists, + Effect: core.TaintEffectNoSchedule, + }}, + }, + }, { + name: "empty topology", + topology: &node.Topology{}, + }, { + name: "invalid nodeSelector", + topology: &node.Topology{ + NodeSelector: &core.NodeSelector{ + NodeSelectorTerms: []core.NodeSelectorTerm{{ + MatchExpressions: []core.NodeSelectorRequirement{{ + Key: "not a valid key!!!", + Operator: core.NodeSelectorOpExists, + }}, + }}, + }, + }, + expectErrs: 1, + }, { + name: "invalid toleration", + topology: &node.Topology{ + Tolerations: []core.Toleration{{ + Key: "valid", + Operator: core.TolerationOpExists, + Effect: core.TaintEffectNoSchedule, + }, { + Key: "not a valid key!!!", + Operator: core.TolerationOpExists, + Effect: core.TaintEffectNoSchedule, + }}, + }, + expectErrs: 1, + }, { + name: "invalid topology", + topology: &node.Topology{ + NodeSelector: &core.NodeSelector{ + NodeSelectorTerms: []core.NodeSelectorTerm{{ + MatchExpressions: []core.NodeSelectorRequirement{{ + Key: "not a valid label key!!!", + Operator: core.NodeSelectorOpExists, + }}, + }}, + }, + Tolerations: []core.Toleration{{ + Key: "valid", + Operator: core.TolerationOpExists, + Effect: core.TaintEffectNoSchedule, + }, { + Key: "not a valid toleration key!!!", + Operator: core.TolerationOpExists, + Effect: core.TaintEffectNoSchedule, + }}, + }, + expectErrs: 2, + }} + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + rc := &node.RuntimeClass{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Handler: "bar", + Topology: test.topology, + } + assert.Len(t, ValidateRuntimeClass(rc), test.expectErrs) + }) + } +}