mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Merge pull request #39851 from liggitt/taint-versioned
Automatic merge from submit-queue Use versioned Taint/Toleration/AvoidPods objects when marshalling fixes #39847 `kubectl taint`, the kubelet's `--register-with-taints` option, and several Taint/Toleration/AllowPod annotation helpers were marshaling/unmarshaling using internal structs
This commit is contained in:
commit
eee819039d
@ -16,6 +16,7 @@ go_library(
|
|||||||
"doc.go",
|
"doc.go",
|
||||||
"field_constants.go",
|
"field_constants.go",
|
||||||
"helpers.go",
|
"helpers.go",
|
||||||
|
"json.go",
|
||||||
"mapper.go",
|
"mapper.go",
|
||||||
"meta.go",
|
"meta.go",
|
||||||
"ref.go",
|
"ref.go",
|
||||||
|
@ -18,7 +18,6 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@ -486,32 +485,6 @@ const (
|
|||||||
UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls"
|
UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
|
|
||||||
// and converts it to the []Toleration type in api.
|
|
||||||
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) {
|
|
||||||
var tolerations []Toleration
|
|
||||||
if len(annotations) > 0 && annotations[TolerationsAnnotationKey] != "" {
|
|
||||||
err := json.Unmarshal([]byte(annotations[TolerationsAnnotationKey]), &tolerations)
|
|
||||||
if err != nil {
|
|
||||||
return tolerations, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tolerations, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTaintsFromNodeAnnotations gets the json serialized taints data from Pod.Annotations
|
|
||||||
// and converts it to the []Taint type in api.
|
|
||||||
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error) {
|
|
||||||
var taints []Taint
|
|
||||||
if len(annotations) > 0 && annotations[TaintsAnnotationKey] != "" {
|
|
||||||
err := json.Unmarshal([]byte(annotations[TaintsAnnotationKey]), &taints)
|
|
||||||
if err != nil {
|
|
||||||
return []Taint{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return taints, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TolerationToleratesTaint checks if the toleration tolerates the taint.
|
// TolerationToleratesTaint checks if the toleration tolerates the taint.
|
||||||
func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
|
func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
|
||||||
if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
|
if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
|
||||||
@ -557,17 +530,6 @@ func (t *Taint) ToString() string {
|
|||||||
return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
|
return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAvoidPodsFromNodeAnnotations(annotations map[string]string) (AvoidPods, error) {
|
|
||||||
var avoidPods AvoidPods
|
|
||||||
if len(annotations) > 0 && annotations[PreferAvoidPodsAnnotationKey] != "" {
|
|
||||||
err := json.Unmarshal([]byte(annotations[PreferAvoidPodsAnnotationKey]), &avoidPods)
|
|
||||||
if err != nil {
|
|
||||||
return avoidPods, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return avoidPods, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls
|
// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls
|
||||||
// and a slice of unsafe Sysctls. This is only a convenience wrapper around
|
// and a slice of unsafe Sysctls. This is only a convenience wrapper around
|
||||||
// SysctlsFromPodAnnotation.
|
// SysctlsFromPodAnnotation.
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
)
|
)
|
||||||
@ -342,102 +341,6 @@ func TestMatchTaint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAvoidPodsFromNode(t *testing.T) {
|
|
||||||
controllerFlag := true
|
|
||||||
testCases := []struct {
|
|
||||||
node *Node
|
|
||||||
expectValue AvoidPods
|
|
||||||
expectErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
node: &Node{},
|
|
||||||
expectValue: AvoidPods{},
|
|
||||||
expectErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
node: &Node{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Annotations: map[string]string{
|
|
||||||
PreferAvoidPodsAnnotationKey: `
|
|
||||||
{
|
|
||||||
"preferAvoidPods": [
|
|
||||||
{
|
|
||||||
"podSignature": {
|
|
||||||
"podController": {
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "ReplicationController",
|
|
||||||
"name": "foo",
|
|
||||||
"uid": "abcdef123456",
|
|
||||||
"controller": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"reason": "some reason",
|
|
||||||
"message": "some message"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectValue: AvoidPods{
|
|
||||||
PreferAvoidPods: []PreferAvoidPodsEntry{
|
|
||||||
{
|
|
||||||
PodSignature: PodSignature{
|
|
||||||
PodController: &metav1.OwnerReference{
|
|
||||||
APIVersion: "v1",
|
|
||||||
Kind: "ReplicationController",
|
|
||||||
Name: "foo",
|
|
||||||
UID: "abcdef123456",
|
|
||||||
Controller: &controllerFlag,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Reason: "some reason",
|
|
||||||
Message: "some message",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
node: &Node{
|
|
||||||
// Missing end symbol of "podController" and "podSignature"
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Annotations: map[string]string{
|
|
||||||
PreferAvoidPodsAnnotationKey: `
|
|
||||||
{
|
|
||||||
"preferAvoidPods": [
|
|
||||||
{
|
|
||||||
"podSignature": {
|
|
||||||
"podController": {
|
|
||||||
"kind": "ReplicationController",
|
|
||||||
"apiVersion": "v1"
|
|
||||||
"reason": "some reason",
|
|
||||||
"message": "some message"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectValue: AvoidPods{},
|
|
||||||
expectErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tc := range testCases {
|
|
||||||
v, err := GetAvoidPodsFromNodeAnnotations(tc.node.Annotations)
|
|
||||||
if err == nil && tc.expectErr {
|
|
||||||
t.Errorf("[%v]expected error but got none.", i)
|
|
||||||
}
|
|
||||||
if err != nil && !tc.expectErr {
|
|
||||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(tc.expectValue, v) {
|
|
||||||
t.Errorf("[%v]expect value %v but got %v with %v", i, tc.expectValue, v, v.PreferAvoidPods[0].PodSignature.PodController.Controller)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSysctlsFromPodAnnotation(t *testing.T) {
|
func TestSysctlsFromPodAnnotation(t *testing.T) {
|
||||||
type Test struct {
|
type Test struct {
|
||||||
annotation string
|
annotation string
|
||||||
|
40
pkg/api/json.go
Normal file
40
pkg/api/json.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
// This file implements json marshaling/unmarshaling interfaces on objects that are currently marshaled into annotations
|
||||||
|
// to prevent anyone from marshaling these internal structs.
|
||||||
|
|
||||||
|
var _ = json.Marshaler(Taint{})
|
||||||
|
var _ = json.Unmarshaler(&Taint{})
|
||||||
|
|
||||||
|
func (Taint) MarshalJSON() ([]byte, error) { panic("do not marshal internal struct") }
|
||||||
|
func (*Taint) UnmarshalJSON([]byte) error { panic("do not unmarshal to internal struct") }
|
||||||
|
|
||||||
|
var _ = json.Marshaler(Toleration{})
|
||||||
|
var _ = json.Unmarshaler(&Toleration{})
|
||||||
|
|
||||||
|
func (Toleration) MarshalJSON() ([]byte, error) { panic("do not marshal internal struct") }
|
||||||
|
func (*Toleration) UnmarshalJSON([]byte) error { panic("do not unmarshal to internal struct") }
|
||||||
|
|
||||||
|
var _ = json.Marshaler(&AvoidPods{})
|
||||||
|
var _ = json.Unmarshaler(&AvoidPods{})
|
||||||
|
|
||||||
|
func (AvoidPods) MarshalJSON() ([]byte, error) { panic("do not marshal internal struct") }
|
||||||
|
func (*AvoidPods) UnmarshalJSON([]byte) error { panic("do not unmarshal to internal struct") }
|
@ -23,6 +23,7 @@ go_library(
|
|||||||
"//pkg/api/resource:go_default_library",
|
"//pkg/api/resource:go_default_library",
|
||||||
"//pkg/api/service:go_default_library",
|
"//pkg/api/service:go_default_library",
|
||||||
"//pkg/api/util:go_default_library",
|
"//pkg/api/util:go_default_library",
|
||||||
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/api/validation/genericvalidation:go_default_library",
|
"//pkg/api/validation/genericvalidation:go_default_library",
|
||||||
"//pkg/apis/storage/util:go_default_library",
|
"//pkg/apis/storage/util:go_default_library",
|
||||||
"//pkg/capabilities:go_default_library",
|
"//pkg/capabilities:go_default_library",
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
utilpod "k8s.io/kubernetes/pkg/api/pod"
|
utilpod "k8s.io/kubernetes/pkg/api/pod"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
apiservice "k8s.io/kubernetes/pkg/api/service"
|
apiservice "k8s.io/kubernetes/pkg/api/service"
|
||||||
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/validation/genericvalidation"
|
"k8s.io/kubernetes/pkg/api/validation/genericvalidation"
|
||||||
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
|
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
|
||||||
"k8s.io/kubernetes/pkg/capabilities"
|
"k8s.io/kubernetes/pkg/capabilities"
|
||||||
@ -1846,11 +1847,16 @@ func ValidateNodeSelector(nodeSelector *api.NodeSelector, fldPath *field.Path) f
|
|||||||
func ValidateAvoidPodsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
func ValidateAvoidPodsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
avoids, err := api.GetAvoidPodsFromNodeAnnotations(annotations)
|
v1Avoids, err := v1.GetAvoidPodsFromNodeAnnotations(annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("AvoidPods"), api.PreferAvoidPodsAnnotationKey, err.Error()))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("AvoidPods"), api.PreferAvoidPodsAnnotationKey, err.Error()))
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
var avoids api.AvoidPods
|
||||||
|
if err := v1.Convert_v1_AvoidPods_To_api_AvoidPods(&v1Avoids, &avoids, nil); err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("AvoidPods"), api.PreferAvoidPodsAnnotationKey, err.Error()))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
if len(avoids.PreferAvoidPods) != 0 {
|
if len(avoids.PreferAvoidPods) != 0 {
|
||||||
for i, pa := range avoids.PreferAvoidPods {
|
for i, pa := range avoids.PreferAvoidPods {
|
||||||
@ -1976,11 +1982,18 @@ func validatePodAffinity(podAffinity *api.PodAffinity, fldPath *field.Path) fiel
|
|||||||
func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
tolerations, err := api.GetTolerationsFromPodAnnotations(annotations)
|
v1Tolerations, err := v1.GetTolerationsFromPodAnnotations(annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath, api.TolerationsAnnotationKey, err.Error()))
|
allErrs = append(allErrs, field.Invalid(fldPath, api.TolerationsAnnotationKey, err.Error()))
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
tolerations := make([]api.Toleration, len(v1Tolerations))
|
||||||
|
for i := range v1Tolerations {
|
||||||
|
if err := v1.Convert_v1_Toleration_To_api_Toleration(&v1Tolerations[i], &tolerations[i], nil); err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath, api.TolerationsAnnotationKey, err.Error()))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(tolerations) > 0 {
|
if len(tolerations) > 0 {
|
||||||
allErrs = append(allErrs, validateTolerations(tolerations, fldPath.Child(api.TolerationsAnnotationKey))...)
|
allErrs = append(allErrs, validateTolerations(tolerations, fldPath.Child(api.TolerationsAnnotationKey))...)
|
||||||
}
|
}
|
||||||
@ -2676,11 +2689,18 @@ func validateTaints(taints []api.Taint, fldPath *field.Path) field.ErrorList {
|
|||||||
func ValidateTaintsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
func ValidateTaintsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
taints, err := api.GetTaintsFromNodeAnnotations(annotations)
|
v1Taints, err := v1.GetTaintsFromNodeAnnotations(annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath, api.TaintsAnnotationKey, err.Error()))
|
allErrs = append(allErrs, field.Invalid(fldPath, api.TaintsAnnotationKey, err.Error()))
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
taints := make([]api.Taint, len(v1Taints))
|
||||||
|
for i := range v1Taints {
|
||||||
|
if err := v1.Convert_v1_Taint_To_api_Taint(&v1Taints[i], &taints[i], nil); err != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath, api.TaintsAnnotationKey, err.Error()))
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(taints) > 0 {
|
if len(taints) > 0 {
|
||||||
allErrs = append(allErrs, validateTaints(taints, fldPath.Child(api.TaintsAnnotationKey))...)
|
allErrs = append(allErrs, validateTaints(taints, fldPath.Child(api.TaintsAnnotationKey))...)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/validation"
|
"k8s.io/apimachinery/pkg/util/validation"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
@ -44,8 +44,8 @@ import (
|
|||||||
// TaintOptions have the data required to perform the taint operation
|
// TaintOptions have the data required to perform the taint operation
|
||||||
type TaintOptions struct {
|
type TaintOptions struct {
|
||||||
resources []string
|
resources []string
|
||||||
taintsToAdd []api.Taint
|
taintsToAdd []v1.Taint
|
||||||
taintsToRemove []api.Taint
|
taintsToRemove []v1.Taint
|
||||||
builder *resource.Builder
|
builder *resource.Builder
|
||||||
selector string
|
selector string
|
||||||
overwrite bool
|
overwrite bool
|
||||||
@ -112,8 +112,8 @@ func NewCmdTaint(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteTaint(taints []api.Taint, taintToDelete api.Taint) ([]api.Taint, error) {
|
func deleteTaint(taints []v1.Taint, taintToDelete v1.Taint) ([]v1.Taint, error) {
|
||||||
newTaints := []api.Taint{}
|
newTaints := []v1.Taint{}
|
||||||
found := false
|
found := false
|
||||||
for _, taint := range taints {
|
for _, taint := range taints {
|
||||||
if taint.Key == taintToDelete.Key &&
|
if taint.Key == taintToDelete.Key &&
|
||||||
@ -132,14 +132,14 @@ func deleteTaint(taints []api.Taint, taintToDelete api.Taint) ([]api.Taint, erro
|
|||||||
|
|
||||||
// reorganizeTaints returns the updated set of taints, taking into account old taints that were not updated,
|
// reorganizeTaints returns the updated set of taints, taking into account old taints that were not updated,
|
||||||
// old taints that were updated, old taints that were deleted, and new taints.
|
// old taints that were updated, old taints that were deleted, and new taints.
|
||||||
func reorganizeTaints(accessor metav1.Object, overwrite bool, taintsToAdd []api.Taint, taintsToRemove []api.Taint) ([]api.Taint, error) {
|
func reorganizeTaints(accessor metav1.Object, overwrite bool, taintsToAdd []v1.Taint, taintsToRemove []v1.Taint) ([]v1.Taint, error) {
|
||||||
newTaints := append([]api.Taint{}, taintsToAdd...)
|
newTaints := append([]v1.Taint{}, taintsToAdd...)
|
||||||
|
|
||||||
var oldTaints []api.Taint
|
var oldTaints []v1.Taint
|
||||||
var err error
|
var err error
|
||||||
annotations := accessor.GetAnnotations()
|
annotations := accessor.GetAnnotations()
|
||||||
if annotations != nil {
|
if annotations != nil {
|
||||||
if oldTaints, err = api.GetTaintsFromNodeAnnotations(annotations); err != nil {
|
if oldTaints, err = v1.GetTaintsFromNodeAnnotations(annotations); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,9 +168,9 @@ func reorganizeTaints(accessor metav1.Object, overwrite bool, taintsToAdd []api.
|
|||||||
return newTaints, utilerrors.NewAggregate(allErrs)
|
return newTaints, utilerrors.NewAggregate(allErrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTaints(spec []string) ([]api.Taint, []api.Taint, error) {
|
func parseTaints(spec []string) ([]v1.Taint, []v1.Taint, error) {
|
||||||
var taints, taintsToRemove []api.Taint
|
var taints, taintsToRemove []v1.Taint
|
||||||
uniqueTaints := map[api.TaintEffect]sets.String{}
|
uniqueTaints := map[v1.TaintEffect]sets.String{}
|
||||||
|
|
||||||
for _, taintSpec := range spec {
|
for _, taintSpec := range spec {
|
||||||
if strings.Index(taintSpec, "=") != -1 && strings.Index(taintSpec, ":") != -1 {
|
if strings.Index(taintSpec, "=") != -1 && strings.Index(taintSpec, ":") != -1 {
|
||||||
@ -191,13 +191,13 @@ func parseTaints(spec []string) ([]api.Taint, []api.Taint, error) {
|
|||||||
taints = append(taints, newTaint)
|
taints = append(taints, newTaint)
|
||||||
} else if strings.HasSuffix(taintSpec, "-") {
|
} else if strings.HasSuffix(taintSpec, "-") {
|
||||||
taintKey := taintSpec[:len(taintSpec)-1]
|
taintKey := taintSpec[:len(taintSpec)-1]
|
||||||
var effect api.TaintEffect
|
var effect v1.TaintEffect
|
||||||
if strings.Index(taintKey, ":") != -1 {
|
if strings.Index(taintKey, ":") != -1 {
|
||||||
parts := strings.Split(taintKey, ":")
|
parts := strings.Split(taintKey, ":")
|
||||||
taintKey = parts[0]
|
taintKey = parts[0]
|
||||||
effect = api.TaintEffect(parts[1])
|
effect = v1.TaintEffect(parts[1])
|
||||||
}
|
}
|
||||||
taintsToRemove = append(taintsToRemove, api.Taint{Key: taintKey, Effect: effect})
|
taintsToRemove = append(taintsToRemove, v1.Taint{Key: taintKey, Effect: effect})
|
||||||
} else {
|
} else {
|
||||||
return nil, nil, fmt.Errorf("unknown taint spec: %v", taintSpec)
|
return nil, nil, fmt.Errorf("unknown taint spec: %v", taintSpec)
|
||||||
}
|
}
|
||||||
@ -363,14 +363,14 @@ func (o TaintOptions) RunTaint() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateNoTaintOverwrites validates that when overwrite is false, to-be-updated taints don't exist in the node taint list (yet)
|
// validateNoTaintOverwrites validates that when overwrite is false, to-be-updated taints don't exist in the node taint list (yet)
|
||||||
func validateNoTaintOverwrites(accessor metav1.Object, taints []api.Taint) error {
|
func validateNoTaintOverwrites(accessor metav1.Object, taints []v1.Taint) error {
|
||||||
annotations := accessor.GetAnnotations()
|
annotations := accessor.GetAnnotations()
|
||||||
if annotations == nil {
|
if annotations == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
allErrs := []error{}
|
allErrs := []error{}
|
||||||
oldTaints, err := api.GetTaintsFromNodeAnnotations(annotations)
|
oldTaints, err := v1.GetTaintsFromNodeAnnotations(annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
allErrs = append(allErrs, err)
|
allErrs = append(allErrs, err)
|
||||||
return utilerrors.NewAggregate(allErrs)
|
return utilerrors.NewAggregate(allErrs)
|
||||||
@ -412,7 +412,7 @@ func (o TaintOptions) updateTaints(obj runtime.Object) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
annotations[api.TaintsAnnotationKey] = string(taintsData)
|
annotations[v1.TaintsAnnotationKey] = string(taintsData)
|
||||||
accessor.SetAnnotations(annotations)
|
accessor.SetAnnotations(annotations)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -35,7 +35,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/util/strategicpatch"
|
"k8s.io/kubernetes/pkg/util/strategicpatch"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateNodeAndTaintedNode(oldTaints []api.Taint, newTaints []api.Taint) (*api.Node, *api.Node) {
|
func generateNodeAndTaintedNode(oldTaints []v1.Taint, newTaints []v1.Taint) (*api.Node, *api.Node) {
|
||||||
var taintedNode *api.Node
|
var taintedNode *api.Node
|
||||||
|
|
||||||
oldTaintsData, _ := json.Marshal(oldTaints)
|
oldTaintsData, _ := json.Marshal(oldTaints)
|
||||||
@ -45,7 +45,7 @@ func generateNodeAndTaintedNode(oldTaints []api.Taint, newTaints []api.Taint) (*
|
|||||||
Name: "node-name",
|
Name: "node-name",
|
||||||
CreationTimestamp: metav1.Time{Time: time.Now()},
|
CreationTimestamp: metav1.Time{Time: time.Now()},
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
api.TaintsAnnotationKey: string(oldTaintsData),
|
v1.TaintsAnnotationKey: string(oldTaintsData),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.NodeSpec{
|
Spec: api.NodeSpec{
|
||||||
@ -59,18 +59,18 @@ func generateNodeAndTaintedNode(oldTaints []api.Taint, newTaints []api.Taint) (*
|
|||||||
// A copy of the same node, but tainted.
|
// A copy of the same node, but tainted.
|
||||||
taintedNode = clone.(*api.Node)
|
taintedNode = clone.(*api.Node)
|
||||||
taintedNode.Annotations = map[string]string{
|
taintedNode.Annotations = map[string]string{
|
||||||
api.TaintsAnnotationKey: string(newTaintsData),
|
v1.TaintsAnnotationKey: string(newTaintsData),
|
||||||
}
|
}
|
||||||
|
|
||||||
return node, taintedNode
|
return node, taintedNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func AnnotationsHaveEqualTaints(annotationA map[string]string, annotationB map[string]string) bool {
|
func AnnotationsHaveEqualTaints(annotationA map[string]string, annotationB map[string]string) bool {
|
||||||
taintsA, err := api.GetTaintsFromNodeAnnotations(annotationA)
|
taintsA, err := v1.GetTaintsFromNodeAnnotations(annotationA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
taintsB, err := api.GetTaintsFromNodeAnnotations(annotationB)
|
taintsB, err := v1.GetTaintsFromNodeAnnotations(annotationB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -97,8 +97,8 @@ func AnnotationsHaveEqualTaints(annotationA map[string]string, annotationB map[s
|
|||||||
func TestTaint(t *testing.T) {
|
func TestTaint(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
description string
|
description string
|
||||||
oldTaints []api.Taint
|
oldTaints []v1.Taint
|
||||||
newTaints []api.Taint
|
newTaints []v1.Taint
|
||||||
args []string
|
args []string
|
||||||
expectFatal bool
|
expectFatal bool
|
||||||
expectTaint bool
|
expectTaint bool
|
||||||
@ -106,7 +106,7 @@ func TestTaint(t *testing.T) {
|
|||||||
// success cases
|
// success cases
|
||||||
{
|
{
|
||||||
description: "taints a node with effect NoSchedule",
|
description: "taints a node with effect NoSchedule",
|
||||||
newTaints: []api.Taint{{
|
newTaints: []v1.Taint{{
|
||||||
Key: "foo",
|
Key: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
@ -117,7 +117,7 @@ func TestTaint(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "taints a node with effect PreferNoSchedule",
|
description: "taints a node with effect PreferNoSchedule",
|
||||||
newTaints: []api.Taint{{
|
newTaints: []v1.Taint{{
|
||||||
Key: "foo",
|
Key: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
Effect: "PreferNoSchedule",
|
Effect: "PreferNoSchedule",
|
||||||
@ -128,12 +128,12 @@ func TestTaint(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "update an existing taint on the node, change the value from bar to barz",
|
description: "update an existing taint on the node, change the value from bar to barz",
|
||||||
oldTaints: []api.Taint{{
|
oldTaints: []v1.Taint{{
|
||||||
Key: "foo",
|
Key: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
}},
|
}},
|
||||||
newTaints: []api.Taint{{
|
newTaints: []v1.Taint{{
|
||||||
Key: "foo",
|
Key: "foo",
|
||||||
Value: "barz",
|
Value: "barz",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
@ -144,7 +144,7 @@ func TestTaint(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "taints a node with two taints",
|
description: "taints a node with two taints",
|
||||||
newTaints: []api.Taint{{
|
newTaints: []v1.Taint{{
|
||||||
Key: "dedicated",
|
Key: "dedicated",
|
||||||
Value: "namespaceA",
|
Value: "namespaceA",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
@ -159,7 +159,7 @@ func TestTaint(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "node has two taints with the same key but different effect, remove one of them by indicating exact key and effect",
|
description: "node has two taints with the same key but different effect, remove one of them by indicating exact key and effect",
|
||||||
oldTaints: []api.Taint{{
|
oldTaints: []v1.Taint{{
|
||||||
Key: "dedicated",
|
Key: "dedicated",
|
||||||
Value: "namespaceA",
|
Value: "namespaceA",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
@ -168,7 +168,7 @@ func TestTaint(t *testing.T) {
|
|||||||
Value: "namespaceA",
|
Value: "namespaceA",
|
||||||
Effect: "PreferNoSchedule",
|
Effect: "PreferNoSchedule",
|
||||||
}},
|
}},
|
||||||
newTaints: []api.Taint{{
|
newTaints: []v1.Taint{{
|
||||||
Key: "dedicated",
|
Key: "dedicated",
|
||||||
Value: "namespaceA",
|
Value: "namespaceA",
|
||||||
Effect: "PreferNoSchedule",
|
Effect: "PreferNoSchedule",
|
||||||
@ -179,7 +179,7 @@ func TestTaint(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "node has two taints with the same key but different effect, remove all of them with wildcard",
|
description: "node has two taints with the same key but different effect, remove all of them with wildcard",
|
||||||
oldTaints: []api.Taint{{
|
oldTaints: []v1.Taint{{
|
||||||
Key: "dedicated",
|
Key: "dedicated",
|
||||||
Value: "namespaceA",
|
Value: "namespaceA",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
@ -188,14 +188,14 @@ func TestTaint(t *testing.T) {
|
|||||||
Value: "namespaceA",
|
Value: "namespaceA",
|
||||||
Effect: "PreferNoSchedule",
|
Effect: "PreferNoSchedule",
|
||||||
}},
|
}},
|
||||||
newTaints: []api.Taint{},
|
newTaints: []v1.Taint{},
|
||||||
args: []string{"node", "node-name", "dedicated-"},
|
args: []string{"node", "node-name", "dedicated-"},
|
||||||
expectFatal: false,
|
expectFatal: false,
|
||||||
expectTaint: true,
|
expectTaint: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "node has two taints, update one of them and remove the other",
|
description: "node has two taints, update one of them and remove the other",
|
||||||
oldTaints: []api.Taint{{
|
oldTaints: []v1.Taint{{
|
||||||
Key: "dedicated",
|
Key: "dedicated",
|
||||||
Value: "namespaceA",
|
Value: "namespaceA",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
@ -204,7 +204,7 @@ func TestTaint(t *testing.T) {
|
|||||||
Value: "bar",
|
Value: "bar",
|
||||||
Effect: "PreferNoSchedule",
|
Effect: "PreferNoSchedule",
|
||||||
}},
|
}},
|
||||||
newTaints: []api.Taint{{
|
newTaints: []v1.Taint{{
|
||||||
Key: "foo",
|
Key: "foo",
|
||||||
Value: "barz",
|
Value: "barz",
|
||||||
Effect: "PreferNoSchedule",
|
Effect: "PreferNoSchedule",
|
||||||
@ -235,12 +235,12 @@ func TestTaint(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "can't update existing taint on the node, since 'overwrite' flag is not set",
|
description: "can't update existing taint on the node, since 'overwrite' flag is not set",
|
||||||
oldTaints: []api.Taint{{
|
oldTaints: []v1.Taint{{
|
||||||
Key: "foo",
|
Key: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
}},
|
}},
|
||||||
newTaints: []api.Taint{{
|
newTaints: []v1.Taint{{
|
||||||
Key: "foo",
|
Key: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
Effect: "NoSchedule",
|
Effect: "NoSchedule",
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/events"
|
"k8s.io/kubernetes/pkg/api/events"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/apps"
|
"k8s.io/kubernetes/pkg/apis/apps"
|
||||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||||
"k8s.io/kubernetes/pkg/apis/batch"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
@ -2748,9 +2749,15 @@ func printLabelsMultilineWithIndent(w *PrefixWriter, initialIndent, title, inner
|
|||||||
|
|
||||||
// printTaintsMultiline prints multiple taints with a proper alignment.
|
// printTaintsMultiline prints multiple taints with a proper alignment.
|
||||||
func printTaintsInAnnotationMultiline(w *PrefixWriter, title string, annotations map[string]string) {
|
func printTaintsInAnnotationMultiline(w *PrefixWriter, title string, annotations map[string]string) {
|
||||||
taints, err := api.GetTaintsFromNodeAnnotations(annotations)
|
v1Taints, err := v1.GetTaintsFromNodeAnnotations(annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
taints = []api.Taint{}
|
v1Taints = []v1.Taint{}
|
||||||
|
}
|
||||||
|
taints := make([]api.Taint, len(v1Taints))
|
||||||
|
for i := range v1Taints {
|
||||||
|
if err := v1.Convert_v1_Taint_To_api_Taint(&v1Taints[i], &taints[i], nil); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printTaintsMultilineWithIndent(w, "", title, "\t", taints)
|
printTaintsMultilineWithIndent(w, "", title, "\t", taints)
|
||||||
}
|
}
|
||||||
@ -2787,9 +2794,15 @@ func printTaintsMultilineWithIndent(w *PrefixWriter, initialIndent, title, inner
|
|||||||
|
|
||||||
// printTolerationsMultiline prints multiple tolerations with a proper alignment.
|
// printTolerationsMultiline prints multiple tolerations with a proper alignment.
|
||||||
func printTolerationsInAnnotationMultiline(w *PrefixWriter, title string, annotations map[string]string) {
|
func printTolerationsInAnnotationMultiline(w *PrefixWriter, title string, annotations map[string]string) {
|
||||||
tolerations, err := api.GetTolerationsFromPodAnnotations(annotations)
|
v1Tolerations, err := v1.GetTolerationsFromPodAnnotations(annotations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tolerations = []api.Toleration{}
|
v1Tolerations = []v1.Toleration{}
|
||||||
|
}
|
||||||
|
tolerations := make([]api.Toleration, len(v1Tolerations))
|
||||||
|
for i := range v1Tolerations {
|
||||||
|
if err := v1.Convert_v1_Toleration_To_api_Toleration(&v1Tolerations[i], &tolerations[i], nil); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printTolerationsMultilineWithIndent(w, "", title, "\t", tolerations)
|
printTolerationsMultilineWithIndent(w, "", title, "\t", tolerations)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ func TestDescribePod(t *testing.T) {
|
|||||||
|
|
||||||
func TestDescribePodTolerations(t *testing.T) {
|
func TestDescribePodTolerations(t *testing.T) {
|
||||||
|
|
||||||
podTolerations := []api.Toleration{{Key: "key1", Value: "value1"},
|
podTolerations := []v1.Toleration{{Key: "key1", Value: "value1"},
|
||||||
{Key: "key2", Value: "value2"}}
|
{Key: "key2", Value: "value2"}}
|
||||||
pt, _ := json.Marshal(podTolerations)
|
pt, _ := json.Marshal(podTolerations)
|
||||||
fake := fake.NewSimpleClientset(&api.Pod{
|
fake := fake.NewSimpleClientset(&api.Pod{
|
||||||
@ -77,7 +77,7 @@ func TestDescribePodTolerations(t *testing.T) {
|
|||||||
Name: "bar",
|
Name: "bar",
|
||||||
Namespace: "foo",
|
Namespace: "foo",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
api.TolerationsAnnotationKey: string(pt),
|
v1.TolerationsAnnotationKey: string(pt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -204,7 +204,13 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) {
|
|||||||
}
|
}
|
||||||
if len(kl.kubeletConfiguration.RegisterWithTaints) > 0 {
|
if len(kl.kubeletConfiguration.RegisterWithTaints) > 0 {
|
||||||
annotations := make(map[string]string)
|
annotations := make(map[string]string)
|
||||||
b, err := json.Marshal(kl.kubeletConfiguration.RegisterWithTaints)
|
taints := make([]v1.Taint, len(kl.kubeletConfiguration.RegisterWithTaints))
|
||||||
|
for i := range kl.kubeletConfiguration.RegisterWithTaints {
|
||||||
|
if err := v1.Convert_api_Taint_To_v1_Taint(&kl.kubeletConfiguration.RegisterWithTaints[i], &taints[i], nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(taints)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ go_library(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
|
"//pkg/api/v1:go_default_library",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -23,11 +23,12 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/validation"
|
"k8s.io/apimachinery/pkg/util/validation"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseTaint parses a taint from a string. Taint must be off the format '<key>=<value>:<effect>'.
|
// ParseTaint parses a taint from a string. Taint must be off the format '<key>=<value>:<effect>'.
|
||||||
func ParseTaint(st string) (api.Taint, error) {
|
func ParseTaint(st string) (v1.Taint, error) {
|
||||||
var taint api.Taint
|
var taint v1.Taint
|
||||||
parts := strings.Split(st, "=")
|
parts := strings.Split(st, "=")
|
||||||
if len(parts) != 2 || len(parts[1]) == 0 || len(validation.IsQualifiedName(parts[0])) > 0 {
|
if len(parts) != 2 || len(parts[1]) == 0 || len(validation.IsQualifiedName(parts[0])) > 0 {
|
||||||
return taint, fmt.Errorf("invalid taint spec: %v", st)
|
return taint, fmt.Errorf("invalid taint spec: %v", st)
|
||||||
@ -35,14 +36,14 @@ func ParseTaint(st string) (api.Taint, error) {
|
|||||||
|
|
||||||
parts2 := strings.Split(parts[1], ":")
|
parts2 := strings.Split(parts[1], ":")
|
||||||
|
|
||||||
effect := api.TaintEffect(parts2[1])
|
effect := v1.TaintEffect(parts2[1])
|
||||||
|
|
||||||
errs := validation.IsValidLabelValue(parts2[0])
|
errs := validation.IsValidLabelValue(parts2[0])
|
||||||
if len(parts2) != 2 || len(errs) != 0 {
|
if len(parts2) != 2 || len(errs) != 0 {
|
||||||
return taint, fmt.Errorf("invalid taint spec: %v, %s", st, strings.Join(errs, "; "))
|
return taint, fmt.Errorf("invalid taint spec: %v, %s", st, strings.Join(errs, "; "))
|
||||||
}
|
}
|
||||||
|
|
||||||
if effect != api.TaintEffectNoSchedule && effect != api.TaintEffectPreferNoSchedule {
|
if effect != v1.TaintEffectNoSchedule && effect != v1.TaintEffectPreferNoSchedule {
|
||||||
return taint, fmt.Errorf("invalid taint spec: %v, unsupported taint effect", st)
|
return taint, fmt.Errorf("invalid taint spec: %v, unsupported taint effect", st)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ func (t taintsVar) Set(s string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
taints = append(taints, taint)
|
taints = append(taints, api.Taint{Key: taint.Key, Value: taint.Value, Effect: api.TaintEffect(taint.Effect)})
|
||||||
}
|
}
|
||||||
*t.ptr = taints
|
*t.ptr = taints
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user