From b4836ee03ef24f3ba9b72d4f207986d47bc046ff Mon Sep 17 00:00:00 2001 From: Chao Xu Date: Mon, 10 Apr 2017 10:49:54 -0700 Subject: [PATCH] move helpers.go to helper Kubernetes-commit: 08aa712a6c3bf429017e14cdec3dcfb4d983af82 --- pkg/api/annotation_key_constants.go | 3 + pkg/api/{ => helper}/helpers.go | 311 ++++++++++++---------------- pkg/api/methods.go | 46 ++++ pkg/api/v1/helpers.go | 5 +- pkg/api/zz_generated.deepcopy.go | 26 --- 5 files changed, 185 insertions(+), 206 deletions(-) rename pkg/api/{ => helper}/helpers.go (60%) create mode 100644 pkg/api/methods.go diff --git a/pkg/api/annotation_key_constants.go b/pkg/api/annotation_key_constants.go index 07732451..30331f98 100644 --- a/pkg/api/annotation_key_constants.go +++ b/pkg/api/annotation_key_constants.go @@ -64,4 +64,7 @@ const ( // in the Annotations of a Pod. // TODO: remove when alpha support for affinity is removed AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity" + + // annotation key prefix used to identify non-convertible json paths. + NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io" ) diff --git a/pkg/api/helpers.go b/pkg/api/helper/helpers.go similarity index 60% rename from pkg/api/helpers.go rename to pkg/api/helper/helpers.go index f7e7afbd..073890b7 100644 --- a/pkg/api/helpers.go +++ b/pkg/api/helper/helpers.go @@ -14,18 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package api +package helper import ( "crypto/md5" "encoding/json" "fmt" - "reflect" "strings" "time" - "github.com/davecgh/go-spew/spew" - "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" @@ -34,25 +31,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/util/sets" -) - -// Conversion error conveniently packages up errors in conversions. -type ConversionError struct { - In, Out interface{} - Message string -} - -// Return a helpful string about the error -func (c *ConversionError) Error() string { - return spew.Sprintf( - "Conversion error: %s. (in: %v(%+v) out: %v)", - c.Message, reflect.TypeOf(c.In), c.In, reflect.TypeOf(c.Out), - ) -} - -const ( - // annotation key prefix used to identify non-convertible json paths. - NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io" + "k8s.io/client-go/pkg/api" ) // NonConvertibleFields iterates over the provided map and filters out all but @@ -60,7 +39,7 @@ const ( func NonConvertibleFields(annotations map[string]string) map[string]string { nonConvertibleKeys := map[string]string{} for key, value := range annotations { - if strings.HasPrefix(key, NonConvertibleAnnotationPrefix) { + if strings.HasPrefix(key, api.NonConvertibleAnnotationPrefix) { nonConvertibleKeys[key] = value } } @@ -89,10 +68,10 @@ var Semantic = conversion.EqualitiesOrDie( ) var standardResourceQuotaScopes = sets.NewString( - string(ResourceQuotaScopeTerminating), - string(ResourceQuotaScopeNotTerminating), - string(ResourceQuotaScopeBestEffort), - string(ResourceQuotaScopeNotBestEffort), + string(api.ResourceQuotaScopeTerminating), + string(api.ResourceQuotaScopeNotTerminating), + string(api.ResourceQuotaScopeBestEffort), + string(api.ResourceQuotaScopeNotBestEffort), ) // IsStandardResourceQuotaScope returns true if the scope is a standard value @@ -101,24 +80,24 @@ func IsStandardResourceQuotaScope(str string) bool { } var podObjectCountQuotaResources = sets.NewString( - string(ResourcePods), + string(api.ResourcePods), ) var podComputeQuotaResources = sets.NewString( - string(ResourceCPU), - string(ResourceMemory), - string(ResourceLimitsCPU), - string(ResourceLimitsMemory), - string(ResourceRequestsCPU), - string(ResourceRequestsMemory), + string(api.ResourceCPU), + string(api.ResourceMemory), + string(api.ResourceLimitsCPU), + string(api.ResourceLimitsMemory), + string(api.ResourceRequestsCPU), + string(api.ResourceRequestsMemory), ) // IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope -func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource string) bool { +func IsResourceQuotaScopeValidForResource(scope api.ResourceQuotaScope, resource string) bool { switch scope { - case ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeNotBestEffort: + case api.ResourceQuotaScopeTerminating, api.ResourceQuotaScopeNotTerminating, api.ResourceQuotaScopeNotBestEffort: return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource) - case ResourceQuotaScopeBestEffort: + case api.ResourceQuotaScopeBestEffort: return podObjectCountQuotaResources.Has(resource) default: return true @@ -126,8 +105,8 @@ func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource str } var standardContainerResources = sets.NewString( - string(ResourceCPU), - string(ResourceMemory), + string(api.ResourceCPU), + string(api.ResourceMemory), ) // IsStandardContainerResourceName returns true if the container can make a resource request @@ -138,24 +117,24 @@ func IsStandardContainerResourceName(str string) bool { // IsOpaqueIntResourceName returns true if the resource name has the opaque // integer resource prefix. -func IsOpaqueIntResourceName(name ResourceName) bool { - return strings.HasPrefix(string(name), ResourceOpaqueIntPrefix) +func IsOpaqueIntResourceName(name api.ResourceName) bool { + return strings.HasPrefix(string(name), api.ResourceOpaqueIntPrefix) } // OpaqueIntResourceName returns a ResourceName with the canonical opaque // integer prefix prepended. If the argument already has the prefix, it is // returned unmodified. -func OpaqueIntResourceName(name string) ResourceName { - if IsOpaqueIntResourceName(ResourceName(name)) { - return ResourceName(name) +func OpaqueIntResourceName(name string) api.ResourceName { + if IsOpaqueIntResourceName(api.ResourceName(name)) { + return api.ResourceName(name) } - return ResourceName(fmt.Sprintf("%s%s", ResourceOpaqueIntPrefix, name)) + return api.ResourceName(fmt.Sprintf("%s%s", api.ResourceOpaqueIntPrefix, name)) } var standardLimitRangeTypes = sets.NewString( - string(LimitTypePod), - string(LimitTypeContainer), - string(LimitTypePersistentVolumeClaim), + string(api.LimitTypePod), + string(api.LimitTypeContainer), + string(api.LimitTypePersistentVolumeClaim), ) // IsStandardLimitRangeType returns true if the type is Pod or Container @@ -164,22 +143,22 @@ func IsStandardLimitRangeType(str string) bool { } var standardQuotaResources = sets.NewString( - string(ResourceCPU), - string(ResourceMemory), - string(ResourceRequestsCPU), - string(ResourceRequestsMemory), - string(ResourceRequestsStorage), - string(ResourceLimitsCPU), - string(ResourceLimitsMemory), - string(ResourcePods), - string(ResourceQuotas), - string(ResourceServices), - string(ResourceReplicationControllers), - string(ResourceSecrets), - string(ResourcePersistentVolumeClaims), - string(ResourceConfigMaps), - string(ResourceServicesNodePorts), - string(ResourceServicesLoadBalancers), + string(api.ResourceCPU), + string(api.ResourceMemory), + string(api.ResourceRequestsCPU), + string(api.ResourceRequestsMemory), + string(api.ResourceRequestsStorage), + string(api.ResourceLimitsCPU), + string(api.ResourceLimitsMemory), + string(api.ResourcePods), + string(api.ResourceQuotas), + string(api.ResourceServices), + string(api.ResourceReplicationControllers), + string(api.ResourceSecrets), + string(api.ResourcePersistentVolumeClaims), + string(api.ResourceConfigMaps), + string(api.ResourceServicesNodePorts), + string(api.ResourceServicesLoadBalancers), ) // IsStandardQuotaResourceName returns true if the resource is known to @@ -189,21 +168,21 @@ func IsStandardQuotaResourceName(str string) bool { } var standardResources = sets.NewString( - string(ResourceCPU), - string(ResourceMemory), - string(ResourceRequestsCPU), - string(ResourceRequestsMemory), - string(ResourceLimitsCPU), - string(ResourceLimitsMemory), - string(ResourcePods), - string(ResourceQuotas), - string(ResourceServices), - string(ResourceReplicationControllers), - string(ResourceSecrets), - string(ResourceConfigMaps), - string(ResourcePersistentVolumeClaims), - string(ResourceStorage), - string(ResourceRequestsStorage), + string(api.ResourceCPU), + string(api.ResourceMemory), + string(api.ResourceRequestsCPU), + string(api.ResourceRequestsMemory), + string(api.ResourceLimitsCPU), + string(api.ResourceLimitsMemory), + string(api.ResourcePods), + string(api.ResourceQuotas), + string(api.ResourceServices), + string(api.ResourceReplicationControllers), + string(api.ResourceSecrets), + string(api.ResourceConfigMaps), + string(api.ResourcePersistentVolumeClaims), + string(api.ResourceStorage), + string(api.ResourceRequestsStorage), ) // IsStandardResourceName returns true if the resource is known to the system @@ -212,50 +191,50 @@ func IsStandardResourceName(str string) bool { } var integerResources = sets.NewString( - string(ResourcePods), - string(ResourceQuotas), - string(ResourceServices), - string(ResourceReplicationControllers), - string(ResourceSecrets), - string(ResourceConfigMaps), - string(ResourcePersistentVolumeClaims), - string(ResourceServicesNodePorts), - string(ResourceServicesLoadBalancers), + string(api.ResourcePods), + string(api.ResourceQuotas), + string(api.ResourceServices), + string(api.ResourceReplicationControllers), + string(api.ResourceSecrets), + string(api.ResourceConfigMaps), + string(api.ResourcePersistentVolumeClaims), + string(api.ResourceServicesNodePorts), + string(api.ResourceServicesLoadBalancers), ) // IsIntegerResourceName returns true if the resource is measured in integer values func IsIntegerResourceName(str string) bool { - return integerResources.Has(str) || IsOpaqueIntResourceName(ResourceName(str)) + return integerResources.Has(str) || IsOpaqueIntResourceName(api.ResourceName(str)) } // this function aims to check if the service's ClusterIP is set or not // the objective is not to perform validation here -func IsServiceIPSet(service *Service) bool { - return service.Spec.ClusterIP != ClusterIPNone && service.Spec.ClusterIP != "" +func IsServiceIPSet(service *api.Service) bool { + return service.Spec.ClusterIP != api.ClusterIPNone && service.Spec.ClusterIP != "" } // this function aims to check if the service's cluster IP is requested or not -func IsServiceIPRequested(service *Service) bool { +func IsServiceIPRequested(service *api.Service) bool { // ExternalName services are CNAME aliases to external ones. Ignore the IP. - if service.Spec.Type == ServiceTypeExternalName { + if service.Spec.Type == api.ServiceTypeExternalName { return false } return service.Spec.ClusterIP == "" } var standardFinalizers = sets.NewString( - string(FinalizerKubernetes), + string(api.FinalizerKubernetes), metav1.FinalizerOrphanDependents, ) // HasAnnotation returns a bool if passed in annotation exists -func HasAnnotation(obj ObjectMeta, ann string) bool { +func HasAnnotation(obj api.ObjectMeta, ann string) bool { _, found := obj.Annotations[ann] return found } // SetMetaDataAnnotation sets the annotation and value -func SetMetaDataAnnotation(obj *ObjectMeta, ann string, value string) { +func SetMetaDataAnnotation(obj *api.ObjectMeta, ann string, value string) { if obj.Annotations == nil { obj.Annotations = make(map[string]string) } @@ -268,7 +247,7 @@ func IsStandardFinalizerName(str string) bool { // AddToNodeAddresses appends the NodeAddresses to the passed-by-pointer slice, // only if they do not already exist -func AddToNodeAddresses(addresses *[]NodeAddress, addAddresses ...NodeAddress) { +func AddToNodeAddresses(addresses *[]api.NodeAddress, addAddresses ...api.NodeAddress) { for _, add := range addAddresses { exists := false for _, existing := range *addresses { @@ -292,11 +271,11 @@ func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) { } // TODO: make method on LoadBalancerStatus? -func LoadBalancerStatusEqual(l, r *LoadBalancerStatus) bool { +func LoadBalancerStatusEqual(l, r *api.LoadBalancerStatus) bool { return ingressSliceEqual(l.Ingress, r.Ingress) } -func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool { +func ingressSliceEqual(lhs, rhs []api.LoadBalancerIngress) bool { if len(lhs) != len(rhs) { return false } @@ -308,7 +287,7 @@ func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool { return true } -func ingressEqual(lhs, rhs *LoadBalancerIngress) bool { +func ingressEqual(lhs, rhs *api.LoadBalancerIngress) bool { if lhs.IP != rhs.IP { return false } @@ -319,9 +298,9 @@ func ingressEqual(lhs, rhs *LoadBalancerIngress) bool { } // TODO: make method on LoadBalancerStatus? -func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus { - c := &LoadBalancerStatus{} - c.Ingress = make([]LoadBalancerIngress, len(lb.Ingress)) +func LoadBalancerStatusDeepCopy(lb *api.LoadBalancerStatus) *api.LoadBalancerStatus { + c := &api.LoadBalancerStatus{} + c.Ingress = make([]api.LoadBalancerIngress, len(lb.Ingress)) for i := range lb.Ingress { c.Ingress[i] = lb.Ingress[i] } @@ -330,42 +309,42 @@ func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus { // GetAccessModesAsString returns a string representation of an array of access modes. // modes, when present, are always in the same order: RWO,ROX,RWX. -func GetAccessModesAsString(modes []PersistentVolumeAccessMode) string { +func GetAccessModesAsString(modes []api.PersistentVolumeAccessMode) string { modes = removeDuplicateAccessModes(modes) modesStr := []string{} - if containsAccessMode(modes, ReadWriteOnce) { + if containsAccessMode(modes, api.ReadWriteOnce) { modesStr = append(modesStr, "RWO") } - if containsAccessMode(modes, ReadOnlyMany) { + if containsAccessMode(modes, api.ReadOnlyMany) { modesStr = append(modesStr, "ROX") } - if containsAccessMode(modes, ReadWriteMany) { + if containsAccessMode(modes, api.ReadWriteMany) { modesStr = append(modesStr, "RWX") } return strings.Join(modesStr, ",") } // GetAccessModesAsString returns an array of AccessModes from a string created by GetAccessModesAsString -func GetAccessModesFromString(modes string) []PersistentVolumeAccessMode { +func GetAccessModesFromString(modes string) []api.PersistentVolumeAccessMode { strmodes := strings.Split(modes, ",") - accessModes := []PersistentVolumeAccessMode{} + accessModes := []api.PersistentVolumeAccessMode{} for _, s := range strmodes { s = strings.Trim(s, " ") switch { case s == "RWO": - accessModes = append(accessModes, ReadWriteOnce) + accessModes = append(accessModes, api.ReadWriteOnce) case s == "ROX": - accessModes = append(accessModes, ReadOnlyMany) + accessModes = append(accessModes, api.ReadOnlyMany) case s == "RWX": - accessModes = append(accessModes, ReadWriteMany) + accessModes = append(accessModes, api.ReadWriteMany) } } return accessModes } // removeDuplicateAccessModes returns an array of access modes without any duplicates -func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []PersistentVolumeAccessMode { - accessModes := []PersistentVolumeAccessMode{} +func removeDuplicateAccessModes(modes []api.PersistentVolumeAccessMode) []api.PersistentVolumeAccessMode { + accessModes := []api.PersistentVolumeAccessMode{} for _, m := range modes { if !containsAccessMode(accessModes, m) { accessModes = append(accessModes, m) @@ -374,7 +353,7 @@ func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []Persistent return accessModes } -func containsAccessMode(modes []PersistentVolumeAccessMode, mode PersistentVolumeAccessMode) bool { +func containsAccessMode(modes []api.PersistentVolumeAccessMode, mode api.PersistentVolumeAccessMode) bool { for _, m := range modes { if m == mode { return true @@ -397,7 +376,7 @@ func ParseRFC3339(s string, nowFn func() metav1.Time) (metav1.Time, error) { // NodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements // labels.Selector. -func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.Selector, error) { +func NodeSelectorRequirementsAsSelector(nsm []api.NodeSelectorRequirement) (labels.Selector, error) { if len(nsm) == 0 { return labels.Nothing(), nil } @@ -405,17 +384,17 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S for _, expr := range nsm { var op selection.Operator switch expr.Operator { - case NodeSelectorOpIn: + case api.NodeSelectorOpIn: op = selection.In - case NodeSelectorOpNotIn: + case api.NodeSelectorOpNotIn: op = selection.NotIn - case NodeSelectorOpExists: + case api.NodeSelectorOpExists: op = selection.Exists - case NodeSelectorOpDoesNotExist: + case api.NodeSelectorOpDoesNotExist: op = selection.DoesNotExist - case NodeSelectorOpGt: + case api.NodeSelectorOpGt: op = selection.GreaterThan - case NodeSelectorOpLt: + case api.NodeSelectorOpLt: op = selection.LessThan default: return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator) @@ -431,10 +410,10 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S // 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) +func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]api.Toleration, error) { + var tolerations []api.Toleration + if len(annotations) > 0 && annotations[api.TolerationsAnnotationKey] != "" { + err := json.Unmarshal([]byte(annotations[api.TolerationsAnnotationKey]), &tolerations) if err != nil { return tolerations, err } @@ -444,10 +423,10 @@ func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Tolerati // AddOrUpdateTolerationInPod tries to add a toleration to the pod's toleration list. // Returns true if something was updated, false otherwise. -func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool { +func AddOrUpdateTolerationInPod(pod *api.Pod, toleration *api.Toleration) bool { podTolerations := pod.Spec.Tolerations - var newTolerations []Toleration + var newTolerations []api.Toleration updated := false for i := range podTolerations { if toleration.MatchToleration(&podTolerations[i]) { @@ -470,18 +449,8 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool { return true } -// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by , -// if the two tolerations have same combination, regard as they match. -// TODO: uniqueness check for tolerations in api validations. -func (t *Toleration) MatchToleration(tolerationToMatch *Toleration) bool { - return t.Key == tolerationToMatch.Key && - t.Effect == tolerationToMatch.Effect && - t.Operator == tolerationToMatch.Operator && - t.Value == tolerationToMatch.Value -} - // TolerationToleratesTaint checks if the toleration tolerates the taint. -func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool { +func TolerationToleratesTaint(toleration *api.Toleration, taint *api.Taint) bool { if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect { return false } @@ -490,17 +459,17 @@ func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool { return false } // TODO: Use proper defaulting when Toleration becomes a field of PodSpec - if (len(toleration.Operator) == 0 || toleration.Operator == TolerationOpEqual) && toleration.Value == taint.Value { + if (len(toleration.Operator) == 0 || toleration.Operator == api.TolerationOpEqual) && toleration.Value == taint.Value { return true } - if toleration.Operator == TolerationOpExists { + if toleration.Operator == api.TolerationOpExists { return true } return false } // TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations. -func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool { +func TaintToleratedByTolerations(taint *api.Taint, tolerations []api.Toleration) bool { tolerated := false for i := range tolerations { if TolerationToleratesTaint(&tolerations[i], taint) { @@ -511,28 +480,14 @@ func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool { return tolerated } -// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect, -// if the two taints have same key:effect, regard as they match. -func (t *Taint) MatchTaint(taintToMatch Taint) bool { - return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect -} - -// taint.ToString() converts taint struct to string in format key=value:effect or key:effect. -func (t *Taint) ToString() string { - if len(t.Value) == 0 { - return fmt.Sprintf("%v:%v", t.Key, t.Effect) - } - return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect) -} - // 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) +func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]api.Taint, error) { + var taints []api.Taint + if len(annotations) > 0 && annotations[api.TaintsAnnotationKey] != "" { + err := json.Unmarshal([]byte(annotations[api.TaintsAnnotationKey]), &taints) if err != nil { - return []Taint{}, err + return []api.Taint{}, err } } return taints, nil @@ -541,12 +496,12 @@ func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error // SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls // and a slice of unsafe Sysctls. This is only a convenience wrapper around // SysctlsFromPodAnnotation. -func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error) { - safe, err := SysctlsFromPodAnnotation(a[SysctlsPodAnnotationKey]) +func SysctlsFromPodAnnotations(a map[string]string) ([]api.Sysctl, []api.Sysctl, error) { + safe, err := SysctlsFromPodAnnotation(a[api.SysctlsPodAnnotationKey]) if err != nil { return nil, nil, err } - unsafe, err := SysctlsFromPodAnnotation(a[UnsafeSysctlsPodAnnotationKey]) + unsafe, err := SysctlsFromPodAnnotation(a[api.UnsafeSysctlsPodAnnotationKey]) if err != nil { return nil, nil, err } @@ -555,13 +510,13 @@ func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error) } // SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls. -func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) { +func SysctlsFromPodAnnotation(annotation string) ([]api.Sysctl, error) { if len(annotation) == 0 { return nil, nil } kvs := strings.Split(annotation, ",") - sysctls := make([]Sysctl, len(kvs)) + sysctls := make([]api.Sysctl, len(kvs)) for i, kv := range kvs { cs := strings.Split(kv, "=") if len(cs) != 2 || len(cs[0]) == 0 { @@ -574,7 +529,7 @@ func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) { } // PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls. -func PodAnnotationsFromSysctls(sysctls []Sysctl) string { +func PodAnnotationsFromSysctls(sysctls []api.Sysctl) string { if len(sysctls) == 0 { return "" } @@ -589,10 +544,10 @@ func PodAnnotationsFromSysctls(sysctls []Sysctl) string { // GetAffinityFromPodAnnotations gets the json serialized affinity data from Pod.Annotations // and converts it to the Affinity type in api. // TODO: remove when alpha support for affinity is removed -func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) { - if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" { - var affinity Affinity - err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity) +func GetAffinityFromPodAnnotations(annotations map[string]string) (*api.Affinity, error) { + if len(annotations) > 0 && annotations[api.AffinityAnnotationKey] != "" { + var affinity api.Affinity + err := json.Unmarshal([]byte(annotations[api.AffinityAnnotationKey]), &affinity) if err != nil { return nil, err } @@ -602,9 +557,9 @@ func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, er } // GetPersistentVolumeClass returns StorageClassName. -func GetPersistentVolumeClass(volume *PersistentVolume) string { +func GetPersistentVolumeClass(volume *api.PersistentVolume) string { // Use beta annotation first - if class, found := volume.Annotations[BetaStorageClassAnnotation]; found { + if class, found := volume.Annotations[api.BetaStorageClassAnnotation]; found { return class } @@ -613,9 +568,9 @@ func GetPersistentVolumeClass(volume *PersistentVolume) string { // GetPersistentVolumeClaimClass returns StorageClassName. If no storage class was // requested, it returns "". -func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string { +func GetPersistentVolumeClaimClass(claim *api.PersistentVolumeClaim) string { // Use beta annotation first - if class, found := claim.Annotations[BetaStorageClassAnnotation]; found { + if class, found := claim.Annotations[api.BetaStorageClassAnnotation]; found { return class } @@ -627,9 +582,9 @@ func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string { } // PersistentVolumeClaimHasClass returns true if given claim has set StorageClassName field. -func PersistentVolumeClaimHasClass(claim *PersistentVolumeClaim) bool { +func PersistentVolumeClaimHasClass(claim *api.PersistentVolumeClaim) bool { // Use beta annotation first - if _, found := claim.Annotations[BetaStorageClassAnnotation]; found { + if _, found := claim.Annotations[api.BetaStorageClassAnnotation]; found { return true } diff --git a/pkg/api/methods.go b/pkg/api/methods.go new file mode 100644 index 00000000..b3bebfee --- /dev/null +++ b/pkg/api/methods.go @@ -0,0 +1,46 @@ +/* +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. +*/ + +//TODO: consider making these methods functions, because we don't want helper +//functions in the k8s.io/api repo. + +package api + +import "fmt" + +// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by , +// if the two tolerations have same combination, regard as they match. +// TODO: uniqueness check for tolerations in api validations. +func (t *Toleration) MatchToleration(tolerationToMatch *Toleration) bool { + return t.Key == tolerationToMatch.Key && + t.Effect == tolerationToMatch.Effect && + t.Operator == tolerationToMatch.Operator && + t.Value == tolerationToMatch.Value +} + +// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect, +// if the two taints have same key:effect, regard as they match. +func (t *Taint) MatchTaint(taintToMatch Taint) bool { + return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect +} + +// taint.ToString() converts taint struct to string in format key=value:effect or key:effect. +func (t *Taint) ToString() string { + if len(t.Value) == 0 { + return fmt.Sprintf("%v:%v", t.Key, t.Effect) + } + return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect) +} diff --git a/pkg/api/v1/helpers.go b/pkg/api/v1/helpers.go index 340ba63a..05764e4c 100644 --- a/pkg/api/v1/helpers.go +++ b/pkg/api/v1/helpers.go @@ -28,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/pkg/api" + "k8s.io/client-go/pkg/api/helper" ) // IsOpaqueIntResourceName returns true if the resource name has the opaque @@ -285,7 +286,7 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool { updated := false for i := range podTolerations { if toleration.MatchToleration(&podTolerations[i]) { - if api.Semantic.DeepEqual(toleration, podTolerations[i]) { + if helper.Semantic.DeepEqual(toleration, podTolerations[i]) { return false } newTolerations = append(newTolerations, *toleration) @@ -527,7 +528,7 @@ func AddOrUpdateTaint(node *Node, taint *Taint) (*Node, bool, error) { updated := false for i := range nodeTaints { if taint.MatchTaint(&nodeTaints[i]) { - if api.Semantic.DeepEqual(taint, nodeTaints[i]) { + if helper.Semantic.DeepEqual(taint, nodeTaints[i]) { return newNode, false, nil } newTaints = append(newTaints, *taint) diff --git a/pkg/api/zz_generated.deepcopy.go b/pkg/api/zz_generated.deepcopy.go index 3b9fdbba..b3430b97 100644 --- a/pkg/api/zz_generated.deepcopy.go +++ b/pkg/api/zz_generated.deepcopy.go @@ -65,7 +65,6 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStateTerminated, InType: reflect.TypeOf(&ContainerStateTerminated{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStateWaiting, InType: reflect.TypeOf(&ContainerStateWaiting{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStatus, InType: reflect.TypeOf(&ContainerStatus{})}, - conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConversionError, InType: reflect.TypeOf(&ConversionError{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DaemonEndpoint, InType: reflect.TypeOf(&DaemonEndpoint{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DeleteOptions, InType: reflect.TypeOf(&DeleteOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DownwardAPIProjection, InType: reflect.TypeOf(&DownwardAPIProjection{})}, @@ -707,31 +706,6 @@ func DeepCopy_api_ContainerStatus(in interface{}, out interface{}, c *conversion } } -func DeepCopy_api_ConversionError(in interface{}, out interface{}, c *conversion.Cloner) error { - { - in := in.(*ConversionError) - out := out.(*ConversionError) - *out = *in - // in.In is kind 'Interface' - if in.In != nil { - if newVal, err := c.DeepCopy(&in.In); err != nil { - return err - } else { - out.In = *newVal.(*interface{}) - } - } - // in.Out is kind 'Interface' - if in.Out != nil { - if newVal, err := c.DeepCopy(&in.Out); err != nil { - return err - } else { - out.Out = *newVal.(*interface{}) - } - } - return nil - } -} - func DeepCopy_api_DaemonEndpoint(in interface{}, out interface{}, c *conversion.Cloner) error { { in := in.(*DaemonEndpoint)