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:
Kubernetes Submit Queue 2017-01-18 11:30:36 -08:00 committed by GitHub
commit eee819039d
13 changed files with 136 additions and 188 deletions

View File

@ -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",

View File

@ -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.

View File

@ -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
View 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") }

View File

@ -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",

View File

@ -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))...)
} }

View File

@ -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

View File

@ -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",

View File

@ -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)
} }

View File

@ -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),
}, },
}, },
}) })

View File

@ -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
} }

View File

@ -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",
], ],
) )

View File

@ -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