move helpers.go to helper

Kubernetes-commit: 08aa712a6c3bf429017e14cdec3dcfb4d983af82
This commit is contained in:
Chao Xu 2017-04-10 10:49:54 -07:00 committed by Kubernetes Publisher
parent 184fe30384
commit b4836ee03e
5 changed files with 185 additions and 206 deletions

View File

@ -64,4 +64,7 @@ const (
// in the Annotations of a Pod. // in the Annotations of a Pod.
// TODO: remove when alpha support for affinity is removed // TODO: remove when alpha support for affinity is removed
AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity" AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity"
// annotation key prefix used to identify non-convertible json paths.
NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io"
) )

View File

@ -14,18 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package api package helper
import ( import (
"crypto/md5" "crypto/md5"
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect"
"strings" "strings"
"time" "time"
"github.com/davecgh/go-spew/spew"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/conversion"
@ -34,25 +31,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/selection"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
) "k8s.io/client-go/pkg/api"
// 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"
) )
// NonConvertibleFields iterates over the provided map and filters out all but // 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 { func NonConvertibleFields(annotations map[string]string) map[string]string {
nonConvertibleKeys := map[string]string{} nonConvertibleKeys := map[string]string{}
for key, value := range annotations { for key, value := range annotations {
if strings.HasPrefix(key, NonConvertibleAnnotationPrefix) { if strings.HasPrefix(key, api.NonConvertibleAnnotationPrefix) {
nonConvertibleKeys[key] = value nonConvertibleKeys[key] = value
} }
} }
@ -89,10 +68,10 @@ var Semantic = conversion.EqualitiesOrDie(
) )
var standardResourceQuotaScopes = sets.NewString( var standardResourceQuotaScopes = sets.NewString(
string(ResourceQuotaScopeTerminating), string(api.ResourceQuotaScopeTerminating),
string(ResourceQuotaScopeNotTerminating), string(api.ResourceQuotaScopeNotTerminating),
string(ResourceQuotaScopeBestEffort), string(api.ResourceQuotaScopeBestEffort),
string(ResourceQuotaScopeNotBestEffort), string(api.ResourceQuotaScopeNotBestEffort),
) )
// IsStandardResourceQuotaScope returns true if the scope is a standard value // IsStandardResourceQuotaScope returns true if the scope is a standard value
@ -101,24 +80,24 @@ func IsStandardResourceQuotaScope(str string) bool {
} }
var podObjectCountQuotaResources = sets.NewString( var podObjectCountQuotaResources = sets.NewString(
string(ResourcePods), string(api.ResourcePods),
) )
var podComputeQuotaResources = sets.NewString( var podComputeQuotaResources = sets.NewString(
string(ResourceCPU), string(api.ResourceCPU),
string(ResourceMemory), string(api.ResourceMemory),
string(ResourceLimitsCPU), string(api.ResourceLimitsCPU),
string(ResourceLimitsMemory), string(api.ResourceLimitsMemory),
string(ResourceRequestsCPU), string(api.ResourceRequestsCPU),
string(ResourceRequestsMemory), string(api.ResourceRequestsMemory),
) )
// IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope // 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 { switch scope {
case ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeNotBestEffort: case api.ResourceQuotaScopeTerminating, api.ResourceQuotaScopeNotTerminating, api.ResourceQuotaScopeNotBestEffort:
return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource) return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource)
case ResourceQuotaScopeBestEffort: case api.ResourceQuotaScopeBestEffort:
return podObjectCountQuotaResources.Has(resource) return podObjectCountQuotaResources.Has(resource)
default: default:
return true return true
@ -126,8 +105,8 @@ func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource str
} }
var standardContainerResources = sets.NewString( var standardContainerResources = sets.NewString(
string(ResourceCPU), string(api.ResourceCPU),
string(ResourceMemory), string(api.ResourceMemory),
) )
// IsStandardContainerResourceName returns true if the container can make a resource request // 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 // IsOpaqueIntResourceName returns true if the resource name has the opaque
// integer resource prefix. // integer resource prefix.
func IsOpaqueIntResourceName(name ResourceName) bool { func IsOpaqueIntResourceName(name api.ResourceName) bool {
return strings.HasPrefix(string(name), ResourceOpaqueIntPrefix) return strings.HasPrefix(string(name), api.ResourceOpaqueIntPrefix)
} }
// OpaqueIntResourceName returns a ResourceName with the canonical opaque // OpaqueIntResourceName returns a ResourceName with the canonical opaque
// integer prefix prepended. If the argument already has the prefix, it is // integer prefix prepended. If the argument already has the prefix, it is
// returned unmodified. // returned unmodified.
func OpaqueIntResourceName(name string) ResourceName { func OpaqueIntResourceName(name string) api.ResourceName {
if IsOpaqueIntResourceName(ResourceName(name)) { if IsOpaqueIntResourceName(api.ResourceName(name)) {
return 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( var standardLimitRangeTypes = sets.NewString(
string(LimitTypePod), string(api.LimitTypePod),
string(LimitTypeContainer), string(api.LimitTypeContainer),
string(LimitTypePersistentVolumeClaim), string(api.LimitTypePersistentVolumeClaim),
) )
// IsStandardLimitRangeType returns true if the type is Pod or Container // IsStandardLimitRangeType returns true if the type is Pod or Container
@ -164,22 +143,22 @@ func IsStandardLimitRangeType(str string) bool {
} }
var standardQuotaResources = sets.NewString( var standardQuotaResources = sets.NewString(
string(ResourceCPU), string(api.ResourceCPU),
string(ResourceMemory), string(api.ResourceMemory),
string(ResourceRequestsCPU), string(api.ResourceRequestsCPU),
string(ResourceRequestsMemory), string(api.ResourceRequestsMemory),
string(ResourceRequestsStorage), string(api.ResourceRequestsStorage),
string(ResourceLimitsCPU), string(api.ResourceLimitsCPU),
string(ResourceLimitsMemory), string(api.ResourceLimitsMemory),
string(ResourcePods), string(api.ResourcePods),
string(ResourceQuotas), string(api.ResourceQuotas),
string(ResourceServices), string(api.ResourceServices),
string(ResourceReplicationControllers), string(api.ResourceReplicationControllers),
string(ResourceSecrets), string(api.ResourceSecrets),
string(ResourcePersistentVolumeClaims), string(api.ResourcePersistentVolumeClaims),
string(ResourceConfigMaps), string(api.ResourceConfigMaps),
string(ResourceServicesNodePorts), string(api.ResourceServicesNodePorts),
string(ResourceServicesLoadBalancers), string(api.ResourceServicesLoadBalancers),
) )
// IsStandardQuotaResourceName returns true if the resource is known to // IsStandardQuotaResourceName returns true if the resource is known to
@ -189,21 +168,21 @@ func IsStandardQuotaResourceName(str string) bool {
} }
var standardResources = sets.NewString( var standardResources = sets.NewString(
string(ResourceCPU), string(api.ResourceCPU),
string(ResourceMemory), string(api.ResourceMemory),
string(ResourceRequestsCPU), string(api.ResourceRequestsCPU),
string(ResourceRequestsMemory), string(api.ResourceRequestsMemory),
string(ResourceLimitsCPU), string(api.ResourceLimitsCPU),
string(ResourceLimitsMemory), string(api.ResourceLimitsMemory),
string(ResourcePods), string(api.ResourcePods),
string(ResourceQuotas), string(api.ResourceQuotas),
string(ResourceServices), string(api.ResourceServices),
string(ResourceReplicationControllers), string(api.ResourceReplicationControllers),
string(ResourceSecrets), string(api.ResourceSecrets),
string(ResourceConfigMaps), string(api.ResourceConfigMaps),
string(ResourcePersistentVolumeClaims), string(api.ResourcePersistentVolumeClaims),
string(ResourceStorage), string(api.ResourceStorage),
string(ResourceRequestsStorage), string(api.ResourceRequestsStorage),
) )
// IsStandardResourceName returns true if the resource is known to the system // IsStandardResourceName returns true if the resource is known to the system
@ -212,50 +191,50 @@ func IsStandardResourceName(str string) bool {
} }
var integerResources = sets.NewString( var integerResources = sets.NewString(
string(ResourcePods), string(api.ResourcePods),
string(ResourceQuotas), string(api.ResourceQuotas),
string(ResourceServices), string(api.ResourceServices),
string(ResourceReplicationControllers), string(api.ResourceReplicationControllers),
string(ResourceSecrets), string(api.ResourceSecrets),
string(ResourceConfigMaps), string(api.ResourceConfigMaps),
string(ResourcePersistentVolumeClaims), string(api.ResourcePersistentVolumeClaims),
string(ResourceServicesNodePorts), string(api.ResourceServicesNodePorts),
string(ResourceServicesLoadBalancers), string(api.ResourceServicesLoadBalancers),
) )
// IsIntegerResourceName returns true if the resource is measured in integer values // IsIntegerResourceName returns true if the resource is measured in integer values
func IsIntegerResourceName(str string) bool { 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 // this function aims to check if the service's ClusterIP is set or not
// the objective is not to perform validation here // the objective is not to perform validation here
func IsServiceIPSet(service *Service) bool { func IsServiceIPSet(service *api.Service) bool {
return service.Spec.ClusterIP != ClusterIPNone && service.Spec.ClusterIP != "" return service.Spec.ClusterIP != api.ClusterIPNone && service.Spec.ClusterIP != ""
} }
// this function aims to check if the service's cluster IP is requested or not // 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. // 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 false
} }
return service.Spec.ClusterIP == "" return service.Spec.ClusterIP == ""
} }
var standardFinalizers = sets.NewString( var standardFinalizers = sets.NewString(
string(FinalizerKubernetes), string(api.FinalizerKubernetes),
metav1.FinalizerOrphanDependents, metav1.FinalizerOrphanDependents,
) )
// HasAnnotation returns a bool if passed in annotation exists // 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] _, found := obj.Annotations[ann]
return found return found
} }
// SetMetaDataAnnotation sets the annotation and value // 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 { if obj.Annotations == nil {
obj.Annotations = make(map[string]string) 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, // AddToNodeAddresses appends the NodeAddresses to the passed-by-pointer slice,
// only if they do not already exist // 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 { for _, add := range addAddresses {
exists := false exists := false
for _, existing := range *addresses { for _, existing := range *addresses {
@ -292,11 +271,11 @@ func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
} }
// TODO: make method on LoadBalancerStatus? // TODO: make method on LoadBalancerStatus?
func LoadBalancerStatusEqual(l, r *LoadBalancerStatus) bool { func LoadBalancerStatusEqual(l, r *api.LoadBalancerStatus) bool {
return ingressSliceEqual(l.Ingress, r.Ingress) return ingressSliceEqual(l.Ingress, r.Ingress)
} }
func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool { func ingressSliceEqual(lhs, rhs []api.LoadBalancerIngress) bool {
if len(lhs) != len(rhs) { if len(lhs) != len(rhs) {
return false return false
} }
@ -308,7 +287,7 @@ func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
return true return true
} }
func ingressEqual(lhs, rhs *LoadBalancerIngress) bool { func ingressEqual(lhs, rhs *api.LoadBalancerIngress) bool {
if lhs.IP != rhs.IP { if lhs.IP != rhs.IP {
return false return false
} }
@ -319,9 +298,9 @@ func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
} }
// TODO: make method on LoadBalancerStatus? // TODO: make method on LoadBalancerStatus?
func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus { func LoadBalancerStatusDeepCopy(lb *api.LoadBalancerStatus) *api.LoadBalancerStatus {
c := &LoadBalancerStatus{} c := &api.LoadBalancerStatus{}
c.Ingress = make([]LoadBalancerIngress, len(lb.Ingress)) c.Ingress = make([]api.LoadBalancerIngress, len(lb.Ingress))
for i := range lb.Ingress { for i := range lb.Ingress {
c.Ingress[i] = lb.Ingress[i] 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. // GetAccessModesAsString returns a string representation of an array of access modes.
// modes, when present, are always in the same order: RWO,ROX,RWX. // 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) modes = removeDuplicateAccessModes(modes)
modesStr := []string{} modesStr := []string{}
if containsAccessMode(modes, ReadWriteOnce) { if containsAccessMode(modes, api.ReadWriteOnce) {
modesStr = append(modesStr, "RWO") modesStr = append(modesStr, "RWO")
} }
if containsAccessMode(modes, ReadOnlyMany) { if containsAccessMode(modes, api.ReadOnlyMany) {
modesStr = append(modesStr, "ROX") modesStr = append(modesStr, "ROX")
} }
if containsAccessMode(modes, ReadWriteMany) { if containsAccessMode(modes, api.ReadWriteMany) {
modesStr = append(modesStr, "RWX") modesStr = append(modesStr, "RWX")
} }
return strings.Join(modesStr, ",") return strings.Join(modesStr, ",")
} }
// GetAccessModesAsString returns an array of AccessModes from a string created by GetAccessModesAsString // 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, ",") strmodes := strings.Split(modes, ",")
accessModes := []PersistentVolumeAccessMode{} accessModes := []api.PersistentVolumeAccessMode{}
for _, s := range strmodes { for _, s := range strmodes {
s = strings.Trim(s, " ") s = strings.Trim(s, " ")
switch { switch {
case s == "RWO": case s == "RWO":
accessModes = append(accessModes, ReadWriteOnce) accessModes = append(accessModes, api.ReadWriteOnce)
case s == "ROX": case s == "ROX":
accessModes = append(accessModes, ReadOnlyMany) accessModes = append(accessModes, api.ReadOnlyMany)
case s == "RWX": case s == "RWX":
accessModes = append(accessModes, ReadWriteMany) accessModes = append(accessModes, api.ReadWriteMany)
} }
} }
return accessModes return accessModes
} }
// removeDuplicateAccessModes returns an array of access modes without any duplicates // removeDuplicateAccessModes returns an array of access modes without any duplicates
func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []PersistentVolumeAccessMode { func removeDuplicateAccessModes(modes []api.PersistentVolumeAccessMode) []api.PersistentVolumeAccessMode {
accessModes := []PersistentVolumeAccessMode{} accessModes := []api.PersistentVolumeAccessMode{}
for _, m := range modes { for _, m := range modes {
if !containsAccessMode(accessModes, m) { if !containsAccessMode(accessModes, m) {
accessModes = append(accessModes, m) accessModes = append(accessModes, m)
@ -374,7 +353,7 @@ func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []Persistent
return accessModes return accessModes
} }
func containsAccessMode(modes []PersistentVolumeAccessMode, mode PersistentVolumeAccessMode) bool { func containsAccessMode(modes []api.PersistentVolumeAccessMode, mode api.PersistentVolumeAccessMode) bool {
for _, m := range modes { for _, m := range modes {
if m == mode { if m == mode {
return true 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 // NodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
// labels.Selector. // labels.Selector.
func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.Selector, error) { func NodeSelectorRequirementsAsSelector(nsm []api.NodeSelectorRequirement) (labels.Selector, error) {
if len(nsm) == 0 { if len(nsm) == 0 {
return labels.Nothing(), nil return labels.Nothing(), nil
} }
@ -405,17 +384,17 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S
for _, expr := range nsm { for _, expr := range nsm {
var op selection.Operator var op selection.Operator
switch expr.Operator { switch expr.Operator {
case NodeSelectorOpIn: case api.NodeSelectorOpIn:
op = selection.In op = selection.In
case NodeSelectorOpNotIn: case api.NodeSelectorOpNotIn:
op = selection.NotIn op = selection.NotIn
case NodeSelectorOpExists: case api.NodeSelectorOpExists:
op = selection.Exists op = selection.Exists
case NodeSelectorOpDoesNotExist: case api.NodeSelectorOpDoesNotExist:
op = selection.DoesNotExist op = selection.DoesNotExist
case NodeSelectorOpGt: case api.NodeSelectorOpGt:
op = selection.GreaterThan op = selection.GreaterThan
case NodeSelectorOpLt: case api.NodeSelectorOpLt:
op = selection.LessThan op = selection.LessThan
default: default:
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator) 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 // GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
// and converts it to the []Toleration type in api. // and converts it to the []Toleration type in api.
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) { func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]api.Toleration, error) {
var tolerations []Toleration var tolerations []api.Toleration
if len(annotations) > 0 && annotations[TolerationsAnnotationKey] != "" { if len(annotations) > 0 && annotations[api.TolerationsAnnotationKey] != "" {
err := json.Unmarshal([]byte(annotations[TolerationsAnnotationKey]), &tolerations) err := json.Unmarshal([]byte(annotations[api.TolerationsAnnotationKey]), &tolerations)
if err != nil { if err != nil {
return tolerations, err 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. // AddOrUpdateTolerationInPod tries to add a toleration to the pod's toleration list.
// Returns true if something was updated, false otherwise. // 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 podTolerations := pod.Spec.Tolerations
var newTolerations []Toleration var newTolerations []api.Toleration
updated := false updated := false
for i := range podTolerations { for i := range podTolerations {
if toleration.MatchToleration(&podTolerations[i]) { if toleration.MatchToleration(&podTolerations[i]) {
@ -470,18 +449,8 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
return true return true
} }
// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by <key,effect,operator,value>,
// if the two tolerations have same <key,effect,operator,value> 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. // 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 { if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
return false return false
} }
@ -490,17 +459,17 @@ func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
return false return false
} }
// TODO: Use proper defaulting when Toleration becomes a field of PodSpec // 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 return true
} }
if toleration.Operator == TolerationOpExists { if toleration.Operator == api.TolerationOpExists {
return true return true
} }
return false return false
} }
// TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations. // 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 tolerated := false
for i := range tolerations { for i := range tolerations {
if TolerationToleratesTaint(&tolerations[i], taint) { if TolerationToleratesTaint(&tolerations[i], taint) {
@ -511,28 +480,14 @@ func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool {
return tolerated 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 // GetTaintsFromNodeAnnotations gets the json serialized taints data from Pod.Annotations
// and converts it to the []Taint type in api. // and converts it to the []Taint type in api.
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error) { func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]api.Taint, error) {
var taints []Taint var taints []api.Taint
if len(annotations) > 0 && annotations[TaintsAnnotationKey] != "" { if len(annotations) > 0 && annotations[api.TaintsAnnotationKey] != "" {
err := json.Unmarshal([]byte(annotations[TaintsAnnotationKey]), &taints) err := json.Unmarshal([]byte(annotations[api.TaintsAnnotationKey]), &taints)
if err != nil { if err != nil {
return []Taint{}, err return []api.Taint{}, err
} }
} }
return taints, nil 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 // 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.
func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error) { func SysctlsFromPodAnnotations(a map[string]string) ([]api.Sysctl, []api.Sysctl, error) {
safe, err := SysctlsFromPodAnnotation(a[SysctlsPodAnnotationKey]) safe, err := SysctlsFromPodAnnotation(a[api.SysctlsPodAnnotationKey])
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
unsafe, err := SysctlsFromPodAnnotation(a[UnsafeSysctlsPodAnnotationKey]) unsafe, err := SysctlsFromPodAnnotation(a[api.UnsafeSysctlsPodAnnotationKey])
if err != nil { if err != nil {
return nil, nil, err 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. // 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 { if len(annotation) == 0 {
return nil, nil return nil, nil
} }
kvs := strings.Split(annotation, ",") kvs := strings.Split(annotation, ",")
sysctls := make([]Sysctl, len(kvs)) sysctls := make([]api.Sysctl, len(kvs))
for i, kv := range kvs { for i, kv := range kvs {
cs := strings.Split(kv, "=") cs := strings.Split(kv, "=")
if len(cs) != 2 || len(cs[0]) == 0 { 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. // 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 { if len(sysctls) == 0 {
return "" return ""
} }
@ -589,10 +544,10 @@ func PodAnnotationsFromSysctls(sysctls []Sysctl) string {
// GetAffinityFromPodAnnotations gets the json serialized affinity data from Pod.Annotations // GetAffinityFromPodAnnotations gets the json serialized affinity data from Pod.Annotations
// and converts it to the Affinity type in api. // and converts it to the Affinity type in api.
// TODO: remove when alpha support for affinity is removed // TODO: remove when alpha support for affinity is removed
func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) { func GetAffinityFromPodAnnotations(annotations map[string]string) (*api.Affinity, error) {
if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" { if len(annotations) > 0 && annotations[api.AffinityAnnotationKey] != "" {
var affinity Affinity var affinity api.Affinity
err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity) err := json.Unmarshal([]byte(annotations[api.AffinityAnnotationKey]), &affinity)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -602,9 +557,9 @@ func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, er
} }
// GetPersistentVolumeClass returns StorageClassName. // GetPersistentVolumeClass returns StorageClassName.
func GetPersistentVolumeClass(volume *PersistentVolume) string { func GetPersistentVolumeClass(volume *api.PersistentVolume) string {
// Use beta annotation first // Use beta annotation first
if class, found := volume.Annotations[BetaStorageClassAnnotation]; found { if class, found := volume.Annotations[api.BetaStorageClassAnnotation]; found {
return class return class
} }
@ -613,9 +568,9 @@ func GetPersistentVolumeClass(volume *PersistentVolume) string {
// GetPersistentVolumeClaimClass returns StorageClassName. If no storage class was // GetPersistentVolumeClaimClass returns StorageClassName. If no storage class was
// requested, it returns "". // requested, it returns "".
func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string { func GetPersistentVolumeClaimClass(claim *api.PersistentVolumeClaim) string {
// Use beta annotation first // Use beta annotation first
if class, found := claim.Annotations[BetaStorageClassAnnotation]; found { if class, found := claim.Annotations[api.BetaStorageClassAnnotation]; found {
return class return class
} }
@ -627,9 +582,9 @@ func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string {
} }
// PersistentVolumeClaimHasClass returns true if given claim has set StorageClassName field. // 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 // Use beta annotation first
if _, found := claim.Annotations[BetaStorageClassAnnotation]; found { if _, found := claim.Annotations[api.BetaStorageClassAnnotation]; found {
return true return true
} }

46
pkg/api/methods.go Normal file
View File

@ -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 <key,effect,operator,value>,
// if the two tolerations have same <key,effect,operator,value> 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)
}

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/pkg/api" "k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/helper"
) )
// IsOpaqueIntResourceName returns true if the resource name has the opaque // IsOpaqueIntResourceName returns true if the resource name has the opaque
@ -285,7 +286,7 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
updated := false updated := false
for i := range podTolerations { for i := range podTolerations {
if toleration.MatchToleration(&podTolerations[i]) { if toleration.MatchToleration(&podTolerations[i]) {
if api.Semantic.DeepEqual(toleration, podTolerations[i]) { if helper.Semantic.DeepEqual(toleration, podTolerations[i]) {
return false return false
} }
newTolerations = append(newTolerations, *toleration) newTolerations = append(newTolerations, *toleration)
@ -527,7 +528,7 @@ func AddOrUpdateTaint(node *Node, taint *Taint) (*Node, bool, error) {
updated := false updated := false
for i := range nodeTaints { for i := range nodeTaints {
if taint.MatchTaint(&nodeTaints[i]) { if taint.MatchTaint(&nodeTaints[i]) {
if api.Semantic.DeepEqual(taint, nodeTaints[i]) { if helper.Semantic.DeepEqual(taint, nodeTaints[i]) {
return newNode, false, nil return newNode, false, nil
} }
newTaints = append(newTaints, *taint) newTaints = append(newTaints, *taint)

View File

@ -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_ContainerStateTerminated, InType: reflect.TypeOf(&ContainerStateTerminated{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStateWaiting, InType: reflect.TypeOf(&ContainerStateWaiting{})}, 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_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_DaemonEndpoint, InType: reflect.TypeOf(&DaemonEndpoint{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DeleteOptions, InType: reflect.TypeOf(&DeleteOptions{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DeleteOptions, InType: reflect.TypeOf(&DeleteOptions{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DownwardAPIProjection, InType: reflect.TypeOf(&DownwardAPIProjection{})}, 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 { func DeepCopy_api_DaemonEndpoint(in interface{}, out interface{}, c *conversion.Cloner) error {
{ {
in := in.(*DaemonEndpoint) in := in.(*DaemonEndpoint)