func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.Selector, error) {
	if len(nsm) == 0 {
		return labels.Nothing(), nil
	}
	selector := labels.NewSelector()
	for _, expr := range nsm {
		var op labels.Operator
		switch expr.Operator {
		case NodeSelectorOpIn:
			op = labels.InOperator
		case NodeSelectorOpNotIn:
			op = labels.NotInOperator
		case NodeSelectorOpExists:
			op = labels.ExistsOperator
		case NodeSelectorOpDoesNotExist:
			op = labels.DoesNotExistOperator
		case NodeSelectorOpGt:
			op = labels.GreaterThanOperator
		case NodeSelectorOpLt:
			op = labels.LessThanOperator
		default:
			return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
		}
		r, err := labels.NewRequirement(expr.Key, op, sets.NewString(expr.Values...))
		if err != nil {
			return nil, err
		}
		selector = selector.Add(*r)
	}
	return selector, nil
}
NodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
labels.Selector.
package api
import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"reflect"
	"strings"
	"time"
	"k8s.io/kubernetes/pkg/api/resource"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/conversion"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/runtime"
	"k8s.io/kubernetes/pkg/types"
	"k8s.io/kubernetes/pkg/util/sets"
	"github.com/davecgh/go-spew/spew"
)
type ConversionError struct {
	In, Out interface{}
	Message string
}
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),
	)
}
var Semantic = conversion.EqualitiesOrDie(
	func(a, b resource.Quantity) bool {
		return a.Cmp(b) == 0
	},
	func(a, b unversioned.Time) bool {
		return a.UTC() == b.UTC()
	},
	func(a, b labels.Selector) bool {
		return a.String() == b.String()
	},
	func(a, b fields.Selector) bool {
		return a.String() == b.String()
	},
)
var standardResourceQuotaScopes = sets.NewString(
	string(ResourceQuotaScopeTerminating),
	string(ResourceQuotaScopeNotTerminating),
	string(ResourceQuotaScopeBestEffort),
	string(ResourceQuotaScopeNotBestEffort),
)
func IsStandardResourceQuotaScope(str string) bool {
	return standardResourceQuotaScopes.Has(str)
}
var podObjectCountQuotaResources = sets.NewString(
	string(ResourcePods),
)
var podComputeQuotaResources = sets.NewString(
	string(ResourceCPU),
	string(ResourceMemory),
	string(ResourceLimitsCPU),
	string(ResourceLimitsMemory),
	string(ResourceRequestsCPU),
	string(ResourceRequestsMemory),
)
func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource string) bool {
	switch scope {
	case ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeNotBestEffort:
		return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource)
	case ResourceQuotaScopeBestEffort:
		return podObjectCountQuotaResources.Has(resource)
	default:
		return true
	}
}
var standardContainerResources = sets.NewString(
	string(ResourceCPU),
	string(ResourceMemory),
)
func IsStandardContainerResourceName(str string) bool {
	return standardContainerResources.Has(str)
}
var standardLimitRangeTypes = sets.NewString(
	string(LimitTypePod),
	string(LimitTypeContainer),
)
func IsStandardLimitRangeType(str string) bool {
	return standardLimitRangeTypes.Has(str)
}
var standardQuotaResources = 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(ResourcePersistentVolumeClaims),
	string(ResourceConfigMaps),
	string(ResourceServicesNodePorts),
	string(ResourceServicesLoadBalancers),
)
func IsStandardQuotaResourceName(str string) bool {
	return standardQuotaResources.Has(str)
}
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),
)
func IsStandardResourceName(str string) bool {
	return standardResources.Has(str)
}
var integerResources = sets.NewString(
	string(ResourcePods),
	string(ResourceQuotas),
	string(ResourceServices),
	string(ResourceReplicationControllers),
	string(ResourceSecrets),
	string(ResourceConfigMaps),
	string(ResourcePersistentVolumeClaims),
	string(ResourceServicesNodePorts),
	string(ResourceServicesLoadBalancers),
)
func IsIntegerResourceName(str string) bool {
	return integerResources.Has(str)
}
func NewDeleteOptions(grace int64) *DeleteOptions {
	return &DeleteOptions{GracePeriodSeconds: &grace}
}
func NewPreconditionDeleteOptions(uid string) *DeleteOptions {
	u := types.UID(uid)
	p := Preconditions{UID: &u}
	return &DeleteOptions{Preconditions: &p}
}
func NewUIDPreconditions(uid string) *Preconditions {
	u := types.UID(uid)
	return &Preconditions{UID: &u}
}
func IsServiceIPSet(service *Service) bool {
	return service.Spec.ClusterIP != ClusterIPNone && service.Spec.ClusterIP != ""
}
func IsServiceIPRequested(service *Service) bool {
	return service.Spec.ClusterIP == ""
}
var standardFinalizers = sets.NewString(
	string(FinalizerKubernetes),
	FinalizerOrphan,
)
func IsStandardFinalizerName(str string) bool {
	return standardFinalizers.Has(str)
}
func SingleObject(meta ObjectMeta) ListOptions {
	return ListOptions{
		FieldSelector:   fields.OneTermEqualSelector("metadata.name", meta.Name),
		ResourceVersion: meta.ResourceVersion,
	}
}
func AddToNodeAddresses(addresses *[]NodeAddress, addAddresses ...NodeAddress) {
	for _, add := range addAddresses {
		exists := false
		for _, existing := range *addresses {
			if existing.Address == add.Address && existing.Type == add.Type {
				exists = true
				break
			}
		}
		if !exists {
			*addresses = append(*addresses, add)
		}
	}
}
func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
	data, err := runtime.Encode(codec, obj)
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%x", md5.Sum(data)), nil
}
func LoadBalancerStatusEqual(l, r *LoadBalancerStatus) bool {
	return ingressSliceEqual(l.Ingress, r.Ingress)
}
func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
	if len(lhs) != len(rhs) {
		return false
	}
	for i := range lhs {
		if !ingressEqual(&lhs[i], &rhs[i]) {
			return false
		}
	}
	return true
}
func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
	if lhs.IP != rhs.IP {
		return false
	}
	if lhs.Hostname != rhs.Hostname {
		return false
	}
	return true
}
func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus {
	c := &LoadBalancerStatus{}
	c.Ingress = make([]LoadBalancerIngress, len(lb.Ingress))
	for i := range lb.Ingress {
		c.Ingress[i] = lb.Ingress[i]
	}
	return c
}
func GetAccessModesAsString(modes []PersistentVolumeAccessMode) string {
	modes = removeDuplicateAccessModes(modes)
	modesStr := []string{}
	if containsAccessMode(modes, ReadWriteOnce) {
		modesStr = append(modesStr, "RWO")
	}
	if containsAccessMode(modes, ReadOnlyMany) {
		modesStr = append(modesStr, "ROX")
	}
	if containsAccessMode(modes, ReadWriteMany) {
		modesStr = append(modesStr, "RWX")
	}
	return strings.Join(modesStr, ",")
}
func GetAccessModesFromString(modes string) []PersistentVolumeAccessMode {
	strmodes := strings.Split(modes, ",")
	accessModes := []PersistentVolumeAccessMode{}
	for _, s := range strmodes {
		s = strings.Trim(s, " ")
		switch {
		case s == "RWO":
			accessModes = append(accessModes, ReadWriteOnce)
		case s == "ROX":
			accessModes = append(accessModes, ReadOnlyMany)
		case s == "RWX":
			accessModes = append(accessModes, ReadWriteMany)
		}
	}
	return accessModes
}
func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []PersistentVolumeAccessMode {
	accessModes := []PersistentVolumeAccessMode{}
	for _, m := range modes {
		if !containsAccessMode(accessModes, m) {
			accessModes = append(accessModes, m)
		}
	}
	return accessModes
}
func containsAccessMode(modes []PersistentVolumeAccessMode, mode PersistentVolumeAccessMode) bool {
	for _, m := range modes {
		if m == mode {
			return true
		}
	}
	return false
}
func ParseRFC3339(s string, nowFn func() unversioned.Time) (unversioned.Time, error) {
	if t, timeErr := time.Parse(time.RFC3339Nano, s); timeErr == nil {
		return unversioned.Time{Time: t}, nil
	}
	t, err := time.Parse(time.RFC3339, s)
	if err != nil {
		return unversioned.Time{}, err
	}
	return unversioned.Time{Time: t}, nil
}