Merge pull request #36673 from caesarxuchao/convert-to-versioned-API
Convert to use versioned api
This commit is contained in:
commit
1dfd64f437
@ -253,7 +253,7 @@ func Run(s *options.ServerRunOptions) error {
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to create clientset: %v", err)
|
||||
}
|
||||
sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute)
|
||||
sharedInformers := informers.NewSharedInformerFactory(nil, client, 10*time.Minute)
|
||||
|
||||
authorizationConfig := authorizer.AuthorizationConfig{
|
||||
PolicyFile: s.GenericServerRunOptions.AuthorizationPolicyFile,
|
||||
|
@ -21,11 +21,12 @@ go_library(
|
||||
"//cmd/kube-controller-manager/app/options:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apimachinery/registered:go_default_library",
|
||||
"//pkg/apis/batch:go_default_library",
|
||||
"//pkg/apis/componentconfig:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/core/v1:go_default_library",
|
||||
"//pkg/client/leaderelection:go_default_library",
|
||||
"//pkg/client/leaderelection/resourcelock:go_default_library",
|
||||
"//pkg/client/record:go_default_library",
|
||||
|
@ -34,10 +34,11 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/core/v1"
|
||||
"k8s.io/kubernetes/pkg/client/leaderelection"
|
||||
"k8s.io/kubernetes/pkg/client/leaderelection/resourcelock"
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
@ -159,8 +160,8 @@ func Run(s *options.CMServer) error {
|
||||
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
eventBroadcaster.StartLogging(glog.Infof)
|
||||
eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")})
|
||||
recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "controller-manager"})
|
||||
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.Core().Events("")})
|
||||
recorder := eventBroadcaster.NewRecorder(v1.EventSource{Component: "controller-manager"})
|
||||
|
||||
run := func(stop <-chan struct{}) {
|
||||
rootClientBuilder := controller.SimpleControllerClientBuilder{
|
||||
@ -194,7 +195,7 @@ func Run(s *options.CMServer) error {
|
||||
|
||||
// TODO: enable other lock types
|
||||
rl := resourcelock.EndpointsLock{
|
||||
EndpointsMeta: api.ObjectMeta{
|
||||
EndpointsMeta: v1.ObjectMeta{
|
||||
Namespace: "kube-system",
|
||||
Name: "kube-controller-manager",
|
||||
},
|
||||
@ -225,7 +226,7 @@ func StartControllers(s *options.CMServer, kubeconfig *restclient.Config, rootCl
|
||||
return rootClientBuilder.ClientOrDie(serviceAccountName)
|
||||
}
|
||||
discoveryClient := client("controller-discovery").Discovery()
|
||||
sharedInformers := informers.NewSharedInformerFactory(client("shared-informers"), ResyncPeriod(s)())
|
||||
sharedInformers := informers.NewSharedInformerFactory(client("shared-informers"), nil, ResyncPeriod(s)())
|
||||
|
||||
// always start the SA token controller first using a full-power client, since it needs to mint tokens for the rest
|
||||
if len(s.ServiceAccountKeyFile) > 0 {
|
||||
@ -392,7 +393,7 @@ func StartControllers(s *options.CMServer, kubeconfig *restclient.Config, rootCl
|
||||
return gvr, nil
|
||||
}
|
||||
}
|
||||
namespaceController := namespacecontroller.NewNamespaceController(namespaceKubeClient, namespaceClientPool, gvrFn, s.NamespaceSyncPeriod.Duration, api.FinalizerKubernetes)
|
||||
namespaceController := namespacecontroller.NewNamespaceController(namespaceKubeClient, namespaceClientPool, gvrFn, s.NamespaceSyncPeriod.Duration, v1.FinalizerKubernetes)
|
||||
go namespaceController.Run(int(s.ConcurrentNamespaceSyncs), wait.NeverStop)
|
||||
time.Sleep(wait.Jitter(s.ControllerStartInterval.Duration, ControllerStartJitter))
|
||||
|
||||
|
@ -17,7 +17,7 @@ go_library(
|
||||
deps = [
|
||||
"//cmd/kube-dns/app/options:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/dns:go_default_library",
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/cmd/kube-dns/app/options"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
kclientcmd "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
kdns "k8s.io/kubernetes/pkg/dns"
|
||||
|
@ -20,6 +20,7 @@ go_library(
|
||||
deps = [
|
||||
"//cmd/kube-proxy/app/options:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/client/record:go_default_library",
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/cmd/kube-proxy/app/options"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
@ -205,7 +206,7 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
|
||||
// Create event recorder
|
||||
hostname := nodeutil.GetHostname(config.HostnameOverride)
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: hostname})
|
||||
recorder := eventBroadcaster.NewRecorder(v1.EventSource{Component: "kube-proxy", Host: hostname})
|
||||
|
||||
var proxier proxy.ProxyProvider
|
||||
var endpointsHandler proxyconfig.EndpointsConfigHandler
|
||||
@ -468,7 +469,7 @@ func getNodeIP(client clientset.Interface, hostname string) net.IP {
|
||||
glog.Warningf("Failed to retrieve node info: %v", err)
|
||||
return nil
|
||||
}
|
||||
nodeIP, err = nodeutil.GetNodeHostIP(node)
|
||||
nodeIP, err = nodeutil.InternalGetNodeHostIP(node)
|
||||
if err != nil {
|
||||
glog.Warningf("Failed to retrieve node IP: %v", err)
|
||||
return nil
|
||||
|
@ -32,8 +32,8 @@ go_library(
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
|
@ -25,21 +25,23 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
ipallocator "k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
||||
privilegedTrue := true
|
||||
return api.PodSpec{
|
||||
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
|
||||
Containers: []api.Container{{
|
||||
return v1.PodSpec{
|
||||
HostNetwork: true,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
Containers: []v1.Container{{
|
||||
Name: kubeProxy,
|
||||
Image: images.GetCoreImage(images.KubeProxyImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
||||
Command: append(getProxyCommand(cfg), "--kubeconfig=/run/kubeconfig"),
|
||||
SecurityContext: &api.SecurityContext{Privileged: &privilegedTrue},
|
||||
VolumeMounts: []api.VolumeMount{
|
||||
SecurityContext: &v1.SecurityContext{Privileged: &privilegedTrue},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "dbus",
|
||||
MountPath: "/var/run/dbus",
|
||||
@ -62,33 +64,33 @@ func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
},
|
||||
},
|
||||
}},
|
||||
Volumes: []api.Volume{
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dbus",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: "/var/run/dbus"},
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{Path: "/var/run/dbus"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
||||
|
||||
dnsPodResources := api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("100m"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("170Mi"),
|
||||
dnsPodResources := v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("100m"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("170Mi"),
|
||||
}
|
||||
|
||||
healthzPodResources := api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10m"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("50Mi"),
|
||||
healthzPodResources := v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10m"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("50Mi"),
|
||||
}
|
||||
|
||||
kubeDNSPort := int32(10053)
|
||||
@ -101,13 +103,13 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
nslookup, kubeDNSPort,
|
||||
)
|
||||
|
||||
return api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
return v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
// DNS server
|
||||
{
|
||||
Name: "kube-dns",
|
||||
Image: images.GetAddonImage(images.KubeDNSImage),
|
||||
Resources: api.ResourceRequirements{
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: dnsPodResources,
|
||||
Requests: dnsPodResources,
|
||||
},
|
||||
@ -116,12 +118,12 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
fmt.Sprintf("--dns-port=%d", kubeDNSPort),
|
||||
// TODO __PILLAR__FEDERATIONS__DOMAIN__MAP__
|
||||
},
|
||||
LivenessProbe: &api.Probe{
|
||||
Handler: api.Handler{
|
||||
HTTPGet: &api.HTTPGetAction{
|
||||
LivenessProbe: &v1.Probe{
|
||||
Handler: v1.Handler{
|
||||
HTTPGet: &v1.HTTPGetAction{
|
||||
Path: "/healthz",
|
||||
Port: intstr.FromInt(8080),
|
||||
Scheme: api.URISchemeHTTP,
|
||||
Scheme: v1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 60,
|
||||
@ -131,27 +133,27 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
},
|
||||
// # we poll on pod startup for the Kubernetes master service and
|
||||
// # only setup the /readiness HTTP server once that's available.
|
||||
ReadinessProbe: &api.Probe{
|
||||
Handler: api.Handler{
|
||||
HTTPGet: &api.HTTPGetAction{
|
||||
ReadinessProbe: &v1.Probe{
|
||||
Handler: v1.Handler{
|
||||
HTTPGet: &v1.HTTPGetAction{
|
||||
Path: "/readiness",
|
||||
Port: intstr.FromInt(8081),
|
||||
Scheme: api.URISchemeHTTP,
|
||||
Scheme: v1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 30,
|
||||
TimeoutSeconds: 5,
|
||||
},
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: kubeDNSPort,
|
||||
Name: "dns-local",
|
||||
Protocol: api.ProtocolUDP,
|
||||
Protocol: v1.ProtocolUDP,
|
||||
},
|
||||
{
|
||||
ContainerPort: kubeDNSPort,
|
||||
Name: "dns-tcp-local",
|
||||
Protocol: api.ProtocolTCP,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -159,7 +161,7 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
{
|
||||
Name: "dnsmasq",
|
||||
Image: images.GetAddonImage(images.KubeDNSmasqImage),
|
||||
Resources: api.ResourceRequirements{
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: dnsPodResources,
|
||||
Requests: dnsPodResources,
|
||||
},
|
||||
@ -168,16 +170,16 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
"--no-resolv",
|
||||
fmt.Sprintf("--server=127.0.0.1#%d", kubeDNSPort),
|
||||
},
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: dnsmasqPort,
|
||||
Name: "dns",
|
||||
Protocol: api.ProtocolUDP,
|
||||
Protocol: v1.ProtocolUDP,
|
||||
},
|
||||
{
|
||||
ContainerPort: dnsmasqPort,
|
||||
Name: "dns-tcp",
|
||||
Protocol: api.ProtocolTCP,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -185,7 +187,7 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
{
|
||||
Name: "healthz",
|
||||
Image: images.GetAddonImage(images.KubeExechealthzImage),
|
||||
Resources: api.ResourceRequirements{
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: healthzPodResources,
|
||||
Requests: healthzPodResources,
|
||||
},
|
||||
@ -194,18 +196,18 @@ func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
"-port=8080",
|
||||
"-quiet",
|
||||
},
|
||||
Ports: []api.ContainerPort{{
|
||||
Ports: []v1.ContainerPort{{
|
||||
ContainerPort: 8080,
|
||||
Protocol: api.ProtocolTCP,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}},
|
||||
},
|
||||
},
|
||||
DNSPolicy: api.DNSDefault,
|
||||
DNSPolicy: v1.DNSDefault,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func createKubeDNSServiceSpec(cfg *kubeadmapi.MasterConfiguration) (*api.ServiceSpec, error) {
|
||||
func createKubeDNSServiceSpec(cfg *kubeadmapi.MasterConfiguration) (*v1.ServiceSpec, error) {
|
||||
_, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse %q: %v", cfg.Networking.ServiceSubnet, err)
|
||||
@ -215,11 +217,11 @@ func createKubeDNSServiceSpec(cfg *kubeadmapi.MasterConfiguration) (*api.Service
|
||||
return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR (%q) [%v]", cfg.Networking.ServiceSubnet, err)
|
||||
}
|
||||
|
||||
svc := &api.ServiceSpec{
|
||||
svc := &v1.ServiceSpec{
|
||||
Selector: map[string]string{"name": "kube-dns"},
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "dns", Port: 53, Protocol: api.ProtocolUDP},
|
||||
{Name: "dns-tcp", Port: 53, Protocol: api.ProtocolTCP},
|
||||
Ports: []v1.ServicePort{
|
||||
{Name: "dns", Port: 53, Protocol: v1.ProtocolUDP},
|
||||
{Name: "dns-tcp", Port: 53, Protocol: v1.ProtocolTCP},
|
||||
},
|
||||
ClusterIP: ip.String(),
|
||||
}
|
||||
|
@ -26,8 +26,9 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
||||
unversionedapi "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
@ -55,7 +56,7 @@ func CreateClientAndWaitForAPI(adminConfig *clientcmdapi.Config) (*clientset.Cli
|
||||
|
||||
start := time.Now()
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
cs, err := client.ComponentStatuses().List(api.ListOptions{})
|
||||
cs, err := client.ComponentStatuses().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
@ -66,7 +67,7 @@ func CreateClientAndWaitForAPI(adminConfig *clientcmdapi.Config) (*clientset.Cli
|
||||
}
|
||||
for _, item := range cs.Items {
|
||||
for _, condition := range item.Conditions {
|
||||
if condition.Type != api.ComponentHealthy {
|
||||
if condition.Type != v1.ComponentHealthy {
|
||||
fmt.Printf("<master/apiclient> control plane component %q is still unhealthy: %#v\n", item.ObjectMeta.Name, item.Conditions)
|
||||
return false, nil
|
||||
}
|
||||
@ -80,7 +81,7 @@ func CreateClientAndWaitForAPI(adminConfig *clientcmdapi.Config) (*clientset.Cli
|
||||
fmt.Println("<master/apiclient> waiting for at least one node to register and become ready")
|
||||
start = time.Now()
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
nodeList, err := client.Nodes().List(api.ListOptions{})
|
||||
nodeList, err := client.Nodes().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
fmt.Println("<master/apiclient> temporarily unable to list nodes (will retry)")
|
||||
return false, nil
|
||||
@ -89,7 +90,7 @@ func CreateClientAndWaitForAPI(adminConfig *clientcmdapi.Config) (*clientset.Cli
|
||||
return false, nil
|
||||
}
|
||||
n := &nodeList.Items[0]
|
||||
if !api.IsNodeReady(n) {
|
||||
if !v1.IsNodeReady(n) {
|
||||
fmt.Println("<master/apiclient> first node has registered, but is not ready yet")
|
||||
return false, nil
|
||||
}
|
||||
@ -110,24 +111,24 @@ func standardLabels(n string) map[string]string {
|
||||
}
|
||||
}
|
||||
|
||||
func NewDaemonSet(daemonName string, podSpec api.PodSpec) *extensions.DaemonSet {
|
||||
func NewDaemonSet(daemonName string, podSpec v1.PodSpec) *extensions.DaemonSet {
|
||||
l := standardLabels(daemonName)
|
||||
return &extensions.DaemonSet{
|
||||
ObjectMeta: api.ObjectMeta{Name: daemonName},
|
||||
ObjectMeta: v1.ObjectMeta{Name: daemonName},
|
||||
Spec: extensions.DaemonSetSpec{
|
||||
Selector: &unversionedapi.LabelSelector{MatchLabels: l},
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{Labels: l},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: v1.ObjectMeta{Labels: l},
|
||||
Spec: podSpec,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewService(serviceName string, spec api.ServiceSpec) *api.Service {
|
||||
func NewService(serviceName string, spec v1.ServiceSpec) *v1.Service {
|
||||
l := standardLabels(serviceName)
|
||||
return &api.Service{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
return &v1.Service{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: serviceName,
|
||||
Labels: l,
|
||||
},
|
||||
@ -135,15 +136,15 @@ func NewService(serviceName string, spec api.ServiceSpec) *api.Service {
|
||||
}
|
||||
}
|
||||
|
||||
func NewDeployment(deploymentName string, replicas int32, podSpec api.PodSpec) *extensions.Deployment {
|
||||
func NewDeployment(deploymentName string, replicas int32, podSpec v1.PodSpec) *extensions.Deployment {
|
||||
l := standardLabels(deploymentName)
|
||||
return &extensions.Deployment{
|
||||
ObjectMeta: api.ObjectMeta{Name: deploymentName},
|
||||
ObjectMeta: v1.ObjectMeta{Name: deploymentName},
|
||||
Spec: extensions.DeploymentSpec{
|
||||
Replicas: replicas,
|
||||
Replicas: &replicas,
|
||||
Selector: &unversionedapi.LabelSelector{MatchLabels: l},
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{Labels: l},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: v1.ObjectMeta{Labels: l},
|
||||
Spec: podSpec,
|
||||
},
|
||||
},
|
||||
@ -152,8 +153,8 @@ func NewDeployment(deploymentName string, replicas int32, podSpec api.PodSpec) *
|
||||
|
||||
// It's safe to do this for alpha, as we don't have HA and there is no way we can get
|
||||
// more then one node here (TODO(phase1+) use os.Hostname)
|
||||
func findMyself(client *clientset.Clientset) (*api.Node, error) {
|
||||
nodeList, err := client.Nodes().List(api.ListOptions{})
|
||||
func findMyself(client *clientset.Clientset) (*v1.Node, error) {
|
||||
nodeList, err := client.Nodes().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to list nodes [%v]", err)
|
||||
}
|
||||
@ -173,8 +174,8 @@ func attemptToUpdateMasterRoleLabelsAndTaints(client *clientset.Clientset, sched
|
||||
n.ObjectMeta.Labels[unversionedapi.NodeLabelKubeadmAlphaRole] = unversionedapi.NodeLabelRoleMaster
|
||||
|
||||
if !schedulable {
|
||||
taintsAnnotation, _ := json.Marshal([]api.Taint{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}})
|
||||
n.ObjectMeta.Annotations[api.TaintsAnnotationKey] = string(taintsAnnotation)
|
||||
taintsAnnotation, _ := json.Marshal([]v1.Taint{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}})
|
||||
n.ObjectMeta.Annotations[v1.TaintsAnnotationKey] = string(taintsAnnotation)
|
||||
}
|
||||
|
||||
if _, err := client.Nodes().Update(n); err != nil {
|
||||
@ -199,50 +200,51 @@ func UpdateMasterRoleLabelsAndTaints(client *clientset.Clientset, schedulable bo
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetMasterTaintTolerations(meta *api.ObjectMeta) {
|
||||
tolerationsAnnotation, _ := json.Marshal([]api.Toleration{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}})
|
||||
func SetMasterTaintTolerations(meta *v1.ObjectMeta) {
|
||||
tolerationsAnnotation, _ := json.Marshal([]v1.Toleration{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}})
|
||||
if meta.Annotations == nil {
|
||||
meta.Annotations = map[string]string{}
|
||||
}
|
||||
meta.Annotations[api.TolerationsAnnotationKey] = string(tolerationsAnnotation)
|
||||
meta.Annotations[v1.TolerationsAnnotationKey] = string(tolerationsAnnotation)
|
||||
}
|
||||
|
||||
// SetNodeAffinity is a basic helper to set meta.Annotations[api.AffinityAnnotationKey] for one or more api.NodeSelectorRequirement(s)
|
||||
func SetNodeAffinity(meta *api.ObjectMeta, expr ...api.NodeSelectorRequirement) {
|
||||
nodeAffinity := &api.NodeAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
|
||||
NodeSelectorTerms: []api.NodeSelectorTerm{{MatchExpressions: expr}},
|
||||
// SetNodeAffinity is a basic helper to set meta.Annotations[v1.AffinityAnnotationKey] for one or more v1.NodeSelectorRequirement(s)
|
||||
func SetNodeAffinity(meta *v1.ObjectMeta, expr ...v1.NodeSelectorRequirement) {
|
||||
nodeAffinity := &v1.NodeAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{{MatchExpressions: expr}},
|
||||
},
|
||||
}
|
||||
affinityAnnotation, _ := json.Marshal(api.Affinity{NodeAffinity: nodeAffinity})
|
||||
affinityAnnotation, _ := json.Marshal(v1.Affinity{NodeAffinity: nodeAffinity})
|
||||
if meta.Annotations == nil {
|
||||
meta.Annotations = map[string]string{}
|
||||
}
|
||||
meta.Annotations[api.AffinityAnnotationKey] = string(affinityAnnotation)
|
||||
meta.Annotations[v1.AffinityAnnotationKey] = string(affinityAnnotation)
|
||||
}
|
||||
|
||||
// MasterNodeAffinity returns api.NodeSelectorRequirement to be used with SetNodeAffinity to set affinity to master node
|
||||
func MasterNodeAffinity() api.NodeSelectorRequirement {
|
||||
return api.NodeSelectorRequirement{
|
||||
// MasterNodeAffinity returns v1.NodeSelectorRequirement to be used with SetNodeAffinity to set affinity to master node
|
||||
func MasterNodeAffinity() v1.NodeSelectorRequirement {
|
||||
return v1.NodeSelectorRequirement{
|
||||
Key: unversionedapi.NodeLabelKubeadmAlphaRole,
|
||||
Operator: api.NodeSelectorOpIn,
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{unversionedapi.NodeLabelRoleMaster},
|
||||
}
|
||||
}
|
||||
|
||||
// NativeArchitectureNodeAffinity returns api.NodeSelectorRequirement to be used with SetNodeAffinity to nodes with CPU architecture
|
||||
// NativeArchitectureNodeAffinity returns v1.NodeSelectorRequirement to be used with SetNodeAffinity to nodes with CPU architecture
|
||||
// the same as master node
|
||||
func NativeArchitectureNodeAffinity() api.NodeSelectorRequirement {
|
||||
return api.NodeSelectorRequirement{
|
||||
Key: "beta.kubernetes.io/arch", Operator: api.NodeSelectorOpIn, Values: []string{runtime.GOARCH},
|
||||
func NativeArchitectureNodeAffinity() v1.NodeSelectorRequirement {
|
||||
return v1.NodeSelectorRequirement{
|
||||
Key: "beta.kubernetes.io/arch", Operator: v1.NodeSelectorOpIn, Values: []string{runtime.GOARCH},
|
||||
}
|
||||
}
|
||||
|
||||
func createDummyDeployment(client *clientset.Clientset) {
|
||||
fmt.Println("<master/apiclient> attempting a test deployment")
|
||||
dummyDeployment := NewDeployment("dummy", 1, api.PodSpec{
|
||||
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
|
||||
Containers: []api.Container{{
|
||||
dummyDeployment := NewDeployment("dummy", 1, v1.PodSpec{
|
||||
HostNetwork: true,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
Containers: []v1.Container{{
|
||||
Name: "dummy",
|
||||
Image: images.GetAddonImage("pause"),
|
||||
}},
|
||||
@ -271,7 +273,7 @@ func createDummyDeployment(client *clientset.Clientset) {
|
||||
|
||||
fmt.Println("<master/apiclient> test deployment succeeded")
|
||||
|
||||
if err := client.Extensions().Deployments(api.NamespaceSystem).Delete("dummy", &api.DeleteOptions{}); err != nil {
|
||||
if err := client.Extensions().Deployments(api.NamespaceSystem).Delete("dummy", &v1.DeleteOptions{}); err != nil {
|
||||
fmt.Printf("<master/apiclient> failed to delete test deployment [%v] (will ignore)", err)
|
||||
}
|
||||
}
|
||||
|
@ -25,15 +25,16 @@ import (
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
type kubeDiscovery struct {
|
||||
Deployment *extensions.Deployment
|
||||
Secret *api.Secret
|
||||
Secret *v1.Secret
|
||||
}
|
||||
|
||||
const (
|
||||
@ -61,29 +62,30 @@ func encodeKubeDiscoverySecretData(cfg *kubeadmapi.MasterConfiguration, caCert *
|
||||
return data
|
||||
}
|
||||
|
||||
func newKubeDiscoveryPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
return api.PodSpec{
|
||||
func newKubeDiscoveryPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
||||
return v1.PodSpec{
|
||||
// We have to use host network namespace, as `HostPort`/`HostIP` are Docker's
|
||||
// buisness and CNI support isn't quite there yet (except for kubenet)
|
||||
// (see https://github.com/kubernetes/kubernetes/issues/31307)
|
||||
// TODO update this when #31307 is resolved
|
||||
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
|
||||
Containers: []api.Container{{
|
||||
HostNetwork: true,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
Containers: []v1.Container{{
|
||||
Name: kubeDiscoveryName,
|
||||
Image: kubeadmapi.GlobalEnvParams.DiscoveryImage,
|
||||
Command: []string{"/usr/local/bin/kube-discovery"},
|
||||
VolumeMounts: []api.VolumeMount{{
|
||||
VolumeMounts: []v1.VolumeMount{{
|
||||
Name: kubeDiscoverySecretName,
|
||||
MountPath: "/tmp/secret", // TODO use a shared constant
|
||||
ReadOnly: true,
|
||||
}},
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
// TODO when CNI issue (#31307) is resolved, we should consider adding
|
||||
// `HostIP: s.API.AdvertiseAddrs[0]`, if there is only one address`
|
||||
{Name: "http", ContainerPort: kubeadmapiext.DefaultDiscoveryBindPort, HostPort: cfg.Discovery.BindPort},
|
||||
},
|
||||
SecurityContext: &api.SecurityContext{
|
||||
SELinuxOptions: &api.SELinuxOptions{
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
SELinuxOptions: &v1.SELinuxOptions{
|
||||
// TODO: This implies our discovery container is not being restricted by
|
||||
// SELinux. This is not optimal and would be nice to adjust in future
|
||||
// so it can read /tmp/secret, but for now this avoids recommending
|
||||
@ -92,10 +94,10 @@ func newKubeDiscoveryPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
},
|
||||
},
|
||||
}},
|
||||
Volumes: []api.Volume{{
|
||||
Volumes: []v1.Volume{{
|
||||
Name: kubeDiscoverySecretName,
|
||||
VolumeSource: api.VolumeSource{
|
||||
Secret: &api.SecretVolumeSource{SecretName: kubeDiscoverySecretName},
|
||||
VolumeSource: v1.VolumeSource{
|
||||
Secret: &v1.SecretVolumeSource{SecretName: kubeDiscoverySecretName},
|
||||
}},
|
||||
},
|
||||
}
|
||||
@ -104,9 +106,9 @@ func newKubeDiscoveryPodSpec(cfg *kubeadmapi.MasterConfiguration) api.PodSpec {
|
||||
func newKubeDiscovery(cfg *kubeadmapi.MasterConfiguration, caCert *x509.Certificate) kubeDiscovery {
|
||||
kd := kubeDiscovery{
|
||||
Deployment: NewDeployment(kubeDiscoveryName, 1, newKubeDiscoveryPodSpec(cfg)),
|
||||
Secret: &api.Secret{
|
||||
ObjectMeta: api.ObjectMeta{Name: kubeDiscoverySecretName},
|
||||
Type: api.SecretTypeOpaque,
|
||||
Secret: &v1.Secret{
|
||||
ObjectMeta: v1.ObjectMeta{Name: kubeDiscoverySecretName},
|
||||
Type: v1.SecretTypeOpaque,
|
||||
Data: encodeKubeDiscoverySecretData(cfg, caCert),
|
||||
},
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ go_library(
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/apis/certificates:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
"//pkg/kubelet/util/csr:go_default_library",
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
certclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
certclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
@ -34,7 +34,7 @@ import (
|
||||
|
||||
// ConnectionDetails represents a master API endpoint connection
|
||||
type ConnectionDetails struct {
|
||||
CertClient *certclient.CertificatesClient
|
||||
CertClient *certclient.CertificatesV1alpha1Client
|
||||
Endpoint string
|
||||
CACert []byte
|
||||
NodeName types.NodeName
|
||||
@ -82,7 +82,7 @@ func EstablishMasterConnection(s *kubeadmapi.NodeConfiguration, clusterInfo *kub
|
||||
// connection established, stop all wait threads
|
||||
close(stopChan)
|
||||
result <- &ConnectionDetails{
|
||||
CertClient: clientSet.CertificatesClient,
|
||||
CertClient: clientSet.CertificatesV1alpha1Client,
|
||||
Endpoint: apiEndpoint,
|
||||
CACert: caCert,
|
||||
NodeName: nodeName,
|
||||
|
@ -23,6 +23,7 @@ go_library(
|
||||
deps = [
|
||||
"//cmd/kubelet/app/options:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/componentconfig:go_default_library",
|
||||
"//pkg/apis/componentconfig/v1alpha1:go_default_library",
|
||||
"//pkg/auth/authenticator:go_default_library",
|
||||
@ -31,11 +32,11 @@ go_library(
|
||||
"//pkg/auth/group:go_default_library",
|
||||
"//pkg/capabilities:go_default_library",
|
||||
"//pkg/client/chaosclient:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/authorization/v1beta1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/core/v1:go_default_library",
|
||||
"//pkg/client/record:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/client/unversioned/auth:go_default_library",
|
||||
|
@ -26,9 +26,9 @@ import (
|
||||
"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||
"k8s.io/kubernetes/pkg/auth/group"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion"
|
||||
authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1"
|
||||
authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/authorization/v1beta1"
|
||||
alwaysallowauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||
"k8s.io/kubernetes/pkg/kubelet/server"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
@ -40,7 +40,7 @@ import (
|
||||
webhooksar "k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook"
|
||||
)
|
||||
|
||||
func buildAuth(nodeName types.NodeName, client internalclientset.Interface, config componentconfig.KubeletConfiguration) (server.AuthInterface, error) {
|
||||
func buildAuth(nodeName types.NodeName, client clientset.Interface, config componentconfig.KubeletConfiguration) (server.AuthInterface, error) {
|
||||
// Get clients, if provided
|
||||
var (
|
||||
tokenClient authenticationclient.TokenReviewInterface
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
unversionedcertificates "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion"
|
||||
unversionedcertificates "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
|
@ -38,12 +38,13 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubelet/app/options"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/componentconfig"
|
||||
componentconfigv1alpha1 "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
"k8s.io/kubernetes/pkg/client/chaosclient"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/core/v1"
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
clientauth "k8s.io/kubernetes/pkg/client/unversioned/auth"
|
||||
@ -170,7 +171,7 @@ func getRemoteKubeletConfig(s *options.KubeletServer, kubeDeps *kubelet.KubeletD
|
||||
return "", err
|
||||
}
|
||||
|
||||
configmap, err := func() (*api.ConfigMap, error) {
|
||||
configmap, err := func() (*v1.ConfigMap, error) {
|
||||
var nodename types.NodeName
|
||||
hostname := nodeutil.GetHostname(s.HostnameOverride)
|
||||
|
||||
@ -186,14 +187,14 @@ func getRemoteKubeletConfig(s *options.KubeletServer, kubeDeps *kubelet.KubeletD
|
||||
return nil, err
|
||||
}
|
||||
// look for kubelet-<node-name> configmap from "kube-system"
|
||||
configmap, err := kubeClient.CoreClient.ConfigMaps("kube-system").Get(fmt.Sprintf("kubelet-%s", nodename))
|
||||
configmap, err := kubeClient.CoreV1Client.ConfigMaps("kube-system").Get(fmt.Sprintf("kubelet-%s", nodename))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return configmap, nil
|
||||
}
|
||||
// No cloud provider yet, so can't get the nodename via Cloud.Instances().CurrentNodeName(hostname), try just using the hostname
|
||||
configmap, err := kubeClient.CoreClient.ConfigMaps("kube-system").Get(fmt.Sprintf("kubelet-%s", hostname))
|
||||
configmap, err := kubeClient.CoreV1Client.ConfigMaps("kube-system").Get(fmt.Sprintf("kubelet-%s", hostname))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cloud provider was nil, and attempt to use hostname to find config resulted in: %v", err)
|
||||
}
|
||||
@ -660,11 +661,11 @@ func RunKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *kubelet
|
||||
}
|
||||
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
kubeDeps.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "kubelet", Host: string(nodeName)})
|
||||
kubeDeps.Recorder = eventBroadcaster.NewRecorder(v1.EventSource{Component: "kubelet", Host: string(nodeName)})
|
||||
eventBroadcaster.StartLogging(glog.V(3).Infof)
|
||||
if kubeDeps.EventClient != nil {
|
||||
glog.V(4).Infof("Sending events to api server.")
|
||||
eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeDeps.EventClient.Events("")})
|
||||
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeDeps.EventClient.Events("")})
|
||||
} else {
|
||||
glog.Warning("No api server defined - no events will be sent to API server.")
|
||||
}
|
||||
|
@ -15,8 +15,9 @@ go_binary(
|
||||
srcs = ["hollow-node.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/metrics/prometheus:go_default_library",
|
||||
"//pkg/client/record:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
|
@ -19,8 +19,9 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
@ -96,10 +97,14 @@ func main() {
|
||||
glog.Fatalf("Failed to create a ClientConfig: %v. Exiting.", err)
|
||||
}
|
||||
|
||||
clientset, err := internalclientset.NewForConfig(clientConfig)
|
||||
clientset, err := clientset.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
glog.Fatalf("Failed to create a ClientSet: %v. Exiting.", err)
|
||||
}
|
||||
internalClientset, err := internalclientset.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
glog.Fatalf("Failed to create an internal ClientSet: %v. Exiting.", err)
|
||||
}
|
||||
|
||||
if config.Morph == "kubelet" {
|
||||
cadvisorInterface := new(cadvisortest.Fake)
|
||||
@ -124,7 +129,7 @@ func main() {
|
||||
|
||||
if config.Morph == "proxy" {
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: config.NodeName})
|
||||
recorder := eventBroadcaster.NewRecorder(v1.EventSource{Component: "kube-proxy", Host: config.NodeName})
|
||||
|
||||
iptInterface := fakeiptables.NewFake()
|
||||
|
||||
@ -134,7 +139,7 @@ func main() {
|
||||
endpointsConfig := proxyconfig.NewEndpointsConfig()
|
||||
endpointsConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
|
||||
|
||||
hollowProxy := kubemark.NewHollowProxyOrDie(config.NodeName, clientset, endpointsConfig, serviceConfig, iptInterface, eventBroadcaster, recorder)
|
||||
hollowProxy := kubemark.NewHollowProxyOrDie(config.NodeName, internalClientset, endpointsConfig, serviceConfig, iptInterface, eventBroadcaster, recorder)
|
||||
hollowProxy.Run()
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ func Run(s *options.ServerRunOptions) error {
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to create clientset: %v", err)
|
||||
}
|
||||
sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute)
|
||||
sharedInformers := informers.NewSharedInformerFactory(nil, client, 10*time.Minute)
|
||||
|
||||
authorizationConfig := authorizer.AuthorizationConfig{
|
||||
PolicyFile: s.GenericServerRunOptions.AuthorizationPolicyFile,
|
||||
|
@ -24,8 +24,6 @@ import (
|
||||
federation_v1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
cluster_cache "k8s.io/kubernetes/federation/client/cache"
|
||||
federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_5"
|
||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
@ -66,13 +64,11 @@ func NewclusterController(federationClient federationclientset.Interface, cluste
|
||||
}
|
||||
cc.clusterStore.Store, cc.clusterController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return cc.federationClient.Federation().Clusters().List(versionedOptions)
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return cc.federationClient.Federation().Clusters().List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return cc.federationClient.Federation().Clusters().Watch(versionedOptions)
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return cc.federationClient.Federation().Clusters().Watch(options)
|
||||
},
|
||||
},
|
||||
&federation_v1beta1.Cluster{},
|
||||
|
@ -79,7 +79,7 @@ type ConfigMapController struct {
|
||||
func NewConfigMapController(client federationclientset.Interface) *ConfigMapController {
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client))
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-configmaps-controller"})
|
||||
recorder := broadcaster.NewRecorder(api_v1.EventSource{Component: "federated-configmaps-controller"})
|
||||
|
||||
configmapcontroller := &ConfigMapController{
|
||||
federatedApiClient: client,
|
||||
@ -98,13 +98,11 @@ func NewConfigMapController(client federationclientset.Interface) *ConfigMapCont
|
||||
// Start informer on federated API servers on configmaps that should be federated.
|
||||
configmapcontroller.configmapInformerStore, configmapcontroller.configmapInformerController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Core().ConfigMaps(api_v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return client.Core().ConfigMaps(api_v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Core().ConfigMaps(api_v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return client.Core().ConfigMaps(api_v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&api_v1.ConfigMap{},
|
||||
@ -117,13 +115,11 @@ func NewConfigMapController(client federationclientset.Interface) *ConfigMapCont
|
||||
func(cluster *federation_api.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().ConfigMaps(api_v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return targetClient.Core().ConfigMaps(api_v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().ConfigMaps(api_v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return targetClient.Core().ConfigMaps(api_v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&api_v1.ConfigMap{},
|
||||
|
@ -87,7 +87,7 @@ type DaemonSetController struct {
|
||||
func NewDaemonSetController(client federationclientset.Interface) *DaemonSetController {
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client))
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-daemonset-controller"})
|
||||
recorder := broadcaster.NewRecorder(api_v1.EventSource{Component: "federated-daemonset-controller"})
|
||||
|
||||
daemonsetcontroller := &DaemonSetController{
|
||||
federatedApiClient: client,
|
||||
@ -106,13 +106,11 @@ func NewDaemonSetController(client federationclientset.Interface) *DaemonSetCont
|
||||
// Start informer in federated API servers on daemonsets that should be federated.
|
||||
daemonsetcontroller.daemonsetInformerStore, daemonsetcontroller.daemonsetInformerController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Extensions().DaemonSets(api_v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return client.Extensions().DaemonSets(api_v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Extensions().DaemonSets(api_v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return client.Extensions().DaemonSets(api_v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensionsv1.DaemonSet{},
|
||||
@ -125,13 +123,11 @@ func NewDaemonSetController(client federationclientset.Interface) *DaemonSetCont
|
||||
func(cluster *federation_api.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Extensions().DaemonSets(api_v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return targetClient.Extensions().DaemonSets(api_v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Extensions().DaemonSets(api_v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return targetClient.Extensions().DaemonSets(api_v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensionsv1.DaemonSet{},
|
||||
|
@ -104,7 +104,7 @@ type DeploymentController struct {
|
||||
func NewDeploymentController(federationClient fedclientset.Interface) *DeploymentController {
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(federationClient))
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-deployment-controller"})
|
||||
recorder := broadcaster.NewRecorder(apiv1.EventSource{Component: "federated-deployment-controller"})
|
||||
|
||||
fdc := &DeploymentController{
|
||||
fedClient: federationClient,
|
||||
@ -123,13 +123,11 @@ func NewDeploymentController(federationClient fedclientset.Interface) *Deploymen
|
||||
deploymentFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Extensions().Deployments(apiv1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options apiv1.ListOptions) (runtime.Object, error) {
|
||||
return clientset.Extensions().Deployments(apiv1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Extensions().Deployments(apiv1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options apiv1.ListOptions) (watch.Interface, error) {
|
||||
return clientset.Extensions().Deployments(apiv1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensionsv1.Deployment{},
|
||||
@ -152,13 +150,11 @@ func NewDeploymentController(federationClient fedclientset.Interface) *Deploymen
|
||||
podFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options apiv1.ListOptions) (runtime.Object, error) {
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options apiv1.ListOptions) (watch.Interface, error) {
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&apiv1.Pod{},
|
||||
@ -174,13 +170,11 @@ func NewDeploymentController(federationClient fedclientset.Interface) *Deploymen
|
||||
|
||||
fdc.deploymentStore, fdc.deploymentController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return fdc.fedClient.Extensions().Deployments(apiv1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options apiv1.ListOptions) (runtime.Object, error) {
|
||||
return fdc.fedClient.Extensions().Deployments(apiv1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return fdc.fedClient.Extensions().Deployments(apiv1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options apiv1.ListOptions) (watch.Interface, error) {
|
||||
return fdc.fedClient.Extensions().Deployments(apiv1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensionsv1.Deployment{},
|
||||
|
@ -108,7 +108,7 @@ func NewIngressController(client federationclientset.Interface) *IngressControll
|
||||
glog.V(4).Infof("->NewIngressController V(4)")
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client))
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-ingress-controller"})
|
||||
recorder := broadcaster.NewRecorder(v1.EventSource{Component: "federated-ingress-controller"})
|
||||
ic := &IngressController{
|
||||
federatedApiClient: client,
|
||||
ingressReviewDelay: time.Second * 10,
|
||||
@ -129,13 +129,11 @@ func NewIngressController(client federationclientset.Interface) *IngressControll
|
||||
// Start informer in federated API servers on ingresses that should be federated.
|
||||
ic.ingressInformerStore, ic.ingressInformerController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Extensions().Ingresses(api.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return client.Extensions().Ingresses(api.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Extensions().Ingresses(api.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return client.Extensions().Ingresses(api.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensions_v1beta1.Ingress{},
|
||||
@ -152,13 +150,11 @@ func NewIngressController(client federationclientset.Interface) *IngressControll
|
||||
func(cluster *federation_api.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Extensions().Ingresses(api.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return targetClient.Extensions().Ingresses(api.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Extensions().Ingresses(api.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return targetClient.Extensions().Ingresses(api.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensions_v1beta1.Ingress{},
|
||||
@ -187,19 +183,17 @@ func NewIngressController(client federationclientset.Interface) *IngressControll
|
||||
glog.V(4).Infof("Returning new informer for cluster %q", cluster.Name)
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
ListFunc: func(options v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
if targetClient == nil {
|
||||
glog.Errorf("Internal error: targetClient is nil")
|
||||
}
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().ConfigMaps(uidConfigMapNamespace).List(versionedOptions) // we only want to list one by name - unfortunately Kubernetes don't have a selector for that.
|
||||
return targetClient.Core().ConfigMaps(uidConfigMapNamespace).List(options) // we only want to list one by name - unfortunately Kubernetes don't have a selector for that.
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if targetClient == nil {
|
||||
glog.Errorf("Internal error: targetClient is nil")
|
||||
}
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().ConfigMaps(uidConfigMapNamespace).Watch(versionedOptions) // as above
|
||||
return targetClient.Core().ConfigMaps(uidConfigMapNamespace).Watch(options) // as above
|
||||
},
|
||||
},
|
||||
&v1.ConfigMap{},
|
||||
|
@ -84,7 +84,7 @@ type NamespaceController struct {
|
||||
func NewNamespaceController(client federationclientset.Interface) *NamespaceController {
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client))
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-namespace-controller"})
|
||||
recorder := broadcaster.NewRecorder(api_v1.EventSource{Component: "federated-namespace-controller"})
|
||||
|
||||
nc := &NamespaceController{
|
||||
federatedApiClient: client,
|
||||
@ -103,13 +103,11 @@ func NewNamespaceController(client federationclientset.Interface) *NamespaceCont
|
||||
// Start informer in federated API servers on namespaces that should be federated.
|
||||
nc.namespaceInformerStore, nc.namespaceInformerController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Core().Namespaces().List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (runtime.Object, error) {
|
||||
return client.Core().Namespaces().List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Core().Namespaces().Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return client.Core().Namespaces().Watch(options)
|
||||
},
|
||||
},
|
||||
&api_v1.Namespace{},
|
||||
@ -122,13 +120,11 @@ func NewNamespaceController(client federationclientset.Interface) *NamespaceCont
|
||||
func(cluster *federation_api.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().Namespaces().List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (runtime.Object, error) {
|
||||
return targetClient.Core().Namespaces().List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().Namespaces().Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return targetClient.Core().Namespaces().Watch(options)
|
||||
},
|
||||
},
|
||||
&api_v1.Namespace{},
|
||||
|
@ -106,7 +106,7 @@ type ReplicaSetController struct {
|
||||
func NewReplicaSetController(federationClient fedclientset.Interface) *ReplicaSetController {
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(federationClient))
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-replicaset-controller"})
|
||||
recorder := broadcaster.NewRecorder(apiv1.EventSource{Component: "federated-replicaset-controller"})
|
||||
|
||||
frsc := &ReplicaSetController{
|
||||
fedClient: federationClient,
|
||||
@ -125,13 +125,11 @@ func NewReplicaSetController(federationClient fedclientset.Interface) *ReplicaSe
|
||||
replicaSetFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Extensions().ReplicaSets(apiv1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options apiv1.ListOptions) (runtime.Object, error) {
|
||||
return clientset.Extensions().ReplicaSets(apiv1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Extensions().ReplicaSets(apiv1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options apiv1.ListOptions) (watch.Interface, error) {
|
||||
return clientset.Extensions().ReplicaSets(apiv1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensionsv1.ReplicaSet{},
|
||||
@ -154,13 +152,11 @@ func NewReplicaSetController(federationClient fedclientset.Interface) *ReplicaSe
|
||||
podFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options apiv1.ListOptions) (runtime.Object, error) {
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options apiv1.ListOptions) (watch.Interface, error) {
|
||||
return clientset.Core().Pods(apiv1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&apiv1.Pod{},
|
||||
@ -176,13 +172,11 @@ func NewReplicaSetController(federationClient fedclientset.Interface) *ReplicaSe
|
||||
|
||||
frsc.replicaSetStore.Indexer, frsc.replicaSetController = cache.NewIndexerInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return frsc.fedClient.Extensions().ReplicaSets(apiv1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options apiv1.ListOptions) (runtime.Object, error) {
|
||||
return frsc.fedClient.Extensions().ReplicaSets(apiv1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := fedutil.VersionizeV1ListOptions(options)
|
||||
return frsc.fedClient.Extensions().ReplicaSets(apiv1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options apiv1.ListOptions) (watch.Interface, error) {
|
||||
return frsc.fedClient.Extensions().ReplicaSets(apiv1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&extensionsv1.ReplicaSet{},
|
||||
|
@ -85,7 +85,7 @@ type SecretController struct {
|
||||
func NewSecretController(client federationclientset.Interface) *SecretController {
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client))
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-secrets-controller"})
|
||||
recorder := broadcaster.NewRecorder(api_v1.EventSource{Component: "federated-secrets-controller"})
|
||||
|
||||
secretcontroller := &SecretController{
|
||||
federatedApiClient: client,
|
||||
@ -104,13 +104,11 @@ func NewSecretController(client federationclientset.Interface) *SecretController
|
||||
// Start informer in federated API servers on secrets that should be federated.
|
||||
secretcontroller.secretInformerStore, secretcontroller.secretInformerController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Core().Secrets(api_v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return client.Core().Secrets(api_v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return client.Core().Secrets(api_v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return client.Core().Secrets(api_v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&api_v1.Secret{},
|
||||
@ -123,13 +121,11 @@ func NewSecretController(client federationclientset.Interface) *SecretController
|
||||
func(cluster *federation_api.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().Secrets(api_v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return targetClient.Core().Secrets(api_v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return targetClient.Core().Secrets(api_v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return targetClient.Core().Secrets(api_v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&api_v1.Secret{},
|
||||
|
@ -28,7 +28,6 @@ go_library(
|
||||
"//federation/pkg/dnsprovider:go_default_library",
|
||||
"//federation/pkg/dnsprovider/rrstype:go_default_library",
|
||||
"//federation/pkg/federation-controller/util:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/cache:go_default_library",
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"sync"
|
||||
|
||||
v1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
cache "k8s.io/kubernetes/pkg/client/cache"
|
||||
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
@ -92,13 +91,11 @@ func (cc *clusterClientCache) startClusterLW(cluster *v1beta1.Cluster, clusterNa
|
||||
}
|
||||
cachedClusterClient.endpointStore.Store, cachedClusterClient.endpointController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Endpoints(v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return clientset.Core().Endpoints(v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Endpoints(v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return clientset.Core().Endpoints(v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&v1.Endpoints{},
|
||||
@ -118,13 +115,11 @@ func (cc *clusterClientCache) startClusterLW(cluster *v1beta1.Cluster, clusterNa
|
||||
|
||||
cachedClusterClient.serviceStore.Indexer, cachedClusterClient.serviceController = cache.NewIndexerInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Services(v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return clientset.Core().Services(v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Services(v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return clientset.Core().Services(v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&v1.Service{},
|
||||
|
@ -22,9 +22,10 @@ import (
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/federation/pkg/dnsprovider"
|
||||
"k8s.io/kubernetes/federation/pkg/dnsprovider/rrstype"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -21,12 +21,13 @@ import (
|
||||
"testing"
|
||||
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
"k8s.io/kubernetes/federation/pkg/dnsprovider/providers/google/clouddns" // Only for unit testing purposes.
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func TestServiceController_ensureDnsRecords(t *testing.T) {
|
||||
|
@ -28,8 +28,6 @@ import (
|
||||
federationcache "k8s.io/kubernetes/federation/client/cache"
|
||||
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_5"
|
||||
"k8s.io/kubernetes/federation/pkg/dnsprovider"
|
||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
cache "k8s.io/kubernetes/pkg/client/cache"
|
||||
@ -145,7 +143,7 @@ func New(federationClient fedclientset.Interface, dns dnsprovider.Interface,
|
||||
broadcaster := record.NewBroadcaster()
|
||||
// federationClient event is not supported yet
|
||||
// broadcaster.StartRecordingToSink(&unversioned_core.EventSinkImpl{Interface: kubeClient.Core().Events("")})
|
||||
recorder := broadcaster.NewRecorder(api.EventSource{Component: UserAgentName})
|
||||
recorder := broadcaster.NewRecorder(v1.EventSource{Component: UserAgentName})
|
||||
|
||||
s := &ServiceController{
|
||||
dns: dns,
|
||||
@ -166,13 +164,11 @@ func New(federationClient fedclientset.Interface, dns dnsprovider.Interface,
|
||||
}
|
||||
s.serviceStore.Indexer, s.serviceController = cache.NewIndexerInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return s.federationClient.Core().Services(v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return s.federationClient.Core().Services(v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return s.federationClient.Core().Services(v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return s.federationClient.Core().Services(v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&v1.Service{},
|
||||
@ -191,13 +187,11 @@ func New(federationClient fedclientset.Interface, dns dnsprovider.Interface,
|
||||
)
|
||||
s.clusterStore.Store, s.clusterController = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return s.federationClient.Federation().Clusters().List(versionedOptions)
|
||||
ListFunc: func(options v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return s.federationClient.Federation().Clusters().List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := util.VersionizeV1ListOptions(options)
|
||||
return s.federationClient.Federation().Clusters().Watch(versionedOptions)
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return s.federationClient.Federation().Clusters().Watch(options)
|
||||
},
|
||||
},
|
||||
&v1beta1.Cluster{},
|
||||
|
@ -60,7 +60,6 @@ go_test(
|
||||
deps = [
|
||||
"//federation/apis/federation/v1beta1:go_default_library",
|
||||
"//federation/client/clientset_generated/federation_release_1_5/fake:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/cache:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
|
@ -30,7 +30,6 @@ go_test(
|
||||
deps = [
|
||||
"//federation/client/clientset_generated/federation_release_1_5/fake:go_default_library",
|
||||
"//federation/pkg/federation-controller/util/test:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/testing/core:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
|
@ -37,36 +37,14 @@ func NewFederatedEventSink(clientset fedclientset.Interface) *FederatedEventSink
|
||||
}
|
||||
}
|
||||
|
||||
func (fes *FederatedEventSink) Create(event *api.Event) (*api.Event, error) {
|
||||
return fes.executeOperation(event, func(eventV1 *api_v1.Event) (*api_v1.Event, error) {
|
||||
return fes.clientset.Core().Events(event.Namespace).Create(eventV1)
|
||||
})
|
||||
func (fes *FederatedEventSink) Create(event *api_v1.Event) (*api_v1.Event, error) {
|
||||
return fes.clientset.Core().Events(event.Namespace).Create(event)
|
||||
}
|
||||
|
||||
func (fes *FederatedEventSink) Update(event *api.Event) (*api.Event, error) {
|
||||
return fes.executeOperation(event, func(eventV1 *api_v1.Event) (*api_v1.Event, error) {
|
||||
return fes.clientset.Core().Events(event.Namespace).Update(eventV1)
|
||||
})
|
||||
func (fes *FederatedEventSink) Update(event *api_v1.Event) (*api_v1.Event, error) {
|
||||
return fes.clientset.Core().Events(event.Namespace).Update(event)
|
||||
}
|
||||
|
||||
func (fes *FederatedEventSink) Patch(event *api.Event, data []byte) (*api.Event, error) {
|
||||
return fes.executeOperation(event, func(eventV1 *api_v1.Event) (*api_v1.Event, error) {
|
||||
return fes.clientset.Core().Events(event.Namespace).Patch(event.Name, api.StrategicMergePatchType, data)
|
||||
})
|
||||
}
|
||||
|
||||
func (fes *FederatedEventSink) executeOperation(event *api.Event, operation func(*api_v1.Event) (*api_v1.Event, error)) (*api.Event, error) {
|
||||
var versionedEvent api_v1.Event
|
||||
if err := api.Scheme.Convert(event, &versionedEvent, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
versionedEventPtr, err := operation(&versionedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var unversionedEvent api.Event
|
||||
if err := api.Scheme.Convert(versionedEventPtr, &unversionedEvent, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &unversionedEvent, nil
|
||||
func (fes *FederatedEventSink) Patch(event *api_v1.Event, data []byte) (*api_v1.Event, error) {
|
||||
return fes.clientset.Core().Events(event.Namespace).Patch(event.Name, api.StrategicMergePatchType, data)
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
fake_fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_5/fake"
|
||||
. "k8s.io/kubernetes/federation/pkg/federation-controller/util/test"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
api_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
@ -46,8 +45,8 @@ func TestEventSink(t *testing.T) {
|
||||
return true, obj, nil
|
||||
})
|
||||
|
||||
event := api.Event{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
event := api_v1.Event{
|
||||
ObjectMeta: api_v1.ObjectMeta{
|
||||
Name: "bzium",
|
||||
Namespace: "ns",
|
||||
},
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
|
||||
federation_api "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_5"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
api_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
@ -161,13 +160,11 @@ func NewFederatedInformer(
|
||||
|
||||
federatedInformer.clusterInformer.store, federatedInformer.clusterInformer.controller = cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) {
|
||||
versionedOptions := VersionizeV1ListOptions(options)
|
||||
return federationClient.Federation().Clusters().List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (pkg_runtime.Object, error) {
|
||||
return federationClient.Federation().Clusters().List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := VersionizeV1ListOptions(options)
|
||||
return federationClient.Federation().Clusters().Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return federationClient.Federation().Clusters().Watch(options)
|
||||
},
|
||||
},
|
||||
&federation_api.Cluster{},
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
federation_api "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||
fakefederationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_release_1_5/fake"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
api_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
@ -81,13 +80,11 @@ func TestFederatedInformer(t *testing.T) {
|
||||
targetInformerFactory := func(cluster *federation_api.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.ControllerInterface) {
|
||||
return cache.NewInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
versionedOptions := VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Services(api_v1.NamespaceAll).List(versionedOptions)
|
||||
ListFunc: func(options api_v1.ListOptions) (runtime.Object, error) {
|
||||
return clientset.Core().Services(api_v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
versionedOptions := VersionizeV1ListOptions(options)
|
||||
return clientset.Core().Services(api_v1.NamespaceAll).Watch(versionedOptions)
|
||||
WatchFunc: func(options api_v1.ListOptions) (watch.Interface, error) {
|
||||
return clientset.Core().Services(api_v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&api_v1.Service{},
|
||||
|
@ -64,6 +64,7 @@ pkg/api/meta
|
||||
pkg/api/resource
|
||||
pkg/api/service
|
||||
pkg/api/v1
|
||||
pkg/api/v1/service
|
||||
pkg/apimachinery
|
||||
pkg/apis/abac/v0
|
||||
pkg/apis/apps/install
|
||||
@ -88,6 +89,7 @@ pkg/apiserver/audit
|
||||
pkg/apiserver/openapi
|
||||
pkg/auth/authenticator
|
||||
pkg/auth/authorizer/union
|
||||
pkg/client/conditions
|
||||
pkg/client/listers/apps/internalversion
|
||||
pkg/client/listers/apps/v1alpha1
|
||||
pkg/client/listers/apps/v1beta1
|
||||
|
@ -2313,8 +2313,9 @@ __EOF__
|
||||
kubectl-with-retry rollout resume deployment nginx "${kube_flags[@]}"
|
||||
# The resumed deployment can now be rolled back
|
||||
kubectl rollout undo deployment nginx "${kube_flags[@]}"
|
||||
# Check that the new replica set (nginx-618515232) has all old revisions stored in an annotation
|
||||
kubectl get rs nginx-618515232 -o yaml | grep "deployment.kubernetes.io/revision-history: 1,3"
|
||||
# Check that the new replica set has all old revisions stored in an annotation
|
||||
newrs="$(kubectl describe deployment nginx | grep NewReplicaSet | awk '{print $2}')"
|
||||
kubectl get rs "${newrs}" -o yaml | grep "deployment.kubernetes.io/revision-history: 1,3"
|
||||
# Check that trying to watch the status of a superseded revision returns an error
|
||||
! kubectl rollout status deployment/nginx --revision=3
|
||||
cat hack/testdata/deployment-revision1.yaml | $SED "s/name: nginx$/name: nginx2/" | kubectl create -f - "${kube_flags[@]}"
|
||||
|
@ -14,19 +14,4 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -16,13 +16,6 @@ limitations under the License.
|
||||
|
||||
package pod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO: to be de!eted after v1.3 is released. PodSpec has a dedicated Hostname field.
|
||||
// The annotation value is a string specifying the hostname to be used for the pod e.g 'my-webserver-1'
|
||||
@ -36,26 +29,3 @@ const (
|
||||
// <hostname>.my-web-service.<namespace>.svc.<cluster domain>" would be resolved by the cluster DNS Server.
|
||||
PodSubdomainAnnotation = "pod.beta.kubernetes.io/subdomain"
|
||||
)
|
||||
|
||||
// FindPort locates the container port for the given pod and portName. If the
|
||||
// targetPort is a number, use that. If the targetPort is a string, look that
|
||||
// string up in all named ports in all containers in the target pod. If no
|
||||
// match is found, fail.
|
||||
func FindPort(pod *api.Pod, svcPort *api.ServicePort) (int, error) {
|
||||
portName := svcPort.TargetPort
|
||||
switch portName.Type {
|
||||
case intstr.String:
|
||||
name := portName.StrVal
|
||||
for _, container := range pod.Spec.Containers {
|
||||
for _, port := range container.Ports {
|
||||
if port.Name == name && port.Protocol == svcPort.Protocol {
|
||||
return int(port.ContainerPort), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
case intstr.Int:
|
||||
return portName.IntValue(), nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
|
||||
}
|
||||
|
@ -97,15 +97,3 @@ func GetServiceHealthCheckNodePort(service *api.Service) int32 {
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetServiceHealthCheckPathPort Return the path and nodePort programmed into the Cloud LB Health Check
|
||||
func GetServiceHealthCheckPathPort(service *api.Service) (string, int32) {
|
||||
if !NeedsHealthCheck(service) {
|
||||
return "", 0
|
||||
}
|
||||
port := GetServiceHealthCheckNodePort(service)
|
||||
if port == 0 {
|
||||
return "", 0
|
||||
}
|
||||
return "/healthz", port
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ go_library(
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/batch:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
|
@ -18,6 +18,7 @@ package testing
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// DeepEqualSafePodSpec returns a PodSpec which is ready to be used with api.Semantic.DeepEqual
|
||||
@ -30,3 +31,14 @@ func DeepEqualSafePodSpec() api.PodSpec {
|
||||
SecurityContext: &api.PodSecurityContext{},
|
||||
}
|
||||
}
|
||||
|
||||
// V1DeepEqualSafePodSpec returns a PodSpec which is ready to be used with api.Semantic.DeepEqual
|
||||
func V1DeepEqualSafePodSpec() v1.PodSpec {
|
||||
grace := int64(30)
|
||||
return v1.PodSpec{
|
||||
RestartPolicy: v1.RestartPolicyAlways,
|
||||
DNSPolicy: v1.DNSClusterFirst,
|
||||
TerminationGracePeriodSeconds: &grace,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,13 @@ go_library(
|
||||
"conversion.go",
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"generate.go",
|
||||
"generated.pb.go",
|
||||
"helpers.go",
|
||||
"meta.go",
|
||||
"ref.go",
|
||||
"register.go",
|
||||
"resource_helpers.go",
|
||||
"types.generated.go",
|
||||
"types.go",
|
||||
"types_swagger_doc_generated.go",
|
||||
@ -36,11 +39,16 @@ go_library(
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/conversion:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/labels:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/selection:go_default_library",
|
||||
"//pkg/types:go_default_library",
|
||||
"//pkg/util:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
"//pkg/util/parsers:go_default_library",
|
||||
"//pkg/util/rand:go_default_library",
|
||||
"//pkg/util/sets:go_default_library",
|
||||
"//pkg/util/validation/field:go_default_library",
|
||||
"//pkg/watch/versioned:go_default_library",
|
||||
"//vendor:github.com/gogo/protobuf/proto",
|
||||
@ -70,3 +78,19 @@ go_test(
|
||||
"//pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"helpers_test.go",
|
||||
"resource_helpers_test.go",
|
||||
],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/labels:go_default_library",
|
||||
],
|
||||
)
|
||||
|
34
pkg/api/v1/endpoints/BUILD
Normal file
34
pkg/api/v1/endpoints/BUILD
Normal file
@ -0,0 +1,34 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/types:go_default_library",
|
||||
"//pkg/util/hash:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/types:go_default_library",
|
||||
"//vendor:github.com/davecgh/go-spew/spew",
|
||||
],
|
||||
)
|
238
pkg/api/v1/endpoints/util.go
Normal file
238
pkg/api/v1/endpoints/util.go
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
Copyright 2015 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 endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"sort"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO: to be deleted after v1.3 is released
|
||||
// Its value is the json representation of map[string(IP)][HostRecord]
|
||||
// example: '{"10.245.1.6":{"HostName":"my-webserver"}}'
|
||||
PodHostnamesAnnotation = "endpoints.beta.kubernetes.io/hostnames-map"
|
||||
)
|
||||
|
||||
// TODO: to be deleted after v1.3 is released
|
||||
type HostRecord struct {
|
||||
HostName string
|
||||
}
|
||||
|
||||
// RepackSubsets takes a slice of EndpointSubset objects, expands it to the full
|
||||
// representation, and then repacks that into the canonical layout. This
|
||||
// ensures that code which operates on these objects can rely on the common
|
||||
// form for things like comparison. The result is a newly allocated slice.
|
||||
func RepackSubsets(subsets []v1.EndpointSubset) []v1.EndpointSubset {
|
||||
// First map each unique port definition to the sets of hosts that
|
||||
// offer it.
|
||||
allAddrs := map[addressKey]*v1.EndpointAddress{}
|
||||
portToAddrReadyMap := map[v1.EndpointPort]addressSet{}
|
||||
for i := range subsets {
|
||||
for _, port := range subsets[i].Ports {
|
||||
for k := range subsets[i].Addresses {
|
||||
mapAddressByPort(&subsets[i].Addresses[k], port, true, allAddrs, portToAddrReadyMap)
|
||||
}
|
||||
for k := range subsets[i].NotReadyAddresses {
|
||||
mapAddressByPort(&subsets[i].NotReadyAddresses[k], port, false, allAddrs, portToAddrReadyMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next, map the sets of hosts to the sets of ports they offer.
|
||||
// Go does not allow maps or slices as keys to maps, so we have
|
||||
// to synthesize an artificial key and do a sort of 2-part
|
||||
// associative entity.
|
||||
type keyString string
|
||||
keyToAddrReadyMap := map[keyString]addressSet{}
|
||||
addrReadyMapKeyToPorts := map[keyString][]v1.EndpointPort{}
|
||||
for port, addrs := range portToAddrReadyMap {
|
||||
key := keyString(hashAddresses(addrs))
|
||||
keyToAddrReadyMap[key] = addrs
|
||||
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
|
||||
}
|
||||
|
||||
// Next, build the N-to-M association the API wants.
|
||||
final := []v1.EndpointSubset{}
|
||||
for key, ports := range addrReadyMapKeyToPorts {
|
||||
var readyAddrs, notReadyAddrs []v1.EndpointAddress
|
||||
for addr, ready := range keyToAddrReadyMap[key] {
|
||||
if ready {
|
||||
readyAddrs = append(readyAddrs, *addr)
|
||||
} else {
|
||||
notReadyAddrs = append(notReadyAddrs, *addr)
|
||||
}
|
||||
}
|
||||
final = append(final, v1.EndpointSubset{Addresses: readyAddrs, NotReadyAddresses: notReadyAddrs, Ports: ports})
|
||||
}
|
||||
|
||||
// Finally, sort it.
|
||||
return SortSubsets(final)
|
||||
}
|
||||
|
||||
// The sets of hosts must be de-duped, using IP+UID as the key.
|
||||
type addressKey struct {
|
||||
ip string
|
||||
uid types.UID
|
||||
}
|
||||
|
||||
// mapAddressByPort adds an address into a map by its ports, registering the address with a unique pointer, and preserving
|
||||
// any existing ready state.
|
||||
func mapAddressByPort(addr *v1.EndpointAddress, port v1.EndpointPort, ready bool, allAddrs map[addressKey]*v1.EndpointAddress, portToAddrReadyMap map[v1.EndpointPort]addressSet) *v1.EndpointAddress {
|
||||
// use addressKey to distinguish between two endpoints that are identical addresses
|
||||
// but may have come from different hosts, for attribution. For instance, Mesos
|
||||
// assigns pods the node IP, but the pods are distinct.
|
||||
key := addressKey{ip: addr.IP}
|
||||
if addr.TargetRef != nil {
|
||||
key.uid = addr.TargetRef.UID
|
||||
}
|
||||
|
||||
// Accumulate the address. The full EndpointAddress structure is preserved for use when
|
||||
// we rebuild the subsets so that the final TargetRef has all of the necessary data.
|
||||
existingAddress := allAddrs[key]
|
||||
if existingAddress == nil {
|
||||
// Make a copy so we don't write to the
|
||||
// input args of this function.
|
||||
existingAddress = &v1.EndpointAddress{}
|
||||
*existingAddress = *addr
|
||||
allAddrs[key] = existingAddress
|
||||
}
|
||||
|
||||
// Remember that this port maps to this address.
|
||||
if _, found := portToAddrReadyMap[port]; !found {
|
||||
portToAddrReadyMap[port] = addressSet{}
|
||||
}
|
||||
// if we have not yet recorded this port for this address, or if the previous
|
||||
// state was ready, write the current ready state. not ready always trumps
|
||||
// ready.
|
||||
if wasReady, found := portToAddrReadyMap[port][existingAddress]; !found || wasReady {
|
||||
portToAddrReadyMap[port][existingAddress] = ready
|
||||
}
|
||||
return existingAddress
|
||||
}
|
||||
|
||||
type addressSet map[*v1.EndpointAddress]bool
|
||||
|
||||
type addrReady struct {
|
||||
addr *v1.EndpointAddress
|
||||
ready bool
|
||||
}
|
||||
|
||||
func hashAddresses(addrs addressSet) string {
|
||||
// Flatten the list of addresses into a string so it can be used as a
|
||||
// map key. Unfortunately, DeepHashObject is implemented in terms of
|
||||
// spew, and spew does not handle non-primitive map keys well. So
|
||||
// first we collapse it into a slice, sort the slice, then hash that.
|
||||
slice := make([]addrReady, 0, len(addrs))
|
||||
for k, ready := range addrs {
|
||||
slice = append(slice, addrReady{k, ready})
|
||||
}
|
||||
sort.Sort(addrsReady(slice))
|
||||
hasher := md5.New()
|
||||
hashutil.DeepHashObject(hasher, slice)
|
||||
return hex.EncodeToString(hasher.Sum(nil)[0:])
|
||||
}
|
||||
|
||||
func lessAddrReady(a, b addrReady) bool {
|
||||
// ready is not significant to hashing since we can't have duplicate addresses
|
||||
return LessEndpointAddress(a.addr, b.addr)
|
||||
}
|
||||
|
||||
type addrsReady []addrReady
|
||||
|
||||
func (sl addrsReady) Len() int { return len(sl) }
|
||||
func (sl addrsReady) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrsReady) Less(i, j int) bool {
|
||||
return lessAddrReady(sl[i], sl[j])
|
||||
}
|
||||
|
||||
func LessEndpointAddress(a, b *v1.EndpointAddress) bool {
|
||||
ipComparison := bytes.Compare([]byte(a.IP), []byte(b.IP))
|
||||
if ipComparison != 0 {
|
||||
return ipComparison < 0
|
||||
}
|
||||
if b.TargetRef == nil {
|
||||
return false
|
||||
}
|
||||
if a.TargetRef == nil {
|
||||
return true
|
||||
}
|
||||
return a.TargetRef.UID < b.TargetRef.UID
|
||||
}
|
||||
|
||||
type addrPtrsByIpAndUID []*v1.EndpointAddress
|
||||
|
||||
func (sl addrPtrsByIpAndUID) Len() int { return len(sl) }
|
||||
func (sl addrPtrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrPtrsByIpAndUID) Less(i, j int) bool {
|
||||
return LessEndpointAddress(sl[i], sl[j])
|
||||
}
|
||||
|
||||
// SortSubsets sorts an array of EndpointSubset objects in place. For ease of
|
||||
// use it returns the input slice.
|
||||
func SortSubsets(subsets []v1.EndpointSubset) []v1.EndpointSubset {
|
||||
for i := range subsets {
|
||||
ss := &subsets[i]
|
||||
sort.Sort(addrsByIpAndUID(ss.Addresses))
|
||||
sort.Sort(addrsByIpAndUID(ss.NotReadyAddresses))
|
||||
sort.Sort(portsByHash(ss.Ports))
|
||||
}
|
||||
sort.Sort(subsetsByHash(subsets))
|
||||
return subsets
|
||||
}
|
||||
|
||||
func hashObject(hasher hash.Hash, obj interface{}) []byte {
|
||||
hashutil.DeepHashObject(hasher, obj)
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
type subsetsByHash []v1.EndpointSubset
|
||||
|
||||
func (sl subsetsByHash) Len() int { return len(sl) }
|
||||
func (sl subsetsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl subsetsByHash) Less(i, j int) bool {
|
||||
hasher := md5.New()
|
||||
h1 := hashObject(hasher, sl[i])
|
||||
h2 := hashObject(hasher, sl[j])
|
||||
return bytes.Compare(h1, h2) < 0
|
||||
}
|
||||
|
||||
type addrsByIpAndUID []v1.EndpointAddress
|
||||
|
||||
func (sl addrsByIpAndUID) Len() int { return len(sl) }
|
||||
func (sl addrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrsByIpAndUID) Less(i, j int) bool {
|
||||
return LessEndpointAddress(&sl[i], &sl[j])
|
||||
}
|
||||
|
||||
type portsByHash []v1.EndpointPort
|
||||
|
||||
func (sl portsByHash) Len() int { return len(sl) }
|
||||
func (sl portsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl portsByHash) Less(i, j int) bool {
|
||||
hasher := md5.New()
|
||||
h1 := hashObject(hasher, sl[i])
|
||||
h2 := hashObject(hasher, sl[j])
|
||||
return bytes.Compare(h1, h2) < 0
|
||||
}
|
464
pkg/api/v1/endpoints/util_test.go
Normal file
464
pkg/api/v1/endpoints/util_test.go
Normal file
@ -0,0 +1,464 @@
|
||||
/*
|
||||
Copyright 2015 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 endpoints
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
)
|
||||
|
||||
func podRef(uid string) *v1.ObjectReference {
|
||||
ref := v1.ObjectReference{UID: types.UID(uid)}
|
||||
return &ref
|
||||
}
|
||||
|
||||
func TestPackSubsets(t *testing.T) {
|
||||
// The downside of table-driven tests is that some things have to live outside the table.
|
||||
fooObjRef := v1.ObjectReference{Name: "foo"}
|
||||
barObjRef := v1.ObjectReference{Name: "bar"}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
given []v1.EndpointSubset
|
||||
expect []v1.EndpointSubset
|
||||
}{
|
||||
{
|
||||
name: "empty everything",
|
||||
given: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{}, Ports: []v1.EndpointPort{}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty addresses",
|
||||
given: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{}, Ports: []v1.EndpointPort{{Port: 111}}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty ports",
|
||||
given: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []v1.EndpointPort{}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty ports",
|
||||
given: []v1.EndpointSubset{{NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []v1.EndpointPort{}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "one set, one ip, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, one port (IPv6)",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1:2:3:4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1:2:3:4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, one UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, one UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, empty UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, empty UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two ips, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two mixed ips, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two duplicate ips, one port, notReady is covered by ready",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips, one port (IPv6)",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1"}, {IP: "beef::1"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips with target-refs, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &fooObjRef},
|
||||
{IP: "1.2.3.4", TargetRef: &barObjRef},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup mixed ips with target-refs, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &fooObjRef},
|
||||
},
|
||||
NotReadyAddresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &barObjRef},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
// finding the same address twice is considered an error on input, only the first address+port
|
||||
// reference is preserved
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, dup ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, dup port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup mixed ip, dup port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, dup uids, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup mixed ip, dup uids, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, dup port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two set, dup ip, two uids, dup ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-2")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two set, dup ip, with and without uid, dup ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-2")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, two dup ip with uid, dup port, wrong order",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "5.6.7.8"},
|
||||
{IP: "5.6.7.8", TargetRef: podRef("uid-1")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two mixed ips, two dup ip with uid, dup port, wrong order, ends up with split addresses",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "5.6.7.8"},
|
||||
},
|
||||
NotReadyAddresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "5.6.7.8", TargetRef: podRef("uid-1")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "four sets, three ips, three ports, jumbled",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 333}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}, {Port: 333}},
|
||||
}},
|
||||
}, {
|
||||
name: "four sets, three mixed ips, three ports, jumbled",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 333}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}, {Port: 333}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
result := RepackSubsets(tc.given)
|
||||
if !reflect.DeepEqual(result, SortSubsets(tc.expect)) {
|
||||
t.Errorf("case %q: expected %s, got %s", tc.name, spew.Sprintf("%#v", SortSubsets(tc.expect)), spew.Sprintf("%#v", result))
|
||||
}
|
||||
}
|
||||
}
|
64
pkg/api/v1/generate.go
Normal file
64
pkg/api/v1/generate.go
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2014 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 v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
utilrand "k8s.io/kubernetes/pkg/util/rand"
|
||||
)
|
||||
|
||||
// NameGenerator generates names for objects. Some backends may have more information
|
||||
// available to guide selection of new names and this interface hides those details.
|
||||
type NameGenerator interface {
|
||||
// GenerateName generates a valid name from the base name, adding a random suffix to the
|
||||
// the base. If base is valid, the returned name must also be valid. The generator is
|
||||
// responsible for knowing the maximum valid name length.
|
||||
GenerateName(base string) string
|
||||
}
|
||||
|
||||
// GenerateName will resolve the object name of the provided ObjectMeta to a generated version if
|
||||
// necessary. It expects that validation for ObjectMeta has already completed (that Base is a
|
||||
// valid name) and that the NameGenerator generates a name that is also valid.
|
||||
func GenerateName(u NameGenerator, meta *ObjectMeta) {
|
||||
if len(meta.GenerateName) == 0 || len(meta.Name) != 0 {
|
||||
return
|
||||
}
|
||||
meta.Name = u.GenerateName(meta.GenerateName)
|
||||
}
|
||||
|
||||
// simpleNameGenerator generates random names.
|
||||
type simpleNameGenerator struct{}
|
||||
|
||||
// SimpleNameGenerator is a generator that returns the name plus a random suffix of five alphanumerics
|
||||
// when a name is requested. The string is guaranteed to not exceed the length of a standard Kubernetes
|
||||
// name (63 characters)
|
||||
var SimpleNameGenerator NameGenerator = simpleNameGenerator{}
|
||||
|
||||
const (
|
||||
// TODO: make this flexible for non-core resources with alternate naming rules.
|
||||
maxNameLength = 63
|
||||
randomLength = 5
|
||||
maxGeneratedNameLength = maxNameLength - randomLength
|
||||
)
|
||||
|
||||
func (simpleNameGenerator) GenerateName(base string) string {
|
||||
if len(base) > maxGeneratedNameLength {
|
||||
base = base[:maxGeneratedNameLength]
|
||||
}
|
||||
return fmt.Sprintf("%s%s", base, utilrand.String(randomLength))
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1465,6 +1465,13 @@ message NodeProxyOptions {
|
||||
optional string path = 1;
|
||||
}
|
||||
|
||||
// NodeResources is an object for conveying resource information about a node.
|
||||
// see http://releases.k8s.io/HEAD/docs/design/resources.md for more details.
|
||||
message NodeResources {
|
||||
// Capacity represents the available resources of a node
|
||||
map<string, k8s.io.kubernetes.pkg.api.resource.Quantity> capacity = 1;
|
||||
}
|
||||
|
||||
// A node selector represents the union of the results of one or more label queries
|
||||
// over a set of nodes; that is, it represents the OR of the selectors represented
|
||||
// by the node selector terms.
|
||||
@ -3360,6 +3367,12 @@ message ServiceStatus {
|
||||
optional LoadBalancerStatus loadBalancer = 1;
|
||||
}
|
||||
|
||||
message Sysctl {
|
||||
optional string name = 1;
|
||||
|
||||
optional string value = 2;
|
||||
}
|
||||
|
||||
// TCPSocketAction describes an action based on opening a socket
|
||||
message TCPSocketAction {
|
||||
// Number or name of the port to access on the container.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
Copyright 2014 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.
|
||||
@ -16,18 +16,441 @@ limitations under the License.
|
||||
|
||||
package v1
|
||||
|
||||
import "k8s.io/kubernetes/pkg/types"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/selection"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
// IsOpaqueIntResourceName returns true if the resource name has the opaque
|
||||
// integer resource prefix.
|
||||
func IsOpaqueIntResourceName(name ResourceName) bool {
|
||||
return strings.HasPrefix(string(name), 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)
|
||||
}
|
||||
return ResourceName(fmt.Sprintf("%s%s", api.ResourceOpaqueIntPrefix, name))
|
||||
}
|
||||
|
||||
// NewDeleteOptions returns a DeleteOptions indicating the resource should
|
||||
// be deleted within the specified grace period. Use zero to indicate
|
||||
// immediate deletion. If you would prefer to use the default grace period,
|
||||
// use &v1.DeleteOptions{} directly.
|
||||
// use &api.DeleteOptions{} directly.
|
||||
func NewDeleteOptions(grace int64) *DeleteOptions {
|
||||
return &DeleteOptions{GracePeriodSeconds: &grace}
|
||||
}
|
||||
|
||||
// NewPreconditionDeleteOptions returns a DeleteOptions with a UID precondition set.
|
||||
func NewPreconditionDeleteOptions(uid string) *DeleteOptions {
|
||||
u := types.UID(uid)
|
||||
p := Preconditions{UID: &u}
|
||||
return &DeleteOptions{Preconditions: &p}
|
||||
}
|
||||
|
||||
// NewUIDPreconditions returns a Preconditions with UID set.
|
||||
func NewUIDPreconditions(uid string) *Preconditions {
|
||||
u := types.UID(uid)
|
||||
return &Preconditions{UID: &u}
|
||||
}
|
||||
|
||||
// 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 != ""
|
||||
}
|
||||
|
||||
// this function aims to check if the service's cluster IP is requested or not
|
||||
func IsServiceIPRequested(service *Service) bool {
|
||||
// ExternalName services are CNAME aliases to external ones. Ignore the IP.
|
||||
if service.Spec.Type == ServiceTypeExternalName {
|
||||
return false
|
||||
}
|
||||
return service.Spec.ClusterIP == ""
|
||||
}
|
||||
|
||||
var standardFinalizers = sets.NewString(
|
||||
string(FinalizerKubernetes),
|
||||
FinalizerOrphan,
|
||||
)
|
||||
|
||||
// HasAnnotation returns a bool if passed in annotation exists
|
||||
func HasAnnotation(obj ObjectMeta, ann string) bool {
|
||||
_, found := obj.Annotations[ann]
|
||||
return found
|
||||
}
|
||||
|
||||
// SetMetaDataAnnotation sets the annotation and value
|
||||
func SetMetaDataAnnotation(obj *ObjectMeta, ann string, value string) {
|
||||
if obj.Annotations == nil {
|
||||
obj.Annotations = make(map[string]string)
|
||||
}
|
||||
obj.Annotations[ann] = value
|
||||
}
|
||||
|
||||
func IsStandardFinalizerName(str string) bool {
|
||||
return standardFinalizers.Has(str)
|
||||
}
|
||||
|
||||
// SingleObject returns a ListOptions for watching a single object.
|
||||
func SingleObject(meta ObjectMeta) ListOptions {
|
||||
return ListOptions{
|
||||
FieldSelector: fields.OneTermEqualSelector("metadata.name", meta.Name).String(),
|
||||
ResourceVersion: meta.ResourceVersion,
|
||||
}
|
||||
}
|
||||
|
||||
// AddToNodeAddresses appends the NodeAddresses to the passed-by-pointer slice,
|
||||
// only if they do not already exist
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make method on LoadBalancerStatus?
|
||||
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
|
||||
}
|
||||
|
||||
// TODO: make method on LoadBalancerStatus?
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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, ",")
|
||||
}
|
||||
|
||||
// GetAccessModesAsString returns an array of AccessModes from a string created by GetAccessModesAsString
|
||||
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
|
||||
}
|
||||
|
||||
// removeDuplicateAccessModes returns an array of access modes without any duplicates
|
||||
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
|
||||
}
|
||||
|
||||
// NodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
|
||||
// labels.Selector.
|
||||
func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.Selector, error) {
|
||||
if len(nsm) == 0 {
|
||||
return labels.Nothing(), nil
|
||||
}
|
||||
selector := labels.NewSelector()
|
||||
for _, expr := range nsm {
|
||||
var op selection.Operator
|
||||
switch expr.Operator {
|
||||
case NodeSelectorOpIn:
|
||||
op = selection.In
|
||||
case NodeSelectorOpNotIn:
|
||||
op = selection.NotIn
|
||||
case NodeSelectorOpExists:
|
||||
op = selection.Exists
|
||||
case NodeSelectorOpDoesNotExist:
|
||||
op = selection.DoesNotExist
|
||||
case NodeSelectorOpGt:
|
||||
op = selection.GreaterThan
|
||||
case NodeSelectorOpLt:
|
||||
op = selection.LessThan
|
||||
default:
|
||||
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
|
||||
}
|
||||
r, err := labels.NewRequirement(expr.Key, op, expr.Values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selector = selector.Add(*r)
|
||||
}
|
||||
return selector, nil
|
||||
}
|
||||
|
||||
const (
|
||||
// AffinityAnnotationKey represents the key of affinity data (json serialized)
|
||||
// in the Annotations of a Pod.
|
||||
AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity"
|
||||
|
||||
// TolerationsAnnotationKey represents the key of tolerations data (json serialized)
|
||||
// in the Annotations of a Pod.
|
||||
TolerationsAnnotationKey string = "scheduler.alpha.kubernetes.io/tolerations"
|
||||
|
||||
// TaintsAnnotationKey represents the key of taints data (json serialized)
|
||||
// in the Annotations of a Node.
|
||||
TaintsAnnotationKey string = "scheduler.alpha.kubernetes.io/taints"
|
||||
|
||||
// SeccompPodAnnotationKey represents the key of a seccomp profile applied
|
||||
// to all containers of a pod.
|
||||
SeccompPodAnnotationKey string = "seccomp.security.alpha.kubernetes.io/pod"
|
||||
|
||||
// SeccompContainerAnnotationKeyPrefix represents the key of a seccomp profile applied
|
||||
// to one container of a pod.
|
||||
SeccompContainerAnnotationKeyPrefix string = "container.seccomp.security.alpha.kubernetes.io/"
|
||||
|
||||
// CreatedByAnnotation represents the key used to store the spec(json)
|
||||
// used to create the resource.
|
||||
CreatedByAnnotation = "kubernetes.io/created-by"
|
||||
|
||||
// PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized)
|
||||
// in the Annotations of a Node.
|
||||
PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods"
|
||||
|
||||
// SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure
|
||||
// container of a pod. The annotation value is a comma separated list of sysctl_name=value
|
||||
// key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by
|
||||
// the kubelet. Pods with other sysctls will fail to launch.
|
||||
SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls"
|
||||
|
||||
// UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure
|
||||
// container of a pod. The annotation value is a comma separated list of sysctl_name=value
|
||||
// key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly
|
||||
// namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use
|
||||
// is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet
|
||||
// will fail to launch.
|
||||
UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls"
|
||||
)
|
||||
|
||||
// GetAffinityFromPod gets the json serialized affinity data from Pod.Annotations
|
||||
// and converts it to the Affinity type in api.
|
||||
func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) {
|
||||
if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" {
|
||||
var affinity Affinity
|
||||
err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &affinity, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 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.
|
||||
func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
|
||||
if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
|
||||
return false
|
||||
}
|
||||
|
||||
if toleration.Key != taint.Key {
|
||||
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 {
|
||||
return true
|
||||
}
|
||||
if toleration.Operator == TolerationOpExists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations.
|
||||
func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool {
|
||||
tolerated := false
|
||||
for i := range tolerations {
|
||||
if TolerationToleratesTaint(&tolerations[i], taint) {
|
||||
tolerated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
// 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])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
unsafe, err := SysctlsFromPodAnnotation(a[UnsafeSysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return safe, unsafe, nil
|
||||
}
|
||||
|
||||
// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls.
|
||||
func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) {
|
||||
if len(annotation) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
kvs := strings.Split(annotation, ",")
|
||||
sysctls := make([]Sysctl, len(kvs))
|
||||
for i, kv := range kvs {
|
||||
cs := strings.Split(kv, "=")
|
||||
if len(cs) != 2 || len(cs[0]) == 0 {
|
||||
return nil, fmt.Errorf("sysctl %q not of the format sysctl_name=value", kv)
|
||||
}
|
||||
sysctls[i].Name = cs[0]
|
||||
sysctls[i].Value = cs[1]
|
||||
}
|
||||
return sysctls, nil
|
||||
}
|
||||
|
||||
// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls.
|
||||
func PodAnnotationsFromSysctls(sysctls []Sysctl) string {
|
||||
if len(sysctls) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
kvs := make([]string, len(sysctls))
|
||||
for i := range sysctls {
|
||||
kvs[i] = fmt.Sprintf("%s=%s", sysctls[i].Name, sysctls[i].Value)
|
||||
}
|
||||
return strings.Join(kvs, ",")
|
||||
}
|
||||
|
||||
type Sysctl struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
// NodeResources is an object for conveying resource information about a node.
|
||||
// see http://releases.k8s.io/HEAD/docs/design/resources.md for more details.
|
||||
type NodeResources struct {
|
||||
// Capacity represents the available resources of a node
|
||||
Capacity ResourceList
|
||||
}
|
||||
|
479
pkg/api/v1/helpers_test.go
Normal file
479
pkg/api/v1/helpers_test.go
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
Copyright 2015 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 v1
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
func TestAddToNodeAddresses(t *testing.T) {
|
||||
testCases := []struct {
|
||||
existing []NodeAddress
|
||||
toAdd []NodeAddress
|
||||
expected []NodeAddress
|
||||
}{
|
||||
{
|
||||
existing: []NodeAddress{},
|
||||
toAdd: []NodeAddress{},
|
||||
expected: []NodeAddress{},
|
||||
},
|
||||
{
|
||||
existing: []NodeAddress{},
|
||||
toAdd: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
expected: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
},
|
||||
{
|
||||
existing: []NodeAddress{},
|
||||
toAdd: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
},
|
||||
expected: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
existing: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeInternalIP, Address: "10.1.1.1"},
|
||||
},
|
||||
toAdd: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
expected: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeInternalIP, Address: "10.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
AddToNodeAddresses(&tc.existing, tc.toAdd...)
|
||||
if !api.Semantic.DeepEqual(tc.expected, tc.existing) {
|
||||
t.Errorf("case[%d], expected: %v, got: %v", i, tc.expected, tc.existing)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccessModesFromString(t *testing.T) {
|
||||
modes := GetAccessModesFromString("ROX")
|
||||
if !containsAccessMode(modes, ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes)
|
||||
}
|
||||
|
||||
modes = GetAccessModesFromString("ROX,RWX")
|
||||
if !containsAccessMode(modes, ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes)
|
||||
}
|
||||
if !containsAccessMode(modes, ReadWriteMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadWriteMany, modes)
|
||||
}
|
||||
|
||||
modes = GetAccessModesFromString("RWO,ROX,RWX")
|
||||
if !containsAccessMode(modes, ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes)
|
||||
}
|
||||
if !containsAccessMode(modes, ReadWriteMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadWriteMany, modes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveDuplicateAccessModes(t *testing.T) {
|
||||
modes := []PersistentVolumeAccessMode{
|
||||
ReadWriteOnce, ReadOnlyMany, ReadOnlyMany, ReadOnlyMany,
|
||||
}
|
||||
modes = removeDuplicateAccessModes(modes)
|
||||
if len(modes) != 2 {
|
||||
t.Errorf("Expected 2 distinct modes in set but found %v", len(modes))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
|
||||
matchExpressions := []NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: NodeSelectorOpIn,
|
||||
Values: []string{"bar", "baz"},
|
||||
}}
|
||||
mustParse := func(s string) labels.Selector {
|
||||
out, e := labels.Parse(s)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return out
|
||||
}
|
||||
tc := []struct {
|
||||
in []NodeSelectorRequirement
|
||||
out labels.Selector
|
||||
expectErr bool
|
||||
}{
|
||||
{in: nil, out: labels.Nothing()},
|
||||
{in: []NodeSelectorRequirement{}, out: labels.Nothing()},
|
||||
{
|
||||
in: matchExpressions,
|
||||
out: mustParse("foo in (baz,bar)"),
|
||||
},
|
||||
{
|
||||
in: []NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: NodeSelectorOpExists,
|
||||
Values: []string{"bar", "baz"},
|
||||
}},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
in: []NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: NodeSelectorOpGt,
|
||||
Values: []string{"1"},
|
||||
}},
|
||||
out: mustParse("foo>1"),
|
||||
},
|
||||
{
|
||||
in: []NodeSelectorRequirement{{
|
||||
Key: "bar",
|
||||
Operator: NodeSelectorOpLt,
|
||||
Values: []string{"7"},
|
||||
}},
|
||||
out: mustParse("bar<7"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tc {
|
||||
out, err := NodeSelectorRequirementsAsSelector(tc.in)
|
||||
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(out, tc.out) {
|
||||
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAffinityFromPod(t *testing.T) {
|
||||
testCases := []struct {
|
||||
pod *Pod
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
pod: &Pod{},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
pod: &Pod{
|
||||
ObjectMeta: ObjectMeta{
|
||||
Annotations: map[string]string{
|
||||
AffinityAnnotationKey: `
|
||||
{"nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": {
|
||||
"nodeSelectorTerms": [{
|
||||
"matchExpressions": [{
|
||||
"key": "foo",
|
||||
"operator": "In",
|
||||
"values": ["value1", "value2"]
|
||||
}]
|
||||
}]
|
||||
}}}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
pod: &Pod{
|
||||
ObjectMeta: ObjectMeta{
|
||||
Annotations: map[string]string{
|
||||
AffinityAnnotationKey: `
|
||||
{"nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": {
|
||||
"nodeSelectorTerms": [{
|
||||
"matchExpressions": [{
|
||||
"key": "foo",
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
_, err := GetAffinityFromPodAnnotations(tc.pod.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaintToString(t *testing.T) {
|
||||
testCases := []struct {
|
||||
taint *Taint
|
||||
expectedString string
|
||||
}{
|
||||
{
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectedString: "foo=bar:NoSchedule",
|
||||
},
|
||||
{
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectedString: "foo:NoSchedule",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
if tc.expectedString != tc.taint.ToString() {
|
||||
t.Errorf("[%v] expected taint %v converted to %s, got %s", i, tc.taint, tc.expectedString, tc.taint.ToString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchTaint(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
taint *Taint
|
||||
taintToMatch Taint
|
||||
expectMatch bool
|
||||
}{
|
||||
{
|
||||
description: "two taints with the same key,value,effect should match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
description: "two taints with the same key,effect but different value should match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "different-value",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different key cannot match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "different-key",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different effect cannot match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectPreferNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
if tc.expectMatch != tc.taint.MatchTaint(tc.taintToMatch) {
|
||||
t.Errorf("[%s] expect taint %s match taint %s", tc.description, tc.taint.ToString(), tc.taintToMatch.ToString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAvoidPodsFromNode(t *testing.T) {
|
||||
controllerFlag := true
|
||||
testCases := []struct {
|
||||
node *Node
|
||||
expectValue AvoidPods
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
node: &Node{},
|
||||
expectValue: AvoidPods{},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
node: &Node{
|
||||
ObjectMeta: 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: &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: 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) {
|
||||
type Test struct {
|
||||
annotation string
|
||||
expectValue []Sysctl
|
||||
expectErr bool
|
||||
}
|
||||
for i, test := range []Test{
|
||||
{
|
||||
annotation: "",
|
||||
expectValue: nil,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "=123",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=",
|
||||
expectValue: []Sysctl{{Name: "foo.bar", Value: ""}},
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42",
|
||||
expectValue: []Sysctl{{Name: "foo.bar", Value: "42"}},
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42,",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42,abc.def=1",
|
||||
expectValue: []Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}},
|
||||
},
|
||||
} {
|
||||
sysctls, err := SysctlsFromPodAnnotation(test.annotation)
|
||||
if test.expectErr && err == nil {
|
||||
t.Errorf("[%v]expected error but got none", i)
|
||||
} else if !test.expectErr && err != nil {
|
||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
||||
} else if !reflect.DeepEqual(sysctls, test.expectValue) {
|
||||
t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls)
|
||||
}
|
||||
}
|
||||
}
|
32
pkg/api/v1/pod/BUILD
Normal file
32
pkg/api/v1/pod/BUILD
Normal file
@ -0,0 +1,32 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
120
pkg/api/v1/pod/util.go
Normal file
120
pkg/api/v1/pod/util.go
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2015 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 pod
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO: to be de!eted after v1.3 is released. PodSpec has a dedicated Hostname field.
|
||||
// The annotation value is a string specifying the hostname to be used for the pod e.g 'my-webserver-1'
|
||||
PodHostnameAnnotation = "pod.beta.kubernetes.io/hostname"
|
||||
|
||||
// TODO: to be de!eted after v1.3 is released. PodSpec has a dedicated Subdomain field.
|
||||
// The annotation value is a string specifying the subdomain e.g. "my-web-service"
|
||||
// If specified, on the pod itself, "<hostname>.my-web-service.<namespace>.svc.<cluster domain>" would resolve to
|
||||
// the pod's IP.
|
||||
// If there is a headless service named "my-web-service" in the same namespace as the pod, then,
|
||||
// <hostname>.my-web-service.<namespace>.svc.<cluster domain>" would be resolved by the cluster DNS Server.
|
||||
PodSubdomainAnnotation = "pod.beta.kubernetes.io/subdomain"
|
||||
)
|
||||
|
||||
// FindPort locates the container port for the given pod and portName. If the
|
||||
// targetPort is a number, use that. If the targetPort is a string, look that
|
||||
// string up in all named ports in all containers in the target pod. If no
|
||||
// match is found, fail.
|
||||
func FindPort(pod *v1.Pod, svcPort *v1.ServicePort) (int, error) {
|
||||
portName := svcPort.TargetPort
|
||||
switch portName.Type {
|
||||
case intstr.String:
|
||||
name := portName.StrVal
|
||||
for _, container := range pod.Spec.Containers {
|
||||
for _, port := range container.Ports {
|
||||
if port.Name == name && port.Protocol == svcPort.Protocol {
|
||||
return int(port.ContainerPort), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
case intstr.Int:
|
||||
return portName.IntValue(), nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
|
||||
}
|
||||
|
||||
// TODO: remove this function when init containers becomes a stable feature
|
||||
func SetInitContainersAndStatuses(pod *v1.Pod) error {
|
||||
var initContainersAnnotation string
|
||||
initContainersAnnotation = pod.Annotations[v1.PodInitContainersAnnotationKey]
|
||||
initContainersAnnotation = pod.Annotations[v1.PodInitContainersBetaAnnotationKey]
|
||||
if len(initContainersAnnotation) > 0 {
|
||||
var values []v1.Container
|
||||
if err := json.Unmarshal([]byte(initContainersAnnotation), &values); err != nil {
|
||||
return err
|
||||
}
|
||||
pod.Spec.InitContainers = values
|
||||
}
|
||||
|
||||
var initContainerStatusesAnnotation string
|
||||
initContainerStatusesAnnotation = pod.Annotations[v1.PodInitContainerStatusesAnnotationKey]
|
||||
initContainerStatusesAnnotation = pod.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey]
|
||||
if len(initContainerStatusesAnnotation) > 0 {
|
||||
var values []v1.ContainerStatus
|
||||
if err := json.Unmarshal([]byte(initContainerStatusesAnnotation), &values); err != nil {
|
||||
return err
|
||||
}
|
||||
pod.Status.InitContainerStatuses = values
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: remove this function when init containers becomes a stable feature
|
||||
func SetInitContainersAnnotations(pod *v1.Pod) error {
|
||||
if len(pod.Spec.InitContainers) > 0 {
|
||||
value, err := json.Marshal(pod.Spec.InitContainers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pod.Annotations == nil {
|
||||
pod.Annotations = make(map[string]string)
|
||||
}
|
||||
pod.Annotations[v1.PodInitContainersAnnotationKey] = string(value)
|
||||
pod.Annotations[v1.PodInitContainersBetaAnnotationKey] = string(value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: remove this function when init containers becomes a stable feature
|
||||
func SetInitContainersStatusesAnnotations(pod *v1.Pod) error {
|
||||
if len(pod.Status.InitContainerStatuses) > 0 {
|
||||
value, err := json.Marshal(pod.Status.InitContainerStatuses)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pod.Annotations == nil {
|
||||
pod.Annotations = make(map[string]string)
|
||||
}
|
||||
pod.Annotations[v1.PodInitContainerStatusesAnnotationKey] = string(value)
|
||||
pod.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey] = string(value)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -19,26 +19,26 @@ package pod
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func TestFindPort(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
containers []api.Container
|
||||
containers []v1.Container
|
||||
port intstr.IntOrString
|
||||
expected int
|
||||
pass bool
|
||||
}{{
|
||||
name: "valid int, no ports",
|
||||
containers: []api.Container{{}},
|
||||
containers: []v1.Container{{}},
|
||||
port: intstr.FromInt(93),
|
||||
expected: 93,
|
||||
pass: true,
|
||||
}, {
|
||||
name: "valid int, with ports",
|
||||
containers: []api.Container{{Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{Ports: []v1.ContainerPort{{
|
||||
Name: "",
|
||||
ContainerPort: 11,
|
||||
Protocol: "TCP",
|
||||
@ -52,13 +52,13 @@ func TestFindPort(t *testing.T) {
|
||||
pass: true,
|
||||
}, {
|
||||
name: "valid str, no ports",
|
||||
containers: []api.Container{{}},
|
||||
containers: []v1.Container{{}},
|
||||
port: intstr.FromString("p"),
|
||||
expected: 0,
|
||||
pass: false,
|
||||
}, {
|
||||
name: "valid str, one ctr with ports",
|
||||
containers: []api.Container{{Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{Ports: []v1.ContainerPort{{
|
||||
Name: "",
|
||||
ContainerPort: 11,
|
||||
Protocol: "UDP",
|
||||
@ -76,7 +76,7 @@ func TestFindPort(t *testing.T) {
|
||||
pass: true,
|
||||
}, {
|
||||
name: "valid str, two ctr with ports",
|
||||
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
|
||||
Name: "",
|
||||
ContainerPort: 11,
|
||||
Protocol: "UDP",
|
||||
@ -94,7 +94,7 @@ func TestFindPort(t *testing.T) {
|
||||
pass: true,
|
||||
}, {
|
||||
name: "valid str, two ctr with same port",
|
||||
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
|
||||
Name: "",
|
||||
ContainerPort: 11,
|
||||
Protocol: "UDP",
|
||||
@ -112,7 +112,7 @@ func TestFindPort(t *testing.T) {
|
||||
pass: true,
|
||||
}, {
|
||||
name: "valid str, invalid protocol",
|
||||
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
|
||||
Name: "a",
|
||||
ContainerPort: 11,
|
||||
Protocol: "snmp",
|
||||
@ -123,7 +123,7 @@ func TestFindPort(t *testing.T) {
|
||||
pass: false,
|
||||
}, {
|
||||
name: "valid hostPort",
|
||||
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
|
||||
Name: "a",
|
||||
ContainerPort: 11,
|
||||
HostPort: 81,
|
||||
@ -136,7 +136,7 @@ func TestFindPort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "invalid hostPort",
|
||||
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
|
||||
Name: "a",
|
||||
ContainerPort: 11,
|
||||
HostPort: -1,
|
||||
@ -150,7 +150,7 @@ func TestFindPort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "invalid ContainerPort",
|
||||
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
|
||||
Name: "a",
|
||||
ContainerPort: -1,
|
||||
Protocol: "TCP",
|
||||
@ -163,7 +163,7 @@ func TestFindPort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "HostIP Address",
|
||||
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
|
||||
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
|
||||
Name: "a",
|
||||
ContainerPort: 11,
|
||||
HostIP: "192.168.1.1",
|
||||
@ -177,8 +177,8 @@ func TestFindPort(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
port, err := FindPort(&api.Pod{Spec: api.PodSpec{Containers: tc.containers}},
|
||||
&api.ServicePort{Protocol: "TCP", TargetPort: tc.port})
|
||||
port, err := FindPort(&v1.Pod{Spec: v1.PodSpec{Containers: tc.containers}},
|
||||
&v1.ServicePort{Protocol: "TCP", TargetPort: tc.port})
|
||||
if err != nil && tc.pass {
|
||||
t.Errorf("unexpected error for %s: %v", tc.name, err)
|
||||
}
|
133
pkg/api/v1/ref.go
Normal file
133
pkg/api/v1/ref.go
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2014 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 v1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
// Errors that could be returned by GetReference.
|
||||
ErrNilObject = errors.New("can't reference a nil object")
|
||||
ErrNoSelfLink = errors.New("selfLink was empty, can't make reference")
|
||||
)
|
||||
|
||||
// GetReference returns an ObjectReference which refers to the given
|
||||
// object, or an error if the object doesn't follow the conventions
|
||||
// that would allow this.
|
||||
// TODO: should take a meta.Interface see http://issue.k8s.io/7127
|
||||
func GetReference(obj runtime.Object) (*ObjectReference, error) {
|
||||
if obj == nil {
|
||||
return nil, ErrNilObject
|
||||
}
|
||||
if ref, ok := obj.(*ObjectReference); ok {
|
||||
// Don't make a reference to a reference.
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
gvk := obj.GetObjectKind().GroupVersionKind()
|
||||
|
||||
// if the object referenced is actually persisted, we can just get kind from meta
|
||||
// if we are building an object reference to something not yet persisted, we should fallback to scheme
|
||||
kind := gvk.Kind
|
||||
if len(kind) == 0 {
|
||||
// TODO: this is wrong
|
||||
gvks, _, err := api.Scheme.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kind = gvks[0].Kind
|
||||
}
|
||||
|
||||
// An object that implements only List has enough metadata to build a reference
|
||||
var listMeta meta.List
|
||||
objectMeta, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
listMeta, err = meta.ListAccessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
listMeta = objectMeta
|
||||
}
|
||||
|
||||
// if the object referenced is actually persisted, we can also get version from meta
|
||||
version := gvk.GroupVersion().String()
|
||||
if len(version) == 0 {
|
||||
selfLink := listMeta.GetSelfLink()
|
||||
if len(selfLink) == 0 {
|
||||
return nil, ErrNoSelfLink
|
||||
}
|
||||
selfLinkUrl, err := url.Parse(selfLink)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// example paths: /<prefix>/<version>/*
|
||||
parts := strings.Split(selfLinkUrl.Path, "/")
|
||||
if len(parts) < 3 {
|
||||
return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version)
|
||||
}
|
||||
version = parts[2]
|
||||
}
|
||||
|
||||
// only has list metadata
|
||||
if objectMeta == nil {
|
||||
return &ObjectReference{
|
||||
Kind: kind,
|
||||
APIVersion: version,
|
||||
ResourceVersion: listMeta.GetResourceVersion(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &ObjectReference{
|
||||
Kind: kind,
|
||||
APIVersion: version,
|
||||
Name: objectMeta.GetName(),
|
||||
Namespace: objectMeta.GetNamespace(),
|
||||
UID: objectMeta.GetUID(),
|
||||
ResourceVersion: objectMeta.GetResourceVersion(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetPartialReference is exactly like GetReference, but allows you to set the FieldPath.
|
||||
func GetPartialReference(obj runtime.Object, fieldPath string) (*ObjectReference, error) {
|
||||
ref, err := GetReference(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref.FieldPath = fieldPath
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
// IsAnAPIObject allows clients to preemptively get a reference to an API object and pass it to places that
|
||||
// intend only to get a reference to that object. This simplifies the event recording interface.
|
||||
func (obj *ObjectReference) SetGroupVersionKind(gvk unversioned.GroupVersionKind) {
|
||||
obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
|
||||
}
|
||||
func (obj *ObjectReference) GroupVersionKind() unversioned.GroupVersionKind {
|
||||
return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
|
||||
}
|
||||
|
||||
func (obj *ObjectReference) GetObjectKind() unversioned.ObjectKind { return obj }
|
229
pkg/api/v1/resource_helpers.go
Normal file
229
pkg/api/v1/resource_helpers.go
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
Copyright 2014 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 v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
// Returns string version of ResourceName.
|
||||
func (self ResourceName) String() string {
|
||||
return string(self)
|
||||
}
|
||||
|
||||
// Returns the CPU limit if specified.
|
||||
func (self *ResourceList) Cpu() *resource.Quantity {
|
||||
if val, ok := (*self)[ResourceCPU]; ok {
|
||||
return &val
|
||||
}
|
||||
return &resource.Quantity{Format: resource.DecimalSI}
|
||||
}
|
||||
|
||||
// Returns the Memory limit if specified.
|
||||
func (self *ResourceList) Memory() *resource.Quantity {
|
||||
if val, ok := (*self)[ResourceMemory]; ok {
|
||||
return &val
|
||||
}
|
||||
return &resource.Quantity{Format: resource.BinarySI}
|
||||
}
|
||||
|
||||
func (self *ResourceList) Pods() *resource.Quantity {
|
||||
if val, ok := (*self)[ResourcePods]; ok {
|
||||
return &val
|
||||
}
|
||||
return &resource.Quantity{}
|
||||
}
|
||||
|
||||
func (self *ResourceList) NvidiaGPU() *resource.Quantity {
|
||||
if val, ok := (*self)[ResourceNvidiaGPU]; ok {
|
||||
return &val
|
||||
}
|
||||
return &resource.Quantity{}
|
||||
}
|
||||
|
||||
func GetContainerStatus(statuses []ContainerStatus, name string) (ContainerStatus, bool) {
|
||||
for i := range statuses {
|
||||
if statuses[i].Name == name {
|
||||
return statuses[i], true
|
||||
}
|
||||
}
|
||||
return ContainerStatus{}, false
|
||||
}
|
||||
|
||||
func GetExistingContainerStatus(statuses []ContainerStatus, name string) ContainerStatus {
|
||||
for i := range statuses {
|
||||
if statuses[i].Name == name {
|
||||
return statuses[i]
|
||||
}
|
||||
}
|
||||
return ContainerStatus{}
|
||||
}
|
||||
|
||||
// IsPodAvailable returns true if a pod is available; false otherwise.
|
||||
// Precondition for an available pod is that it must be ready. On top
|
||||
// of that, there are two cases when a pod can be considered available:
|
||||
// 1. minReadySeconds == 0, or
|
||||
// 2. LastTransitionTime (is set) + minReadySeconds < current time
|
||||
func IsPodAvailable(pod *Pod, minReadySeconds int32, now unversioned.Time) bool {
|
||||
if !IsPodReady(pod) {
|
||||
return false
|
||||
}
|
||||
|
||||
c := GetPodReadyCondition(pod.Status)
|
||||
minReadySecondsDuration := time.Duration(minReadySeconds) * time.Second
|
||||
if minReadySeconds == 0 || !c.LastTransitionTime.IsZero() && c.LastTransitionTime.Add(minReadySecondsDuration).Before(now.Time) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsPodReady returns true if a pod is ready; false otherwise.
|
||||
func IsPodReady(pod *Pod) bool {
|
||||
return IsPodReadyConditionTrue(pod.Status)
|
||||
}
|
||||
|
||||
// IsPodReady retruns true if a pod is ready; false otherwise.
|
||||
func IsPodReadyConditionTrue(status PodStatus) bool {
|
||||
condition := GetPodReadyCondition(status)
|
||||
return condition != nil && condition.Status == ConditionTrue
|
||||
}
|
||||
|
||||
// Extracts the pod ready condition from the given status and returns that.
|
||||
// Returns nil if the condition is not present.
|
||||
func GetPodReadyCondition(status PodStatus) *PodCondition {
|
||||
_, condition := GetPodCondition(&status, PodReady)
|
||||
return condition
|
||||
}
|
||||
|
||||
// GetPodCondition extracts the provided condition from the given status and returns that.
|
||||
// Returns nil and -1 if the condition is not present, and the index of the located condition.
|
||||
func GetPodCondition(status *PodStatus, conditionType PodConditionType) (int, *PodCondition) {
|
||||
if status == nil {
|
||||
return -1, nil
|
||||
}
|
||||
for i := range status.Conditions {
|
||||
if status.Conditions[i].Type == conditionType {
|
||||
return i, &status.Conditions[i]
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// GetNodeCondition extracts the provided condition from the given status and returns that.
|
||||
// Returns nil and -1 if the condition is not present, and the index of the located condition.
|
||||
func GetNodeCondition(status *NodeStatus, conditionType NodeConditionType) (int, *NodeCondition) {
|
||||
if status == nil {
|
||||
return -1, nil
|
||||
}
|
||||
for i := range status.Conditions {
|
||||
if status.Conditions[i].Type == conditionType {
|
||||
return i, &status.Conditions[i]
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// Updates existing pod condition or creates a new one. Sets LastTransitionTime to now if the
|
||||
// status has changed.
|
||||
// Returns true if pod condition has changed or has been added.
|
||||
func UpdatePodCondition(status *PodStatus, condition *PodCondition) bool {
|
||||
condition.LastTransitionTime = unversioned.Now()
|
||||
// Try to find this pod condition.
|
||||
conditionIndex, oldCondition := GetPodCondition(status, condition.Type)
|
||||
|
||||
if oldCondition == nil {
|
||||
// We are adding new pod condition.
|
||||
status.Conditions = append(status.Conditions, *condition)
|
||||
return true
|
||||
} else {
|
||||
// We are updating an existing condition, so we need to check if it has changed.
|
||||
if condition.Status == oldCondition.Status {
|
||||
condition.LastTransitionTime = oldCondition.LastTransitionTime
|
||||
}
|
||||
|
||||
isEqual := condition.Status == oldCondition.Status &&
|
||||
condition.Reason == oldCondition.Reason &&
|
||||
condition.Message == oldCondition.Message &&
|
||||
condition.LastProbeTime.Equal(oldCondition.LastProbeTime) &&
|
||||
condition.LastTransitionTime.Equal(oldCondition.LastTransitionTime)
|
||||
|
||||
status.Conditions[conditionIndex] = *condition
|
||||
// Return true if one of the fields have changed.
|
||||
return !isEqual
|
||||
}
|
||||
}
|
||||
|
||||
// IsNodeReady returns true if a node is ready; false otherwise.
|
||||
func IsNodeReady(node *Node) bool {
|
||||
for _, c := range node.Status.Conditions {
|
||||
if c.Type == NodeReady {
|
||||
return c.Status == ConditionTrue
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
|
||||
// containers of the pod.
|
||||
func PodRequestsAndLimits(pod *Pod) (reqs map[ResourceName]resource.Quantity, limits map[ResourceName]resource.Quantity, err error) {
|
||||
reqs, limits = map[ResourceName]resource.Quantity{}, map[ResourceName]resource.Quantity{}
|
||||
for _, container := range pod.Spec.Containers {
|
||||
for name, quantity := range container.Resources.Requests {
|
||||
if value, ok := reqs[name]; !ok {
|
||||
reqs[name] = *quantity.Copy()
|
||||
} else {
|
||||
value.Add(quantity)
|
||||
reqs[name] = value
|
||||
}
|
||||
}
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
if value, ok := limits[name]; !ok {
|
||||
limits[name] = *quantity.Copy()
|
||||
} else {
|
||||
value.Add(quantity)
|
||||
limits[name] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
// init containers define the minimum of any resource
|
||||
for _, container := range pod.Spec.InitContainers {
|
||||
for name, quantity := range container.Resources.Requests {
|
||||
value, ok := reqs[name]
|
||||
if !ok {
|
||||
reqs[name] = *quantity.Copy()
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(value) > 0 {
|
||||
reqs[name] = *quantity.Copy()
|
||||
}
|
||||
}
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
value, ok := limits[name]
|
||||
if !ok {
|
||||
limits[name] = *quantity.Copy()
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(value) > 0 {
|
||||
limits[name] = *quantity.Copy()
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
120
pkg/api/v1/resource_helpers_test.go
Normal file
120
pkg/api/v1/resource_helpers_test.go
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2015 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 v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
func TestResourceHelpers(t *testing.T) {
|
||||
cpuLimit := resource.MustParse("10")
|
||||
memoryLimit := resource.MustParse("10G")
|
||||
resourceSpec := ResourceRequirements{
|
||||
Limits: ResourceList{
|
||||
"cpu": cpuLimit,
|
||||
"memory": memoryLimit,
|
||||
"kube.io/storage": memoryLimit,
|
||||
},
|
||||
}
|
||||
if res := resourceSpec.Limits.Cpu(); res.Cmp(cpuLimit) != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", cpuLimit, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
resourceSpec = ResourceRequirements{
|
||||
Limits: ResourceList{
|
||||
"memory": memoryLimit,
|
||||
"kube.io/storage": memoryLimit,
|
||||
},
|
||||
}
|
||||
if res := resourceSpec.Limits.Cpu(); res.Value() != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", 0, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultResourceHelpers(t *testing.T) {
|
||||
resourceList := ResourceList{}
|
||||
if resourceList.Cpu().Format != resource.DecimalSI {
|
||||
t.Errorf("expected %v, actual %v", resource.DecimalSI, resourceList.Cpu().Format)
|
||||
}
|
||||
if resourceList.Memory().Format != resource.BinarySI {
|
||||
t.Errorf("expected %v, actual %v", resource.BinarySI, resourceList.Memory().Format)
|
||||
}
|
||||
}
|
||||
|
||||
func newPod(now unversioned.Time, ready bool, beforeSec int) *Pod {
|
||||
conditionStatus := ConditionFalse
|
||||
if ready {
|
||||
conditionStatus = ConditionTrue
|
||||
}
|
||||
return &Pod{
|
||||
Status: PodStatus{
|
||||
Conditions: []PodCondition{
|
||||
{
|
||||
Type: PodReady,
|
||||
LastTransitionTime: unversioned.NewTime(now.Time.Add(-1 * time.Duration(beforeSec) * time.Second)),
|
||||
Status: conditionStatus,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsPodAvailable(t *testing.T) {
|
||||
now := unversioned.Now()
|
||||
tests := []struct {
|
||||
pod *Pod
|
||||
minReadySeconds int32
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
pod: newPod(now, false, 0),
|
||||
minReadySeconds: 0,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
pod: newPod(now, true, 0),
|
||||
minReadySeconds: 1,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
pod: newPod(now, true, 0),
|
||||
minReadySeconds: 0,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
pod: newPod(now, true, 51),
|
||||
minReadySeconds: 50,
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
isAvailable := IsPodAvailable(test.pod, test.minReadySeconds, now)
|
||||
if isAvailable != test.expected {
|
||||
t.Errorf("[tc #%d] expected available pod: %t, got: %t", i, test.expected, isAvailable)
|
||||
}
|
||||
}
|
||||
}
|
36
pkg/api/v1/service/BUILD
Normal file
36
pkg/api/v1/service/BUILD
Normal file
@ -0,0 +1,36 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"annotations.go",
|
||||
"util.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/net/sets:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/net/sets:go_default_library",
|
||||
],
|
||||
)
|
111
pkg/api/v1/service/annotations.go
Normal file
111
pkg/api/v1/service/annotations.go
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright 2016 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 service
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
// AnnotationLoadBalancerSourceRangesKey is the key of the annotation on a service to set allowed ingress ranges on their LoadBalancers
|
||||
//
|
||||
// It should be a comma-separated list of CIDRs, e.g. `0.0.0.0/0` to
|
||||
// allow full access (the default) or `18.0.0.0/8,56.0.0.0/8` to allow
|
||||
// access only from the CIDRs currently allocated to MIT & the USPS.
|
||||
//
|
||||
// Not all cloud providers support this annotation, though AWS & GCE do.
|
||||
AnnotationLoadBalancerSourceRangesKey = "service.beta.kubernetes.io/load-balancer-source-ranges"
|
||||
|
||||
// AnnotationValueExternalTrafficLocal Value of annotation to specify local endpoints behaviour
|
||||
AnnotationValueExternalTrafficLocal = "OnlyLocal"
|
||||
// AnnotationValueExternalTrafficGlobal Value of annotation to specify global (legacy) behaviour
|
||||
AnnotationValueExternalTrafficGlobal = "Global"
|
||||
|
||||
// TODO: The alpha annotations have been deprecated, remove them when we move this feature to GA.
|
||||
|
||||
// AlphaAnnotationHealthCheckNodePort Annotation specifying the healthcheck nodePort for the service
|
||||
// If not specified, annotation is created by the service api backend with the allocated nodePort
|
||||
// Will use user-specified nodePort value if specified by the client
|
||||
AlphaAnnotationHealthCheckNodePort = "service.alpha.kubernetes.io/healthcheck-nodeport"
|
||||
|
||||
// AlphaAnnotationExternalTraffic An annotation that denotes if this Service desires to route external traffic to local
|
||||
// endpoints only. This preserves Source IP and avoids a second hop.
|
||||
AlphaAnnotationExternalTraffic = "service.alpha.kubernetes.io/external-traffic"
|
||||
|
||||
// BetaAnnotationHealthCheckNodePort is the beta version of AlphaAnnotationHealthCheckNodePort.
|
||||
BetaAnnotationHealthCheckNodePort = "service.beta.kubernetes.io/healthcheck-nodeport"
|
||||
|
||||
// BetaAnnotationExternalTraffic is the beta version of AlphaAnnotationExternalTraffic.
|
||||
BetaAnnotationExternalTraffic = "service.beta.kubernetes.io/external-traffic"
|
||||
)
|
||||
|
||||
// NeedsHealthCheck Check service for health check annotations
|
||||
func NeedsHealthCheck(service *v1.Service) bool {
|
||||
// First check the alpha annotation and then the beta. This is so existing
|
||||
// Services continue to work till the user decides to transition to beta.
|
||||
// If they transition to beta, there's no way to go back to alpha without
|
||||
// rolling back the cluster.
|
||||
for _, annotation := range []string{AlphaAnnotationExternalTraffic, BetaAnnotationExternalTraffic} {
|
||||
if l, ok := service.Annotations[annotation]; ok {
|
||||
if l == AnnotationValueExternalTrafficLocal {
|
||||
return true
|
||||
} else if l == AnnotationValueExternalTrafficGlobal {
|
||||
return false
|
||||
} else {
|
||||
glog.Errorf("Invalid value for annotation %v: %v", annotation, l)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetServiceHealthCheckNodePort Return health check node port annotation for service, if one exists
|
||||
func GetServiceHealthCheckNodePort(service *v1.Service) int32 {
|
||||
if !NeedsHealthCheck(service) {
|
||||
return 0
|
||||
}
|
||||
// First check the alpha annotation and then the beta. This is so existing
|
||||
// Services continue to work till the user decides to transition to beta.
|
||||
// If they transition to beta, there's no way to go back to alpha without
|
||||
// rolling back the cluster.
|
||||
for _, annotation := range []string{AlphaAnnotationHealthCheckNodePort, BetaAnnotationHealthCheckNodePort} {
|
||||
if l, ok := service.Annotations[annotation]; ok {
|
||||
p, err := strconv.Atoi(l)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to parse annotation %v: %v", annotation, err)
|
||||
continue
|
||||
}
|
||||
return int32(p)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetServiceHealthCheckPathPort Return the path and nodePort programmed into the Cloud LB Health Check
|
||||
func GetServiceHealthCheckPathPort(service *v1.Service) (string, int32) {
|
||||
if !NeedsHealthCheck(service) {
|
||||
return "", 0
|
||||
}
|
||||
port := GetServiceHealthCheckNodePort(service)
|
||||
if port == 0 {
|
||||
return "", 0
|
||||
}
|
||||
return "/healthz", port
|
||||
}
|
68
pkg/api/v1/service/util.go
Normal file
68
pkg/api/v1/service/util.go
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2016 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 service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
netsets "k8s.io/kubernetes/pkg/util/net/sets"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultLoadBalancerSourceRanges = "0.0.0.0/0"
|
||||
)
|
||||
|
||||
// IsAllowAll checks whether the netsets.IPNet allows traffic from 0.0.0.0/0
|
||||
func IsAllowAll(ipnets netsets.IPNet) bool {
|
||||
for _, s := range ipnets.StringSlice() {
|
||||
if s == "0.0.0.0/0" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetLoadBalancerSourceRanges first try to parse and verify LoadBalancerSourceRanges field from a service.
|
||||
// If the field is not specified, turn to parse and verify the AnnotationLoadBalancerSourceRangesKey annotation from a service,
|
||||
// extracting the source ranges to allow, and if not present returns a default (allow-all) value.
|
||||
func GetLoadBalancerSourceRanges(service *v1.Service) (netsets.IPNet, error) {
|
||||
var ipnets netsets.IPNet
|
||||
var err error
|
||||
// if SourceRange field is specified, ignore sourceRange annotation
|
||||
if len(service.Spec.LoadBalancerSourceRanges) > 0 {
|
||||
specs := service.Spec.LoadBalancerSourceRanges
|
||||
ipnets, err = netsets.ParseIPNets(specs...)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("service.Spec.LoadBalancerSourceRanges: %v is not valid. Expecting a list of IP ranges. For example, 10.0.0.0/24. Error msg: %v", specs, err)
|
||||
}
|
||||
} else {
|
||||
val := service.Annotations[AnnotationLoadBalancerSourceRangesKey]
|
||||
val = strings.TrimSpace(val)
|
||||
if val == "" {
|
||||
val = defaultLoadBalancerSourceRanges
|
||||
}
|
||||
specs := strings.Split(val, ",")
|
||||
ipnets, err = netsets.ParseIPNets(specs...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s is not valid. Expecting a comma-separated list of source IP ranges. For example, 10.0.0.0/24,192.168.2.0/24", AnnotationLoadBalancerSourceRangesKey, val)
|
||||
}
|
||||
}
|
||||
return ipnets, nil
|
||||
}
|
131
pkg/api/v1/service/util_test.go
Normal file
131
pkg/api/v1/service/util_test.go
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright 2016 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 service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
netsets "k8s.io/kubernetes/pkg/util/net/sets"
|
||||
)
|
||||
|
||||
func TestGetLoadBalancerSourceRanges(t *testing.T) {
|
||||
checkError := func(v string) {
|
||||
annotations := make(map[string]string)
|
||||
annotations[AnnotationLoadBalancerSourceRangesKey] = v
|
||||
svc := v1.Service{}
|
||||
svc.Annotations = annotations
|
||||
_, err := GetLoadBalancerSourceRanges(&svc)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error parsing: %q", v)
|
||||
}
|
||||
svc = v1.Service{}
|
||||
svc.Spec.LoadBalancerSourceRanges = strings.Split(v, ",")
|
||||
_, err = GetLoadBalancerSourceRanges(&svc)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error parsing: %q", v)
|
||||
}
|
||||
}
|
||||
checkError("10.0.0.1/33")
|
||||
checkError("foo.bar")
|
||||
checkError("10.0.0.1/32,*")
|
||||
checkError("10.0.0.1/32,")
|
||||
checkError("10.0.0.1/32, ")
|
||||
checkError("10.0.0.1")
|
||||
|
||||
checkOK := func(v string) netsets.IPNet {
|
||||
annotations := make(map[string]string)
|
||||
annotations[AnnotationLoadBalancerSourceRangesKey] = v
|
||||
svc := v1.Service{}
|
||||
svc.Annotations = annotations
|
||||
cidrs, err := GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error parsing: %q", v)
|
||||
}
|
||||
svc = v1.Service{}
|
||||
svc.Spec.LoadBalancerSourceRanges = strings.Split(v, ",")
|
||||
cidrs, err = GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error parsing: %q", v)
|
||||
}
|
||||
return cidrs
|
||||
}
|
||||
cidrs := checkOK("192.168.0.1/32")
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
|
||||
}
|
||||
cidrs = checkOK("192.168.0.1/32,192.168.0.1/32")
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR (after de-dup): %v", cidrs.StringSlice())
|
||||
}
|
||||
cidrs = checkOK("192.168.0.1/32,192.168.0.2/32")
|
||||
if len(cidrs) != 2 {
|
||||
t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice())
|
||||
}
|
||||
cidrs = checkOK(" 192.168.0.1/32 , 192.168.0.2/32 ")
|
||||
if len(cidrs) != 2 {
|
||||
t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice())
|
||||
}
|
||||
// check LoadBalancerSourceRanges not specified
|
||||
svc := v1.Service{}
|
||||
cidrs, err := GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
|
||||
}
|
||||
if !IsAllowAll(cidrs) {
|
||||
t.Errorf("Expected default to be allow-all: %v", cidrs.StringSlice())
|
||||
}
|
||||
// check SourceRanges annotation is empty
|
||||
annotations := make(map[string]string)
|
||||
annotations[AnnotationLoadBalancerSourceRangesKey] = ""
|
||||
svc = v1.Service{}
|
||||
svc.Annotations = annotations
|
||||
cidrs, err = GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
|
||||
}
|
||||
if !IsAllowAll(cidrs) {
|
||||
t.Errorf("Expected default to be allow-all: %v", cidrs.StringSlice())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllowAll(t *testing.T) {
|
||||
checkAllowAll := func(allowAll bool, cidrs ...string) {
|
||||
ipnets, err := netsets.ParseIPNets(cidrs...)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error parsing cidrs: %v", cidrs)
|
||||
}
|
||||
if allowAll != IsAllowAll(ipnets) {
|
||||
t.Errorf("IsAllowAll did not return expected value for %v", cidrs)
|
||||
}
|
||||
}
|
||||
checkAllowAll(false, "10.0.0.1/32")
|
||||
checkAllowAll(false, "10.0.0.1/32", "10.0.0.2/32")
|
||||
checkAllowAll(false, "10.0.0.1/32", "10.0.0.1/32")
|
||||
|
||||
checkAllowAll(true, "0.0.0.0/0")
|
||||
checkAllowAll(true, "192.168.0.0/0")
|
||||
checkAllowAll(true, "192.168.0.1/32", "0.0.0.0/0")
|
||||
}
|
@ -2995,6 +2995,8 @@ const (
|
||||
NodeDiskPressure NodeConditionType = "DiskPressure"
|
||||
// NodeNetworkUnavailable means that network for the node is not correctly configured.
|
||||
NodeNetworkUnavailable NodeConditionType = "NetworkUnavailable"
|
||||
// NodeInodePressure means the kublet is under pressure due to insufficient available inodes.
|
||||
NodeInodePressure NodeConditionType = "InodePressure"
|
||||
)
|
||||
|
||||
// NodeCondition contains condition information for a node.
|
||||
@ -3056,6 +3058,11 @@ const (
|
||||
// Number of Pods that may be running on this Node: see ResourcePods
|
||||
)
|
||||
|
||||
const (
|
||||
// Namespace prefix for opaque counted resources (alpha).
|
||||
ResourceOpaqueIntPrefix = "pod.alpha.kubernetes.io/opaque-int-resource-"
|
||||
)
|
||||
|
||||
// ResourceList is a set of (resource name, quantity) pairs.
|
||||
type ResourceList map[ResourceName]resource.Quantity
|
||||
|
||||
@ -3790,6 +3797,35 @@ const (
|
||||
// DockerConfigKey is the key of the required data for SecretTypeDockercfg secrets
|
||||
DockerConfigKey = ".dockercfg"
|
||||
|
||||
// SecretTypeDockerConfigJson contains a dockercfg file that follows the same format rules as ~/.docker/config.json
|
||||
//
|
||||
// Required fields:
|
||||
// - Secret.Data[".dockerconfigjson"] - a serialized ~/.docker/config.json file
|
||||
SecretTypeDockerConfigJson SecretType = "kubernetes.io/dockerconfigjson"
|
||||
|
||||
// DockerConfigJsonKey is the key of the required data for SecretTypeDockerConfigJson secrets
|
||||
DockerConfigJsonKey = ".dockerconfigjson"
|
||||
|
||||
// SecretTypeBasicAuth contains data needed for basic authentication.
|
||||
//
|
||||
// Required at least one of fields:
|
||||
// - Secret.Data["username"] - username used for authentication
|
||||
// - Secret.Data["password"] - password or token needed for authentication
|
||||
SecretTypeBasicAuth SecretType = "kubernetes.io/basic-auth"
|
||||
|
||||
// BasicAuthUsernameKey is the key of the username for SecretTypeBasicAuth secrets
|
||||
BasicAuthUsernameKey = "username"
|
||||
// BasicAuthPasswordKey is the key of the password or token for SecretTypeBasicAuth secrets
|
||||
BasicAuthPasswordKey = "password"
|
||||
|
||||
// SecretTypeSSHAuth contains data needed for SSH authetication.
|
||||
//
|
||||
// Required field:
|
||||
// - Secret.Data["ssh-privatekey"] - private SSH key needed for authentication
|
||||
SecretTypeSSHAuth SecretType = "kubernetes.io/ssh-auth"
|
||||
|
||||
// SSHAuthPrivateKey is the key of the required SSH private key for SecretTypeSSHAuth secrets
|
||||
SSHAuthPrivateKey = "ssh-privatekey"
|
||||
// SecretTypeTLS contains information about a TLS client or server secret. It
|
||||
// is primarily used with TLS termination of the Ingress resource, but may be
|
||||
// used in other types.
|
||||
@ -4011,4 +4047,14 @@ type RangeAllocation struct {
|
||||
const (
|
||||
// "default-scheduler" is the name of default scheduler.
|
||||
DefaultSchedulerName = "default-scheduler"
|
||||
|
||||
// RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule
|
||||
// corresponding to every RequiredDuringScheduling affinity rule.
|
||||
// When the --hard-pod-affinity-weight scheduler flag is not specified,
|
||||
// DefaultHardPodAffinityWeight defines the weight of the implicit PreferredDuringScheduling affinity rule.
|
||||
DefaultHardPodAffinitySymmetricWeight int = 1
|
||||
|
||||
// When the --failure-domains scheduler flag is not specified,
|
||||
// DefaultFailureDomains defines the set of label keys used when TopologyKey is empty in PreferredDuringScheduling anti-affinity.
|
||||
DefaultFailureDomains string = unversioned.LabelHostname + "," + unversioned.LabelZoneFailureDomain + "," + unversioned.LabelZoneRegion
|
||||
)
|
||||
|
25
pkg/api/v1/validation/BUILD
Normal file
25
pkg/api/v1/validation/BUILD
Normal file
@ -0,0 +1,25 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["validation.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/sets:go_default_library",
|
||||
"//pkg/util/validation:go_default_library",
|
||||
"//pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
159
pkg/api/v1/validation/validation.go
Normal file
159
pkg/api/v1/validation/validation.go
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
Copyright 2014 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 validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/util/validation"
|
||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
const isNegativeErrorMsg string = `must be greater than or equal to 0`
|
||||
const isNotIntegerErrorMsg string = `must be an integer`
|
||||
|
||||
func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
limPath := fldPath.Child("limits")
|
||||
reqPath := fldPath.Child("requests")
|
||||
for resourceName, quantity := range requirements.Limits {
|
||||
fldPath := limPath.Key(string(resourceName))
|
||||
// Validate resource name.
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
|
||||
|
||||
// Validate resource quantity.
|
||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
||||
|
||||
// Check that request <= limit.
|
||||
requestQuantity, exists := requirements.Requests[resourceName]
|
||||
if exists {
|
||||
// For GPUs, not only requests can't exceed limits, they also can't be lower, i.e. must be equal.
|
||||
if resourceName == v1.ResourceNvidiaGPU && quantity.Cmp(requestQuantity) != 0 {
|
||||
allErrs = append(allErrs, field.Invalid(reqPath, requestQuantity.String(), fmt.Sprintf("must be equal to %s limit", v1.ResourceNvidiaGPU)))
|
||||
} else if quantity.Cmp(requestQuantity) < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(limPath, quantity.String(), fmt.Sprintf("must be greater than or equal to %s request", resourceName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
for resourceName, quantity := range requirements.Requests {
|
||||
fldPath := reqPath.Key(string(resourceName))
|
||||
// Validate resource name.
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
|
||||
// Validate resource quantity.
|
||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateResourceName(value, fldPath)
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardContainerResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
|
||||
}
|
||||
}
|
||||
return field.ErrorList{}
|
||||
}
|
||||
|
||||
// ValidateResourceQuantityValue enforces that specified quantity is valid for specified resource
|
||||
func ValidateResourceQuantityValue(resource string, value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateNonnegativeQuantity(value, fldPath)...)
|
||||
if api.IsIntegerResourceName(resource) {
|
||||
if value.MilliValue()%int64(1000) != int64(0) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, isNotIntegerErrorMsg))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// Validates that a Quantity is not negative
|
||||
func ValidateNonnegativeQuantity(value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if value.Cmp(resource.Quantity{}) < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value.String(), isNegativeErrorMsg))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// Validate compute resource typename.
|
||||
// Refer to docs/design/resources.md for more details.
|
||||
func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, msg := range validation.IsQualifiedName(value) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, msg))
|
||||
}
|
||||
if len(allErrs) != 0 {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified"))
|
||||
}
|
||||
}
|
||||
|
||||
return field.ErrorList{}
|
||||
}
|
||||
|
||||
func ValidatePodLogOptions(opts *v1.PodLogOptions) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if opts.TailLines != nil && *opts.TailLines < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("tailLines"), *opts.TailLines, isNegativeErrorMsg))
|
||||
}
|
||||
if opts.LimitBytes != nil && *opts.LimitBytes < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("limitBytes"), *opts.LimitBytes, "must be greater than 0"))
|
||||
}
|
||||
switch {
|
||||
case opts.SinceSeconds != nil && opts.SinceTime != nil:
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath(""), "at most one of `sinceTime` or `sinceSeconds` may be specified"))
|
||||
case opts.SinceSeconds != nil:
|
||||
if *opts.SinceSeconds < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("sinceSeconds"), *opts.SinceSeconds, "must be greater than 0"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func AccumulateUniqueHostPorts(containers []v1.Container, accumulator *sets.String, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
for ci, ctr := range containers {
|
||||
idxPath := fldPath.Index(ci)
|
||||
portsPath := idxPath.Child("ports")
|
||||
for pi := range ctr.Ports {
|
||||
idxPath := portsPath.Index(pi)
|
||||
port := ctr.Ports[pi].HostPort
|
||||
if port == 0 {
|
||||
continue
|
||||
}
|
||||
str := fmt.Sprintf("%d/%s", port, ctr.Ports[pi].Protocol)
|
||||
if accumulator.Has(str) {
|
||||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("hostPort"), str))
|
||||
} else {
|
||||
accumulator.Insert(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
@ -189,6 +189,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
Convert_api_NodeList_To_v1_NodeList,
|
||||
Convert_v1_NodeProxyOptions_To_api_NodeProxyOptions,
|
||||
Convert_api_NodeProxyOptions_To_v1_NodeProxyOptions,
|
||||
Convert_v1_NodeResources_To_api_NodeResources,
|
||||
Convert_api_NodeResources_To_v1_NodeResources,
|
||||
Convert_v1_NodeSelector_To_api_NodeSelector,
|
||||
Convert_api_NodeSelector_To_v1_NodeSelector,
|
||||
Convert_v1_NodeSelectorRequirement_To_api_NodeSelectorRequirement,
|
||||
@ -333,6 +335,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
Convert_api_ServiceSpec_To_v1_ServiceSpec,
|
||||
Convert_v1_ServiceStatus_To_api_ServiceStatus,
|
||||
Convert_api_ServiceStatus_To_v1_ServiceStatus,
|
||||
Convert_v1_Sysctl_To_api_Sysctl,
|
||||
Convert_api_Sysctl_To_v1_Sysctl,
|
||||
Convert_v1_TCPSocketAction_To_api_TCPSocketAction,
|
||||
Convert_api_TCPSocketAction_To_v1_TCPSocketAction,
|
||||
Convert_v1_Taint_To_api_Taint,
|
||||
@ -2152,6 +2156,24 @@ func Convert_api_NodeProxyOptions_To_v1_NodeProxyOptions(in *api.NodeProxyOption
|
||||
return autoConvert_api_NodeProxyOptions_To_v1_NodeProxyOptions(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_NodeResources_To_api_NodeResources(in *NodeResources, out *api.NodeResources, s conversion.Scope) error {
|
||||
out.Capacity = *(*api.ResourceList)(unsafe.Pointer(&in.Capacity))
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_NodeResources_To_api_NodeResources(in *NodeResources, out *api.NodeResources, s conversion.Scope) error {
|
||||
return autoConvert_v1_NodeResources_To_api_NodeResources(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_api_NodeResources_To_v1_NodeResources(in *api.NodeResources, out *NodeResources, s conversion.Scope) error {
|
||||
out.Capacity = *(*ResourceList)(unsafe.Pointer(&in.Capacity))
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_api_NodeResources_To_v1_NodeResources(in *api.NodeResources, out *NodeResources, s conversion.Scope) error {
|
||||
return autoConvert_api_NodeResources_To_v1_NodeResources(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_NodeSelector_To_api_NodeSelector(in *NodeSelector, out *api.NodeSelector, s conversion.Scope) error {
|
||||
out.NodeSelectorTerms = *(*[]api.NodeSelectorTerm)(unsafe.Pointer(&in.NodeSelectorTerms))
|
||||
return nil
|
||||
@ -4155,6 +4177,26 @@ func Convert_api_ServiceStatus_To_v1_ServiceStatus(in *api.ServiceStatus, out *S
|
||||
return autoConvert_api_ServiceStatus_To_v1_ServiceStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_Sysctl_To_api_Sysctl(in *Sysctl, out *api.Sysctl, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Value = in.Value
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_Sysctl_To_api_Sysctl(in *Sysctl, out *api.Sysctl, s conversion.Scope) error {
|
||||
return autoConvert_v1_Sysctl_To_api_Sysctl(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_api_Sysctl_To_v1_Sysctl(in *api.Sysctl, out *Sysctl, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Value = in.Value
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_api_Sysctl_To_v1_Sysctl(in *api.Sysctl, out *Sysctl, s conversion.Scope) error {
|
||||
return autoConvert_api_Sysctl_To_v1_Sysctl(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_TCPSocketAction_To_api_TCPSocketAction(in *TCPSocketAction, out *api.TCPSocketAction, s conversion.Scope) error {
|
||||
out.Port = in.Port
|
||||
return nil
|
||||
|
@ -112,6 +112,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_NodeDaemonEndpoints, InType: reflect.TypeOf(&NodeDaemonEndpoints{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_NodeList, InType: reflect.TypeOf(&NodeList{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_NodeProxyOptions, InType: reflect.TypeOf(&NodeProxyOptions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_NodeResources, InType: reflect.TypeOf(&NodeResources{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_NodeSelector, InType: reflect.TypeOf(&NodeSelector{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_NodeSelectorRequirement, InType: reflect.TypeOf(&NodeSelectorRequirement{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_NodeSelectorTerm, InType: reflect.TypeOf(&NodeSelectorTerm{})},
|
||||
@ -184,6 +185,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ServiceProxyOptions, InType: reflect.TypeOf(&ServiceProxyOptions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ServiceSpec, InType: reflect.TypeOf(&ServiceSpec{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ServiceStatus, InType: reflect.TypeOf(&ServiceStatus{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Sysctl, InType: reflect.TypeOf(&Sysctl{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_TCPSocketAction, InType: reflect.TypeOf(&TCPSocketAction{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Taint, InType: reflect.TypeOf(&Taint{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Toleration, InType: reflect.TypeOf(&Toleration{})},
|
||||
@ -1689,6 +1691,23 @@ func DeepCopy_v1_NodeProxyOptions(in interface{}, out interface{}, c *conversion
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_NodeResources(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*NodeResources)
|
||||
out := out.(*NodeResources)
|
||||
if in.Capacity != nil {
|
||||
in, out := &in.Capacity, &out.Capacity
|
||||
*out = make(ResourceList)
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val.DeepCopy()
|
||||
}
|
||||
} else {
|
||||
out.Capacity = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_NodeSelector(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*NodeSelector)
|
||||
@ -3494,6 +3513,16 @@ func DeepCopy_v1_ServiceStatus(in interface{}, out interface{}, c *conversion.Cl
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_Sysctl(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*Sysctl)
|
||||
out := out.(*Sysctl)
|
||||
out.Name = in.Name
|
||||
out.Value = in.Value
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1_TCPSocketAction(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*TCPSocketAction)
|
||||
|
@ -16,6 +16,7 @@ go_library(
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"generated.pb.go",
|
||||
"helpers.go",
|
||||
"register.go",
|
||||
"types.generated.go",
|
||||
"types.go",
|
||||
|
@ -27,9 +27,11 @@ limitations under the License.
|
||||
It has these top-level messages:
|
||||
ClusterRole
|
||||
ClusterRoleBinding
|
||||
ClusterRoleBindingBuilder
|
||||
ClusterRoleBindingList
|
||||
ClusterRoleList
|
||||
PolicyRule
|
||||
PolicyRuleBuilder
|
||||
Role
|
||||
RoleBinding
|
||||
RoleBindingList
|
||||
@ -65,48 +67,60 @@ func (m *ClusterRoleBinding) Reset() { *m = ClusterRoleBindin
|
||||
func (*ClusterRoleBinding) ProtoMessage() {}
|
||||
func (*ClusterRoleBinding) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} }
|
||||
|
||||
func (m *ClusterRoleBindingBuilder) Reset() { *m = ClusterRoleBindingBuilder{} }
|
||||
func (*ClusterRoleBindingBuilder) ProtoMessage() {}
|
||||
func (*ClusterRoleBindingBuilder) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptorGenerated, []int{2}
|
||||
}
|
||||
|
||||
func (m *ClusterRoleBindingList) Reset() { *m = ClusterRoleBindingList{} }
|
||||
func (*ClusterRoleBindingList) ProtoMessage() {}
|
||||
func (*ClusterRoleBindingList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} }
|
||||
func (*ClusterRoleBindingList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} }
|
||||
|
||||
func (m *ClusterRoleList) Reset() { *m = ClusterRoleList{} }
|
||||
func (*ClusterRoleList) ProtoMessage() {}
|
||||
func (*ClusterRoleList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} }
|
||||
func (*ClusterRoleList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} }
|
||||
|
||||
func (m *PolicyRule) Reset() { *m = PolicyRule{} }
|
||||
func (*PolicyRule) ProtoMessage() {}
|
||||
func (*PolicyRule) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} }
|
||||
func (*PolicyRule) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} }
|
||||
|
||||
func (m *PolicyRuleBuilder) Reset() { *m = PolicyRuleBuilder{} }
|
||||
func (*PolicyRuleBuilder) ProtoMessage() {}
|
||||
func (*PolicyRuleBuilder) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{6} }
|
||||
|
||||
func (m *Role) Reset() { *m = Role{} }
|
||||
func (*Role) ProtoMessage() {}
|
||||
func (*Role) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} }
|
||||
func (*Role) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{7} }
|
||||
|
||||
func (m *RoleBinding) Reset() { *m = RoleBinding{} }
|
||||
func (*RoleBinding) ProtoMessage() {}
|
||||
func (*RoleBinding) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{6} }
|
||||
func (*RoleBinding) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} }
|
||||
|
||||
func (m *RoleBindingList) Reset() { *m = RoleBindingList{} }
|
||||
func (*RoleBindingList) ProtoMessage() {}
|
||||
func (*RoleBindingList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{7} }
|
||||
func (*RoleBindingList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} }
|
||||
|
||||
func (m *RoleList) Reset() { *m = RoleList{} }
|
||||
func (*RoleList) ProtoMessage() {}
|
||||
func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} }
|
||||
func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} }
|
||||
|
||||
func (m *RoleRef) Reset() { *m = RoleRef{} }
|
||||
func (*RoleRef) ProtoMessage() {}
|
||||
func (*RoleRef) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} }
|
||||
func (*RoleRef) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} }
|
||||
|
||||
func (m *Subject) Reset() { *m = Subject{} }
|
||||
func (*Subject) ProtoMessage() {}
|
||||
func (*Subject) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} }
|
||||
func (*Subject) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*ClusterRole)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.ClusterRole")
|
||||
proto.RegisterType((*ClusterRoleBinding)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.ClusterRoleBinding")
|
||||
proto.RegisterType((*ClusterRoleBindingBuilder)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.ClusterRoleBindingBuilder")
|
||||
proto.RegisterType((*ClusterRoleBindingList)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.ClusterRoleBindingList")
|
||||
proto.RegisterType((*ClusterRoleList)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.ClusterRoleList")
|
||||
proto.RegisterType((*PolicyRule)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.PolicyRule")
|
||||
proto.RegisterType((*PolicyRuleBuilder)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.PolicyRuleBuilder")
|
||||
proto.RegisterType((*Role)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.Role")
|
||||
proto.RegisterType((*RoleBinding)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.RoleBinding")
|
||||
proto.RegisterType((*RoleBindingList)(nil), "k8s.io.kubernetes.pkg.apis.rbac.v1alpha1.RoleBindingList")
|
||||
@ -198,6 +212,32 @@ func (m *ClusterRoleBinding) MarshalTo(data []byte) (int, error) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *ClusterRoleBindingBuilder) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *ClusterRoleBindingBuilder) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.ClusterRoleBinding.Size()))
|
||||
n4, err := m.ClusterRoleBinding.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n4
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *ClusterRoleBindingList) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
@ -216,11 +256,11 @@ func (m *ClusterRoleBindingList) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size()))
|
||||
n4, err := m.ListMeta.MarshalTo(data[i:])
|
||||
n5, err := m.ListMeta.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n4
|
||||
i += n5
|
||||
if len(m.Items) > 0 {
|
||||
for _, msg := range m.Items {
|
||||
data[i] = 0x12
|
||||
@ -254,11 +294,11 @@ func (m *ClusterRoleList) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size()))
|
||||
n5, err := m.ListMeta.MarshalTo(data[i:])
|
||||
n6, err := m.ListMeta.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n5
|
||||
i += n6
|
||||
if len(m.Items) > 0 {
|
||||
for _, msg := range m.Items {
|
||||
data[i] = 0x12
|
||||
@ -307,11 +347,11 @@ func (m *PolicyRule) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.AttributeRestrictions.Size()))
|
||||
n6, err := m.AttributeRestrictions.MarshalTo(data[i:])
|
||||
n7, err := m.AttributeRestrictions.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n6
|
||||
i += n7
|
||||
if len(m.APIGroups) > 0 {
|
||||
for _, s := range m.APIGroups {
|
||||
data[i] = 0x1a
|
||||
@ -375,6 +415,32 @@ func (m *PolicyRule) MarshalTo(data []byte) (int, error) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *PolicyRuleBuilder) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *PolicyRuleBuilder) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.PolicyRule.Size()))
|
||||
n8, err := m.PolicyRule.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n8
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *Role) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
@ -393,11 +459,11 @@ func (m *Role) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size()))
|
||||
n7, err := m.ObjectMeta.MarshalTo(data[i:])
|
||||
n9, err := m.ObjectMeta.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n7
|
||||
i += n9
|
||||
if len(m.Rules) > 0 {
|
||||
for _, msg := range m.Rules {
|
||||
data[i] = 0x12
|
||||
@ -431,11 +497,11 @@ func (m *RoleBinding) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.ObjectMeta.Size()))
|
||||
n8, err := m.ObjectMeta.MarshalTo(data[i:])
|
||||
n10, err := m.ObjectMeta.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n8
|
||||
i += n10
|
||||
if len(m.Subjects) > 0 {
|
||||
for _, msg := range m.Subjects {
|
||||
data[i] = 0x12
|
||||
@ -451,11 +517,11 @@ func (m *RoleBinding) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.RoleRef.Size()))
|
||||
n9, err := m.RoleRef.MarshalTo(data[i:])
|
||||
n11, err := m.RoleRef.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n9
|
||||
i += n11
|
||||
return i, nil
|
||||
}
|
||||
|
||||
@ -477,11 +543,11 @@ func (m *RoleBindingList) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size()))
|
||||
n10, err := m.ListMeta.MarshalTo(data[i:])
|
||||
n12, err := m.ListMeta.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n10
|
||||
i += n12
|
||||
if len(m.Items) > 0 {
|
||||
for _, msg := range m.Items {
|
||||
data[i] = 0x12
|
||||
@ -515,11 +581,11 @@ func (m *RoleList) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size()))
|
||||
n11, err := m.ListMeta.MarshalTo(data[i:])
|
||||
n13, err := m.ListMeta.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n11
|
||||
i += n13
|
||||
if len(m.Items) > 0 {
|
||||
for _, msg := range m.Items {
|
||||
data[i] = 0x12
|
||||
@ -656,6 +722,14 @@ func (m *ClusterRoleBinding) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *ClusterRoleBindingBuilder) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = m.ClusterRoleBinding.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *ClusterRoleBindingList) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
@ -722,6 +796,14 @@ func (m *PolicyRule) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PolicyRuleBuilder) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = m.PolicyRule.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Role) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
@ -842,6 +924,16 @@ func (this *ClusterRoleBinding) String() string {
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *ClusterRoleBindingBuilder) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&ClusterRoleBindingBuilder{`,
|
||||
`ClusterRoleBinding:` + strings.Replace(strings.Replace(this.ClusterRoleBinding.String(), "ClusterRoleBinding", "ClusterRoleBinding", 1), `&`, ``, 1) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *ClusterRoleBindingList) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
@ -879,6 +971,16 @@ func (this *PolicyRule) String() string {
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *PolicyRuleBuilder) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&PolicyRuleBuilder{`,
|
||||
`PolicyRule:` + strings.Replace(strings.Replace(this.PolicyRule.String(), "PolicyRule", "PolicyRule", 1), `&`, ``, 1) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *Role) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
@ -1209,6 +1311,86 @@ func (m *ClusterRoleBinding) Unmarshal(data []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ClusterRoleBindingBuilder) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ClusterRoleBindingBuilder: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ClusterRoleBindingBuilder: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ClusterRoleBinding", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.ClusterRoleBinding.Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ClusterRoleBindingList) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
@ -1656,6 +1838,86 @@ func (m *PolicyRule) Unmarshal(data []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PolicyRuleBuilder) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PolicyRuleBuilder: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PolicyRuleBuilder: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PolicyRule", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.PolicyRule.Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Role) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
@ -2539,56 +2801,60 @@ var (
|
||||
)
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 815 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xec, 0x54, 0x41, 0x6b, 0xe3, 0x46,
|
||||
0x18, 0xb5, 0x62, 0xbb, 0xb1, 0xc6, 0x35, 0x6e, 0x54, 0x52, 0x84, 0xa1, 0xb2, 0xf1, 0xc9, 0x34,
|
||||
0xc9, 0x08, 0x9b, 0x86, 0xe6, 0xd0, 0x1e, 0xa2, 0x52, 0x4a, 0x68, 0x9a, 0x86, 0x09, 0x0d, 0x6d,
|
||||
0x68, 0x29, 0x63, 0x7b, 0xe2, 0x4c, 0x2d, 0x4b, 0x62, 0x66, 0xe4, 0xb6, 0xf4, 0x12, 0xf6, 0x17,
|
||||
0xec, 0xaf, 0xd8, 0xdb, 0x5e, 0xf6, 0xba, 0xb0, 0x87, 0x3d, 0xe5, 0xb0, 0x87, 0x1c, 0x97, 0x3d,
|
||||
0x98, 0x8d, 0xf6, 0x8f, 0x2c, 0x1a, 0x49, 0x96, 0x1d, 0xdb, 0x1b, 0x27, 0xb0, 0x81, 0x85, 0x3d,
|
||||
0x25, 0xf3, 0x7d, 0xef, 0xbd, 0xf9, 0xde, 0xe7, 0xd1, 0x03, 0x3b, 0xfd, 0x1d, 0x0e, 0xa9, 0x6b,
|
||||
0xf6, 0xfd, 0x36, 0x61, 0x0e, 0x11, 0x84, 0x9b, 0x5e, 0xbf, 0x67, 0x62, 0x8f, 0x72, 0x93, 0xb5,
|
||||
0x71, 0xc7, 0x1c, 0x36, 0xb1, 0xed, 0x9d, 0xe1, 0xa6, 0xd9, 0x23, 0x0e, 0x61, 0x58, 0x90, 0x2e,
|
||||
0xf4, 0x98, 0x2b, 0x5c, 0xad, 0x11, 0x31, 0x61, 0xca, 0x84, 0x5e, 0xbf, 0x07, 0x43, 0x26, 0x0c,
|
||||
0x99, 0x30, 0x61, 0x56, 0xb6, 0x7a, 0x54, 0x9c, 0xf9, 0x6d, 0xd8, 0x71, 0x07, 0x66, 0xcf, 0xed,
|
||||
0xb9, 0xa6, 0x14, 0x68, 0xfb, 0xa7, 0xf2, 0x24, 0x0f, 0xf2, 0xbf, 0x48, 0xb8, 0xd2, 0x5a, 0x38,
|
||||
0x92, 0xc9, 0x08, 0x77, 0x7d, 0xd6, 0x21, 0xd7, 0x87, 0xa9, 0x6c, 0x2f, 0xe6, 0xf8, 0xce, 0x90,
|
||||
0x30, 0x4e, 0x5d, 0x87, 0x74, 0x67, 0x68, 0x9b, 0x8b, 0x69, 0xc3, 0x19, 0xc7, 0x95, 0xad, 0xf9,
|
||||
0x68, 0xe6, 0x3b, 0x82, 0x0e, 0x66, 0x67, 0x6a, 0xce, 0x87, 0xfb, 0x82, 0xda, 0x26, 0x75, 0x04,
|
||||
0x17, 0xec, 0x3a, 0xa5, 0xfe, 0x5c, 0x01, 0xc5, 0xef, 0x6d, 0x9f, 0x0b, 0xc2, 0x90, 0x6b, 0x13,
|
||||
0xed, 0x37, 0x50, 0x18, 0x10, 0x81, 0xbb, 0x58, 0x60, 0x5d, 0xa9, 0x29, 0x8d, 0x62, 0xab, 0x01,
|
||||
0x17, 0xae, 0x1d, 0x0e, 0x9b, 0xf0, 0x97, 0xf6, 0xdf, 0xa4, 0x23, 0x7e, 0x26, 0x02, 0x5b, 0xda,
|
||||
0xc5, 0xa8, 0x9a, 0x09, 0x46, 0x55, 0x90, 0xd6, 0xd0, 0x58, 0x4d, 0xfb, 0x1d, 0xe4, 0x99, 0x6f,
|
||||
0x13, 0xae, 0xaf, 0xd4, 0xb2, 0x8d, 0x62, 0xeb, 0x6b, 0xb8, 0xec, 0xaf, 0x09, 0x0f, 0x5d, 0x9b,
|
||||
0x76, 0xfe, 0x43, 0xbe, 0x4d, 0xac, 0x52, 0x7c, 0x45, 0x3e, 0x3c, 0x71, 0x14, 0x29, 0xd6, 0x1f,
|
||||
0xaf, 0x00, 0x6d, 0xc2, 0x84, 0x45, 0x9d, 0x2e, 0x75, 0x7a, 0xef, 0xd1, 0xcb, 0x5f, 0xa0, 0xc0,
|
||||
0x7d, 0xd9, 0x48, 0xec, 0x34, 0x97, 0xb7, 0x73, 0x14, 0x31, 0xad, 0xcf, 0xe2, 0x2b, 0x0a, 0x71,
|
||||
0x81, 0xa3, 0xb1, 0xa8, 0xf6, 0x07, 0x58, 0x65, 0xae, 0x4d, 0x10, 0x39, 0xd5, 0xb3, 0x72, 0xf2,
|
||||
0x5b, 0xe8, 0xa3, 0x88, 0x68, 0x95, 0x63, 0xfd, 0xd5, 0xb8, 0x80, 0x12, 0xc9, 0xfa, 0x2b, 0x05,
|
||||
0x7c, 0x31, 0xbb, 0xaf, 0x7d, 0xca, 0x85, 0xf6, 0xe7, 0xcc, 0xce, 0xcc, 0x77, 0xec, 0x6c, 0xe2,
|
||||
0xa5, 0xc3, 0x90, 0x2e, 0x57, 0x37, 0xf6, 0x95, 0x54, 0x26, 0x16, 0x87, 0x41, 0x9e, 0x0a, 0x32,
|
||||
0x48, 0xb6, 0xf6, 0xed, 0xf2, 0xae, 0x66, 0xe7, 0x4d, 0x1f, 0xc3, 0x5e, 0x28, 0x89, 0x22, 0xe5,
|
||||
0xfa, 0x0b, 0x05, 0x94, 0x27, 0xc0, 0xf7, 0xe1, 0xea, 0x64, 0xda, 0xd5, 0xf6, 0xdd, 0x5c, 0xcd,
|
||||
0xb7, 0xf3, 0x20, 0x0b, 0x40, 0xfa, 0x01, 0x68, 0x55, 0x90, 0x1f, 0x12, 0xd6, 0xe6, 0xba, 0x52,
|
||||
0xcb, 0x36, 0x54, 0x4b, 0x0d, 0xf1, 0xc7, 0x61, 0x01, 0x45, 0x75, 0xed, 0x5c, 0x01, 0xeb, 0x58,
|
||||
0x08, 0x46, 0xdb, 0xbe, 0x20, 0x88, 0x70, 0xc1, 0x68, 0x47, 0x50, 0xd7, 0x09, 0x87, 0x0b, 0x8d,
|
||||
0x6f, 0x2c, 0x18, 0x2e, 0xce, 0x14, 0x88, 0xf0, 0x3f, 0x3f, 0xfc, 0x2b, 0x88, 0x13, 0xfa, 0xb7,
|
||||
0xbe, 0x8c, 0x47, 0x5a, 0xdf, 0x9d, 0xa7, 0x88, 0xe6, 0x5f, 0xa4, 0x6d, 0x00, 0x15, 0x7b, 0xf4,
|
||||
0x47, 0xe6, 0xfa, 0x1e, 0xd7, 0xb3, 0x72, 0xce, 0x52, 0x30, 0xaa, 0xaa, 0xbb, 0x87, 0x7b, 0x51,
|
||||
0x11, 0xa5, 0xfd, 0x10, 0x9c, 0x64, 0x2c, 0xd7, 0x73, 0x29, 0x18, 0x25, 0x45, 0x94, 0xf6, 0xb5,
|
||||
0x6f, 0x40, 0x29, 0x39, 0x1c, 0xe0, 0x01, 0xe1, 0x7a, 0x5e, 0x12, 0xd6, 0x82, 0x51, 0xb5, 0x84,
|
||||
0x26, 0x1b, 0x68, 0x1a, 0xa7, 0x7d, 0x07, 0xca, 0x8e, 0xeb, 0x24, 0x90, 0x5f, 0xd1, 0x3e, 0xd7,
|
||||
0x3f, 0x91, 0xd4, 0xcf, 0x83, 0x51, 0xb5, 0x7c, 0x30, 0xdd, 0x42, 0xd7, 0xb1, 0xf5, 0xa7, 0x0a,
|
||||
0xc8, 0x7d, 0xb8, 0xf1, 0xf8, 0x68, 0x05, 0x14, 0x3f, 0xe6, 0xe2, 0x12, 0xb9, 0x18, 0x46, 0xc7,
|
||||
0x3d, 0x07, 0xe2, 0xdd, 0xa3, 0xe3, 0xe6, 0x24, 0x7c, 0xa6, 0x80, 0xc2, 0x7d, 0x45, 0xe0, 0xd1,
|
||||
0xb4, 0x0f, 0x78, 0x4b, 0x1f, 0xf3, 0x0d, 0xfc, 0x0f, 0x92, 0xdf, 0x48, 0xdb, 0x04, 0x85, 0x24,
|
||||
0x33, 0xe4, 0xf8, 0x6a, 0x3a, 0x4d, 0x12, 0x2b, 0x68, 0x8c, 0xd0, 0x6a, 0x20, 0xd7, 0xa7, 0x4e,
|
||||
0x57, 0x46, 0x9e, 0x6a, 0x7d, 0x1a, 0x23, 0x73, 0x3f, 0x51, 0xa7, 0x8b, 0x64, 0x27, 0x44, 0x38,
|
||||
0x78, 0x40, 0xe4, 0x2b, 0x9a, 0x40, 0x84, 0x69, 0x81, 0x64, 0xa7, 0xfe, 0x44, 0x01, 0xab, 0xf1,
|
||||
0x0b, 0x1c, 0xeb, 0x29, 0x0b, 0xf5, 0x5a, 0x00, 0x60, 0x8f, 0x1e, 0x47, 0x4b, 0x8b, 0xef, 0x1d,
|
||||
0x7f, 0x2b, 0xbb, 0x87, 0x7b, 0x71, 0x07, 0x4d, 0xa0, 0x6e, 0x9e, 0x41, 0x33, 0x81, 0x1a, 0xfe,
|
||||
0xe5, 0x1e, 0xee, 0x10, 0x3d, 0x27, 0x61, 0x6b, 0x31, 0x4c, 0x3d, 0x48, 0x1a, 0x28, 0xc5, 0x58,
|
||||
0x5f, 0x5d, 0x5c, 0x19, 0x99, 0xcb, 0x2b, 0x23, 0xf3, 0xf2, 0xca, 0xc8, 0x9c, 0x07, 0x86, 0x72,
|
||||
0x11, 0x18, 0xca, 0x65, 0x60, 0x28, 0xaf, 0x03, 0x43, 0x79, 0xf8, 0xc6, 0xc8, 0x9c, 0x14, 0x92,
|
||||
0xc5, 0xbf, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x62, 0x32, 0x8a, 0x1f, 0x89, 0x0b, 0x00, 0x00,
|
||||
// 875 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xec, 0x55, 0xcf, 0x8b, 0x23, 0x45,
|
||||
0x14, 0x4e, 0x4d, 0x12, 0x27, 0x79, 0xe3, 0x30, 0x4e, 0xc9, 0x4a, 0x1b, 0x30, 0x19, 0x72, 0x0a,
|
||||
0xee, 0x6e, 0x37, 0x19, 0x5c, 0xdc, 0x83, 0x1e, 0xa6, 0x45, 0x64, 0x70, 0x1d, 0x87, 0x5a, 0x5c,
|
||||
0x74, 0x51, 0xa4, 0x92, 0xd4, 0x66, 0xca, 0x74, 0xba, 0x9b, 0xaa, 0xea, 0xa8, 0x88, 0xb0, 0x78,
|
||||
0xf2, 0xe8, 0x5f, 0xb1, 0x37, 0x2f, 0x5e, 0x05, 0x0f, 0x9e, 0xe6, 0xe0, 0x61, 0x8f, 0xe2, 0x21,
|
||||
0x38, 0xf1, 0x1f, 0x91, 0xae, 0xae, 0xfe, 0x31, 0x93, 0x8e, 0x9b, 0x19, 0x71, 0x40, 0xd8, 0x53,
|
||||
0xd2, 0xef, 0x7d, 0xdf, 0x57, 0xef, 0xab, 0x57, 0xf5, 0x0a, 0xee, 0x4e, 0xee, 0x4a, 0x9b, 0x07,
|
||||
0xce, 0x24, 0x1a, 0x30, 0xe1, 0x33, 0xc5, 0xa4, 0x13, 0x4e, 0xc6, 0x0e, 0x0d, 0xb9, 0x74, 0xc4,
|
||||
0x80, 0x0e, 0x9d, 0x59, 0x9f, 0x7a, 0xe1, 0x09, 0xed, 0x3b, 0x63, 0xe6, 0x33, 0x41, 0x15, 0x1b,
|
||||
0xd9, 0xa1, 0x08, 0x54, 0x80, 0x7b, 0x09, 0xd3, 0xce, 0x99, 0x76, 0x38, 0x19, 0xdb, 0x31, 0xd3,
|
||||
0x8e, 0x99, 0x76, 0xca, 0x6c, 0xdd, 0x1e, 0x73, 0x75, 0x12, 0x0d, 0xec, 0x61, 0x30, 0x75, 0xc6,
|
||||
0xc1, 0x38, 0x70, 0xb4, 0xc0, 0x20, 0x7a, 0xa4, 0xbf, 0xf4, 0x87, 0xfe, 0x97, 0x08, 0xb7, 0xf6,
|
||||
0x57, 0x96, 0xe4, 0x08, 0x26, 0x83, 0x48, 0x0c, 0xd9, 0xc5, 0x62, 0x5a, 0x77, 0x56, 0x73, 0x22,
|
||||
0x7f, 0xc6, 0x84, 0xe4, 0x81, 0xcf, 0x46, 0x4b, 0xb4, 0x5b, 0xab, 0x69, 0xb3, 0x25, 0xc7, 0xad,
|
||||
0xdb, 0xe5, 0x68, 0x11, 0xf9, 0x8a, 0x4f, 0x97, 0x6b, 0xea, 0x97, 0xc3, 0x23, 0xc5, 0x3d, 0x87,
|
||||
0xfb, 0x4a, 0x2a, 0x71, 0x91, 0xd2, 0xfd, 0x15, 0xc1, 0xd6, 0x3b, 0x5e, 0x24, 0x15, 0x13, 0x24,
|
||||
0xf0, 0x18, 0xfe, 0x18, 0x1a, 0x53, 0xa6, 0xe8, 0x88, 0x2a, 0x6a, 0xa1, 0x3d, 0xd4, 0xdb, 0xda,
|
||||
0xef, 0xd9, 0x2b, 0xb7, 0xdd, 0x9e, 0xf5, 0xed, 0x0f, 0x07, 0x5f, 0xb0, 0xa1, 0xfa, 0x80, 0x29,
|
||||
0xea, 0xe2, 0xd3, 0x79, 0xa7, 0xb2, 0x98, 0x77, 0x20, 0x8f, 0x91, 0x4c, 0x0d, 0x7f, 0x02, 0x75,
|
||||
0x11, 0x79, 0x4c, 0x5a, 0x1b, 0x7b, 0xd5, 0xde, 0xd6, 0xfe, 0x1b, 0xf6, 0xba, 0xdd, 0xb4, 0x8f,
|
||||
0x03, 0x8f, 0x0f, 0xbf, 0x26, 0x91, 0xc7, 0xdc, 0x6d, 0xb3, 0x44, 0x3d, 0xfe, 0x92, 0x24, 0x51,
|
||||
0xec, 0xfe, 0xb8, 0x01, 0xb8, 0x60, 0xc2, 0xe5, 0xfe, 0x88, 0xfb, 0xe3, 0xff, 0xd0, 0xcb, 0xe7,
|
||||
0xd0, 0x90, 0x91, 0x4e, 0xa4, 0x76, 0xfa, 0xeb, 0xdb, 0xb9, 0x9f, 0x30, 0xdd, 0x97, 0xcc, 0x12,
|
||||
0x0d, 0x13, 0x90, 0x24, 0x13, 0xc5, 0x9f, 0xc2, 0xa6, 0x08, 0x3c, 0x46, 0xd8, 0x23, 0xab, 0xaa,
|
||||
0x2b, 0xbf, 0x84, 0x3e, 0x49, 0x88, 0xee, 0x8e, 0xd1, 0xdf, 0x34, 0x01, 0x92, 0x4a, 0x76, 0x9f,
|
||||
0x20, 0x78, 0x75, 0x79, 0xbf, 0xdc, 0x88, 0x7b, 0x23, 0x26, 0xf0, 0xf7, 0x08, 0xf0, 0x70, 0x29,
|
||||
0x6b, 0x76, 0xf0, 0xad, 0xf5, 0xeb, 0x28, 0x59, 0xa1, 0x65, 0x4a, 0x2a, 0xe9, 0x16, 0x29, 0x59,
|
||||
0xb3, 0xfb, 0x07, 0x82, 0x57, 0x96, 0xa1, 0xf7, 0xb8, 0x54, 0xf8, 0xb3, 0xa5, 0xe6, 0x3a, 0xff,
|
||||
0xd0, 0xdc, 0xc2, 0x95, 0xb4, 0x63, 0xba, 0xee, 0x71, 0xd6, 0x80, 0x34, 0x52, 0xe8, 0x30, 0x85,
|
||||
0x3a, 0x57, 0x6c, 0x9a, 0xb6, 0xf7, 0xdf, 0xd9, 0xce, 0x4e, 0xed, 0x61, 0x2c, 0x49, 0x12, 0xe5,
|
||||
0xee, 0x6f, 0x08, 0x76, 0x0a, 0xe0, 0xeb, 0x70, 0xf5, 0xf0, 0xbc, 0xab, 0x3b, 0x57, 0x73, 0x55,
|
||||
0x6e, 0xe7, 0xbb, 0x2a, 0x40, 0x7e, 0x53, 0x71, 0x07, 0xea, 0x33, 0x26, 0x06, 0xd2, 0x42, 0x7b,
|
||||
0xd5, 0x5e, 0xd3, 0x6d, 0xc6, 0xf8, 0x07, 0x71, 0x80, 0x24, 0x71, 0xfc, 0x18, 0xc1, 0x0d, 0xaa,
|
||||
0x94, 0xe0, 0x83, 0x48, 0x31, 0xc2, 0xa4, 0x12, 0x7c, 0xa8, 0x78, 0xe0, 0xc7, 0xc5, 0xc5, 0xc6,
|
||||
0x6f, 0xae, 0x28, 0xce, 0x0c, 0x3f, 0x9b, 0xd0, 0x2f, 0xdf, 0xfd, 0x4a, 0x31, 0x3f, 0xf6, 0xef,
|
||||
0xbe, 0x66, 0x4a, 0xba, 0x71, 0x50, 0xa6, 0x48, 0xca, 0x17, 0xc2, 0x37, 0xa1, 0x49, 0x43, 0xfe,
|
||||
0x9e, 0x08, 0xa2, 0x50, 0x5a, 0x55, 0x5d, 0xe7, 0xf6, 0x62, 0xde, 0x69, 0x1e, 0x1c, 0x1f, 0x26,
|
||||
0x41, 0x92, 0xe7, 0x63, 0x70, 0xfa, 0x18, 0x48, 0xab, 0x96, 0x83, 0x49, 0x1a, 0x24, 0x79, 0x1e,
|
||||
0xbf, 0x09, 0xdb, 0xe9, 0xc7, 0x11, 0x9d, 0x32, 0x69, 0xd5, 0x35, 0x61, 0x77, 0x31, 0xef, 0x6c,
|
||||
0x93, 0x62, 0x82, 0x9c, 0xc7, 0xe1, 0xb7, 0x61, 0xc7, 0x0f, 0xfc, 0x14, 0xf2, 0x11, 0xb9, 0x27,
|
||||
0xad, 0x17, 0x34, 0xf5, 0xe5, 0xc5, 0xbc, 0xb3, 0x73, 0x74, 0x3e, 0x45, 0x2e, 0x62, 0xbb, 0xdf,
|
||||
0xc2, 0x6e, 0x61, 0x5a, 0x9a, 0x0b, 0x7d, 0x02, 0x10, 0x66, 0x41, 0x73, 0xac, 0xae, 0x36, 0x7e,
|
||||
0xb3, 0xa9, 0x98, 0xc7, 0x48, 0x41, 0xbb, 0xfb, 0x33, 0x82, 0xda, 0xff, 0xf7, 0x19, 0x79, 0xb2,
|
||||
0x01, 0x5b, 0xcf, 0xdf, 0x8f, 0x35, 0xde, 0x8f, 0x78, 0x72, 0x5d, 0xf3, 0x3c, 0xbe, 0xfa, 0xe4,
|
||||
0x7a, 0xf6, 0x20, 0xfe, 0x05, 0x41, 0xe3, 0xba, 0x26, 0xf0, 0xfd, 0xf3, 0x3e, 0xec, 0x4b, 0xfa,
|
||||
0x28, 0x37, 0xf0, 0x0d, 0xa4, 0x3d, 0xc2, 0xb7, 0xa0, 0x91, 0x8e, 0x2c, 0x5d, 0x7e, 0x33, 0xaf,
|
||||
0x26, 0x9d, 0x6a, 0x24, 0x43, 0xe0, 0x3d, 0xa8, 0x4d, 0xb8, 0x3f, 0xd2, 0x13, 0xb7, 0xe9, 0xbe,
|
||||
0x68, 0x90, 0xb5, 0xf7, 0xb9, 0x3f, 0x22, 0x3a, 0x13, 0x23, 0x7c, 0x3a, 0x65, 0xfa, 0x14, 0x15,
|
||||
0x10, 0xf1, 0xb0, 0x22, 0x3a, 0xd3, 0xfd, 0x09, 0xc1, 0xa6, 0x39, 0x81, 0x99, 0x1e, 0x5a, 0xa9,
|
||||
0xb7, 0x0f, 0x40, 0x43, 0xfe, 0x20, 0xd9, 0x34, 0xb3, 0x6e, 0x76, 0x57, 0x0e, 0x8e, 0x0f, 0x4d,
|
||||
0x86, 0x14, 0x50, 0xcf, 0xae, 0x01, 0x3b, 0xd0, 0x8c, 0x7f, 0x65, 0x48, 0x87, 0xcc, 0xaa, 0x69,
|
||||
0xd8, 0xae, 0x81, 0x35, 0x8f, 0xd2, 0x04, 0xc9, 0x31, 0xee, 0xeb, 0xa7, 0x67, 0xed, 0xca, 0xd3,
|
||||
0xb3, 0x76, 0xe5, 0xf7, 0xb3, 0x76, 0xe5, 0xf1, 0xa2, 0x8d, 0x4e, 0x17, 0x6d, 0xf4, 0x74, 0xd1,
|
||||
0x46, 0x7f, 0x2e, 0xda, 0xe8, 0x87, 0xbf, 0xda, 0x95, 0x87, 0x8d, 0x74, 0xe3, 0xff, 0x0e, 0x00,
|
||||
0x00, 0xff, 0xff, 0x90, 0x88, 0x4e, 0x35, 0xb1, 0x0c, 0x00, 0x00,
|
||||
}
|
||||
|
@ -55,6 +55,14 @@ message ClusterRoleBinding {
|
||||
optional RoleRef roleRef = 3;
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=false
|
||||
// ClusterRoleBindingBuilder let's us attach methods. A no-no for API types.
|
||||
// We use it to construct bindings in code. It's more compact than trying to write them
|
||||
// out in a literal.
|
||||
message ClusterRoleBindingBuilder {
|
||||
optional ClusterRoleBinding clusterRoleBinding = 1;
|
||||
}
|
||||
|
||||
// ClusterRoleBindingList is a collection of ClusterRoleBindings
|
||||
message ClusterRoleBindingList {
|
||||
// Standard object's metadata.
|
||||
@ -107,6 +115,14 @@ message PolicyRule {
|
||||
repeated string nonResourceURLs = 6;
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=false
|
||||
// PolicyRuleBuilder let's us attach methods. A no-no for API types.
|
||||
// We use it to construct rules in code. It's more compact than trying to write them
|
||||
// out in a literal and allows us to perform some basic checking during construction
|
||||
message PolicyRuleBuilder {
|
||||
optional PolicyRule policyRule = 1;
|
||||
}
|
||||
|
||||
// Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding.
|
||||
message Role {
|
||||
// Standard object's metadata.
|
||||
|
148
pkg/apis/rbac/v1alpha1/helpers.go
Normal file
148
pkg/apis/rbac/v1alpha1/helpers.go
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright 2016 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 v1alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen=false
|
||||
// PolicyRuleBuilder let's us attach methods. A no-no for API types.
|
||||
// We use it to construct rules in code. It's more compact than trying to write them
|
||||
// out in a literal and allows us to perform some basic checking during construction
|
||||
type PolicyRuleBuilder struct {
|
||||
PolicyRule PolicyRule
|
||||
}
|
||||
|
||||
func NewRule(verbs ...string) *PolicyRuleBuilder {
|
||||
return &PolicyRuleBuilder{
|
||||
PolicyRule: PolicyRule{Verbs: verbs},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *PolicyRuleBuilder) Groups(groups ...string) *PolicyRuleBuilder {
|
||||
r.PolicyRule.APIGroups = append(r.PolicyRule.APIGroups, groups...)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *PolicyRuleBuilder) Resources(resources ...string) *PolicyRuleBuilder {
|
||||
r.PolicyRule.Resources = append(r.PolicyRule.Resources, resources...)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *PolicyRuleBuilder) Names(names ...string) *PolicyRuleBuilder {
|
||||
r.PolicyRule.ResourceNames = append(r.PolicyRule.ResourceNames, names...)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *PolicyRuleBuilder) URLs(urls ...string) *PolicyRuleBuilder {
|
||||
r.PolicyRule.NonResourceURLs = append(r.PolicyRule.NonResourceURLs, urls...)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *PolicyRuleBuilder) RuleOrDie() PolicyRule {
|
||||
ret, err := r.Rule()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *PolicyRuleBuilder) Rule() (PolicyRule, error) {
|
||||
if len(r.PolicyRule.Verbs) == 0 {
|
||||
return PolicyRule{}, fmt.Errorf("verbs are required: %#v", r.PolicyRule)
|
||||
}
|
||||
|
||||
switch {
|
||||
case len(r.PolicyRule.NonResourceURLs) > 0:
|
||||
if len(r.PolicyRule.APIGroups) != 0 || len(r.PolicyRule.Resources) != 0 || len(r.PolicyRule.ResourceNames) != 0 {
|
||||
return PolicyRule{}, fmt.Errorf("non-resource rule may not have apiGroups, resources, or resourceNames: %#v", r.PolicyRule)
|
||||
}
|
||||
case len(r.PolicyRule.Resources) > 0:
|
||||
if len(r.PolicyRule.NonResourceURLs) != 0 {
|
||||
return PolicyRule{}, fmt.Errorf("resource rule may not have nonResourceURLs: %#v", r.PolicyRule)
|
||||
}
|
||||
if len(r.PolicyRule.APIGroups) == 0 {
|
||||
// this a common bug
|
||||
return PolicyRule{}, fmt.Errorf("resource rule must have apiGroups: %#v", r.PolicyRule)
|
||||
}
|
||||
default:
|
||||
return PolicyRule{}, fmt.Errorf("a rule must have either nonResourceURLs or resources: %#v", r.PolicyRule)
|
||||
}
|
||||
|
||||
return r.PolicyRule, nil
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=false
|
||||
// ClusterRoleBindingBuilder let's us attach methods. A no-no for API types.
|
||||
// We use it to construct bindings in code. It's more compact than trying to write them
|
||||
// out in a literal.
|
||||
type ClusterRoleBindingBuilder struct {
|
||||
ClusterRoleBinding ClusterRoleBinding
|
||||
}
|
||||
|
||||
func NewClusterBinding(clusterRoleName string) *ClusterRoleBindingBuilder {
|
||||
return &ClusterRoleBindingBuilder{
|
||||
ClusterRoleBinding: ClusterRoleBinding{
|
||||
ObjectMeta: v1.ObjectMeta{Name: clusterRoleName},
|
||||
RoleRef: RoleRef{
|
||||
APIGroup: GroupName,
|
||||
Kind: "ClusterRole",
|
||||
Name: clusterRoleName,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ClusterRoleBindingBuilder) Groups(groups ...string) *ClusterRoleBindingBuilder {
|
||||
for _, group := range groups {
|
||||
r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, Subject{Kind: GroupKind, Name: group})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ClusterRoleBindingBuilder) Users(users ...string) *ClusterRoleBindingBuilder {
|
||||
for _, user := range users {
|
||||
r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, Subject{Kind: UserKind, Name: user})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ClusterRoleBindingBuilder) SAs(namespace string, serviceAccountNames ...string) *ClusterRoleBindingBuilder {
|
||||
for _, saName := range serviceAccountNames {
|
||||
r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, Subject{Kind: ServiceAccountKind, Namespace: namespace, Name: saName})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ClusterRoleBindingBuilder) BindingOrDie() ClusterRoleBinding {
|
||||
ret, err := r.Binding()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *ClusterRoleBindingBuilder) Binding() (ClusterRoleBinding, error) {
|
||||
if len(r.ClusterRoleBinding.Subjects) == 0 {
|
||||
return ClusterRoleBinding{}, fmt.Errorf("subjects are required: %#v", r.ClusterRoleBinding)
|
||||
}
|
||||
|
||||
return r.ClusterRoleBinding, nil
|
||||
}
|
@ -27,6 +27,24 @@ import (
|
||||
// 2. evaluation of RoleBindings in the namespace requested - short circuit on match
|
||||
// 3. deny by default
|
||||
|
||||
const (
|
||||
APIGroupAll = "*"
|
||||
ResourceAll = "*"
|
||||
VerbAll = "*"
|
||||
NonResourceAll = "*"
|
||||
|
||||
GroupKind = "Group"
|
||||
ServiceAccountKind = "ServiceAccount"
|
||||
UserKind = "User"
|
||||
|
||||
UserAll = "*"
|
||||
)
|
||||
|
||||
// Authorization is calculated against
|
||||
// 1. evaluation of ClusterRoleBindings - short circuit on match
|
||||
// 2. evaluation of RoleBindings in the namespace requested - short circuit on match
|
||||
// 3. deny by default
|
||||
|
||||
// PolicyRule holds information that describes a policy rule, but does not contain information
|
||||
// about who the rule applies to or which namespace the rule applies to.
|
||||
type PolicyRule struct {
|
||||
|
@ -39,12 +39,16 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
Convert_rbac_ClusterRole_To_v1alpha1_ClusterRole,
|
||||
Convert_v1alpha1_ClusterRoleBinding_To_rbac_ClusterRoleBinding,
|
||||
Convert_rbac_ClusterRoleBinding_To_v1alpha1_ClusterRoleBinding,
|
||||
Convert_v1alpha1_ClusterRoleBindingBuilder_To_rbac_ClusterRoleBindingBuilder,
|
||||
Convert_rbac_ClusterRoleBindingBuilder_To_v1alpha1_ClusterRoleBindingBuilder,
|
||||
Convert_v1alpha1_ClusterRoleBindingList_To_rbac_ClusterRoleBindingList,
|
||||
Convert_rbac_ClusterRoleBindingList_To_v1alpha1_ClusterRoleBindingList,
|
||||
Convert_v1alpha1_ClusterRoleList_To_rbac_ClusterRoleList,
|
||||
Convert_rbac_ClusterRoleList_To_v1alpha1_ClusterRoleList,
|
||||
Convert_v1alpha1_PolicyRule_To_rbac_PolicyRule,
|
||||
Convert_rbac_PolicyRule_To_v1alpha1_PolicyRule,
|
||||
Convert_v1alpha1_PolicyRuleBuilder_To_rbac_PolicyRuleBuilder,
|
||||
Convert_rbac_PolicyRuleBuilder_To_v1alpha1_PolicyRuleBuilder,
|
||||
Convert_v1alpha1_Role_To_rbac_Role,
|
||||
Convert_rbac_Role_To_v1alpha1_Role,
|
||||
Convert_v1alpha1_RoleBinding_To_rbac_RoleBinding,
|
||||
@ -138,6 +142,28 @@ func Convert_rbac_ClusterRoleBinding_To_v1alpha1_ClusterRoleBinding(in *rbac.Clu
|
||||
return autoConvert_rbac_ClusterRoleBinding_To_v1alpha1_ClusterRoleBinding(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterRoleBindingBuilder_To_rbac_ClusterRoleBindingBuilder(in *ClusterRoleBindingBuilder, out *rbac.ClusterRoleBindingBuilder, s conversion.Scope) error {
|
||||
if err := Convert_v1alpha1_ClusterRoleBinding_To_rbac_ClusterRoleBinding(&in.ClusterRoleBinding, &out.ClusterRoleBinding, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_ClusterRoleBindingBuilder_To_rbac_ClusterRoleBindingBuilder(in *ClusterRoleBindingBuilder, out *rbac.ClusterRoleBindingBuilder, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterRoleBindingBuilder_To_rbac_ClusterRoleBindingBuilder(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_rbac_ClusterRoleBindingBuilder_To_v1alpha1_ClusterRoleBindingBuilder(in *rbac.ClusterRoleBindingBuilder, out *ClusterRoleBindingBuilder, s conversion.Scope) error {
|
||||
if err := Convert_rbac_ClusterRoleBinding_To_v1alpha1_ClusterRoleBinding(&in.ClusterRoleBinding, &out.ClusterRoleBinding, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_rbac_ClusterRoleBindingBuilder_To_v1alpha1_ClusterRoleBindingBuilder(in *rbac.ClusterRoleBindingBuilder, out *ClusterRoleBindingBuilder, s conversion.Scope) error {
|
||||
return autoConvert_rbac_ClusterRoleBindingBuilder_To_v1alpha1_ClusterRoleBindingBuilder(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterRoleBindingList_To_rbac_ClusterRoleBindingList(in *ClusterRoleBindingList, out *rbac.ClusterRoleBindingList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]rbac.ClusterRoleBinding)(unsafe.Pointer(&in.Items))
|
||||
@ -230,6 +256,28 @@ func Convert_rbac_PolicyRule_To_v1alpha1_PolicyRule(in *rbac.PolicyRule, out *Po
|
||||
return autoConvert_rbac_PolicyRule_To_v1alpha1_PolicyRule(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_PolicyRuleBuilder_To_rbac_PolicyRuleBuilder(in *PolicyRuleBuilder, out *rbac.PolicyRuleBuilder, s conversion.Scope) error {
|
||||
if err := Convert_v1alpha1_PolicyRule_To_rbac_PolicyRule(&in.PolicyRule, &out.PolicyRule, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_PolicyRuleBuilder_To_rbac_PolicyRuleBuilder(in *PolicyRuleBuilder, out *rbac.PolicyRuleBuilder, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_PolicyRuleBuilder_To_rbac_PolicyRuleBuilder(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_rbac_PolicyRuleBuilder_To_v1alpha1_PolicyRuleBuilder(in *rbac.PolicyRuleBuilder, out *PolicyRuleBuilder, s conversion.Scope) error {
|
||||
if err := Convert_rbac_PolicyRule_To_v1alpha1_PolicyRule(&in.PolicyRule, &out.PolicyRule, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_rbac_PolicyRuleBuilder_To_v1alpha1_PolicyRuleBuilder(in *rbac.PolicyRuleBuilder, out *PolicyRuleBuilder, s conversion.Scope) error {
|
||||
return autoConvert_rbac_PolicyRuleBuilder_To_v1alpha1_PolicyRuleBuilder(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_Role_To_rbac_Role(in *Role, out *rbac.Role, s conversion.Scope) error {
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
|
||||
|
18
pkg/apis/storage/v1beta1/util/BUILD
Normal file
18
pkg/apis/storage/v1beta1/util/BUILD
Normal file
@ -0,0 +1,18 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["helpers.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//pkg/api/v1:go_default_library"],
|
||||
)
|
134
pkg/apis/storage/v1beta1/util/helpers.go
Normal file
134
pkg/apis/storage/v1beta1/util/helpers.go
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright 2016 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 util
|
||||
|
||||
import "k8s.io/kubernetes/pkg/api/v1"
|
||||
|
||||
// IsDefaultStorageClassAnnotation represents a StorageClass annotation that
|
||||
// marks a class as the default StorageClass
|
||||
//TODO: Update IsDefaultStorageClassannotation and remove Beta when no longer used
|
||||
const IsDefaultStorageClassAnnotation = "storageclass.beta.kubernetes.io/is-default-class"
|
||||
const BetaIsDefaultStorageClassAnnotation = "storageclass.beta.kubernetes.io/is-default-class"
|
||||
|
||||
// AlphaStorageClassAnnotation represents the previous alpha storage class
|
||||
// annotation. it's no longer used and held here for posterity.
|
||||
const AlphaStorageClassAnnotation = "volume.alpha.kubernetes.io/storage-class"
|
||||
|
||||
// BetaStorageClassAnnotation represents the beta/previous StorageClass annotation.
|
||||
// It's currently still used and will be held for backwards compatibility
|
||||
const BetaStorageClassAnnotation = "volume.beta.kubernetes.io/storage-class"
|
||||
|
||||
// StorageClassAnnotation represents the storage class associated with a resource.
|
||||
// It currently matches the Beta value and can change when official is set.
|
||||
// - in PersistentVolumeClaim it represents required class to match.
|
||||
// Only PersistentVolumes with the same class (i.e. annotation with the same
|
||||
// value) can be bound to the claim. In case no such volume exists, the
|
||||
// controller will provision a new one using StorageClass instance with
|
||||
// the same name as the annotation value.
|
||||
// - in PersistentVolume it represents storage class to which the persistent
|
||||
// volume belongs.
|
||||
//TODO: Update this to final annotation value as it matches BetaStorageClassAnnotation for now
|
||||
const StorageClassAnnotation = "volume.beta.kubernetes.io/storage-class"
|
||||
|
||||
// GetVolumeStorageClass returns value of StorageClassAnnotation or empty string in case
|
||||
// the annotation does not exist.
|
||||
// TODO: change to PersistentVolume.Spec.Class value when this attribute is
|
||||
// introduced.
|
||||
func GetVolumeStorageClass(volume *v1.PersistentVolume) string {
|
||||
if class, found := volume.Annotations[StorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
// 'nil' is interpreted as "", i.e. the volume does not belong to any class.
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetClaimStorageClass returns name of class that is requested by given claim.
|
||||
// Request for `nil` class is interpreted as request for class "",
|
||||
// i.e. for a classless PV.
|
||||
// TODO: change to PersistentVolumeClaim.Spec.Class value when this
|
||||
// attribute is introduced.
|
||||
func GetClaimStorageClass(claim *v1.PersistentVolumeClaim) string {
|
||||
if class, found := claim.Annotations[StorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetStorageClassAnnotation returns the StorageClass value
|
||||
// if the annotation is set, empty string if not
|
||||
// TODO: remove Alpha and Beta when no longer used or needed
|
||||
func GetStorageClassAnnotation(obj v1.ObjectMeta) string {
|
||||
if class, ok := obj.Annotations[StorageClassAnnotation]; ok {
|
||||
return class
|
||||
}
|
||||
if class, ok := obj.Annotations[BetaStorageClassAnnotation]; ok {
|
||||
return class
|
||||
}
|
||||
if class, ok := obj.Annotations[AlphaStorageClassAnnotation]; ok {
|
||||
return class
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// HasStorageClassAnnotation returns a boolean
|
||||
// if the annotation is set
|
||||
// TODO: remove Alpha and Beta when no longer used or needed
|
||||
func HasStorageClassAnnotation(obj v1.ObjectMeta) bool {
|
||||
if _, found := obj.Annotations[StorageClassAnnotation]; found {
|
||||
return found
|
||||
}
|
||||
if _, found := obj.Annotations[BetaStorageClassAnnotation]; found {
|
||||
return found
|
||||
}
|
||||
if _, found := obj.Annotations[AlphaStorageClassAnnotation]; found {
|
||||
return found
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
// IsDefaultAnnotationText returns a pretty Yes/No String if
|
||||
// the annotation is set
|
||||
// TODO: remove Beta when no longer needed
|
||||
func IsDefaultAnnotationText(obj v1.ObjectMeta) string {
|
||||
if obj.Annotations[IsDefaultStorageClassAnnotation] == "true" {
|
||||
return "Yes"
|
||||
}
|
||||
if obj.Annotations[BetaIsDefaultStorageClassAnnotation] == "true" {
|
||||
return "Yes"
|
||||
}
|
||||
|
||||
return "No"
|
||||
}
|
||||
|
||||
// IsDefaultAnnotation returns a boolean if
|
||||
// the annotation is set
|
||||
// TODO: remove Beta when no longer needed
|
||||
func IsDefaultAnnotation(obj v1.ObjectMeta) bool {
|
||||
if obj.Annotations[IsDefaultStorageClassAnnotation] == "true" {
|
||||
return true
|
||||
}
|
||||
if obj.Annotations[BetaIsDefaultStorageClassAnnotation] == "true" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
12
pkg/client/cache/BUILD
vendored
12
pkg/client/cache/BUILD
vendored
@ -39,12 +39,15 @@ go_library(
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/meta:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/apis/apps:go_default_library",
|
||||
"//pkg/apis/certificates:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/apps/v1beta1:go_default_library",
|
||||
"//pkg/apis/certificates/v1alpha1:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/apis/policy/v1beta1:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/apis/storage/v1beta1:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/labels:go_default_library",
|
||||
@ -82,8 +85,9 @@ go_test(
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apimachinery/registered:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/client/testing/cache:go_default_library",
|
||||
|
30
pkg/client/cache/controller_test.go
vendored
30
pkg/client/cache/controller_test.go
vendored
@ -23,7 +23,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
fcache "k8s.io/kubernetes/pkg/client/testing/cache"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
@ -51,7 +51,7 @@ func Example() {
|
||||
cfg := &Config{
|
||||
Queue: fifo,
|
||||
ListerWatcher: source,
|
||||
ObjectType: &api.Pod{},
|
||||
ObjectType: &v1.Pod{},
|
||||
FullResyncPeriod: time.Millisecond * 100,
|
||||
RetryOnError: false,
|
||||
|
||||
@ -101,7 +101,7 @@ func Example() {
|
||||
for _, name := range testIDs {
|
||||
// Note that these pods are not valid-- the fake source doesn't
|
||||
// call validation or anything.
|
||||
source.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: name}})
|
||||
source.Add(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: name}})
|
||||
}
|
||||
|
||||
// Let's wait for the controller to process the things we just added.
|
||||
@ -130,7 +130,7 @@ func ExampleNewInformer() {
|
||||
// logs anything deleted.
|
||||
_, controller := NewInformer(
|
||||
source,
|
||||
&api.Pod{},
|
||||
&v1.Pod{},
|
||||
time.Millisecond*100,
|
||||
ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
@ -158,7 +158,7 @@ func ExampleNewInformer() {
|
||||
for _, name := range testIDs {
|
||||
// Note that these pods are not valid-- the fake source doesn't
|
||||
// call validation or anything.
|
||||
source.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: name}})
|
||||
source.Add(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: name}})
|
||||
}
|
||||
|
||||
// Let's wait for the controller to process the things we just added.
|
||||
@ -206,7 +206,7 @@ func TestHammerController(t *testing.T) {
|
||||
// Make a controller which just logs all the changes it gets.
|
||||
_, controller := NewInformer(
|
||||
source,
|
||||
&api.Pod{},
|
||||
&v1.Pod{},
|
||||
time.Millisecond*100,
|
||||
ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) { recordFunc("add", obj) },
|
||||
@ -253,7 +253,7 @@ func TestHammerController(t *testing.T) {
|
||||
name = l[r.Intn(len(l))]
|
||||
}
|
||||
|
||||
pod := &api.Pod{}
|
||||
pod := &v1.Pod{}
|
||||
f.Fuzz(pod)
|
||||
pod.ObjectMeta.Name = name
|
||||
pod.ObjectMeta.Namespace = "default"
|
||||
@ -315,9 +315,9 @@ func TestUpdate(t *testing.T) {
|
||||
pair{FROM, FROM}: true,
|
||||
}
|
||||
|
||||
pod := func(name, check string, final bool) *api.Pod {
|
||||
p := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
pod := func(name, check string, final bool) *v1.Pod {
|
||||
p := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: map[string]string{"check": check},
|
||||
},
|
||||
@ -327,7 +327,7 @@ func TestUpdate(t *testing.T) {
|
||||
}
|
||||
return p
|
||||
}
|
||||
deletePod := func(p *api.Pod) bool {
|
||||
deletePod := func(p *v1.Pod) bool {
|
||||
return p.Labels["final"] == "true"
|
||||
}
|
||||
|
||||
@ -350,20 +350,20 @@ func TestUpdate(t *testing.T) {
|
||||
watchCh := make(chan struct{})
|
||||
_, controller := NewInformer(
|
||||
&testLW{
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
watch, err := source.Watch(options)
|
||||
close(watchCh)
|
||||
return watch, err
|
||||
},
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return source.List(options)
|
||||
},
|
||||
},
|
||||
&api.Pod{},
|
||||
&v1.Pod{},
|
||||
0,
|
||||
ResourceEventHandlerFuncs{
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
o, n := oldObj.(*api.Pod), newObj.(*api.Pod)
|
||||
o, n := oldObj.(*v1.Pod), newObj.(*v1.Pod)
|
||||
from, to := o.Labels["check"], n.Labels["check"]
|
||||
if !allowedTransitions[pair{from, to}] {
|
||||
t.Errorf("observed transition %q -> %q for %v", from, to, n.Name)
|
||||
|
19
pkg/client/cache/index_test.go
vendored
19
pkg/client/cache/index_test.go
vendored
@ -21,19 +21,20 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
func testIndexFunc(obj interface{}) ([]string, error) {
|
||||
pod := obj.(*api.Pod)
|
||||
pod := obj.(*v1.Pod)
|
||||
return []string{pod.Labels["foo"]}, nil
|
||||
}
|
||||
|
||||
func TestGetIndexFuncValues(t *testing.T) {
|
||||
index := NewIndexer(MetaNamespaceKeyFunc, Indexers{"testmodes": testIndexFunc})
|
||||
|
||||
pod1 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "one", Labels: map[string]string{"foo": "bar"}}}
|
||||
pod2 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "two", Labels: map[string]string{"foo": "bar"}}}
|
||||
pod3 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "tre", Labels: map[string]string{"foo": "biz"}}}
|
||||
pod1 := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "one", Labels: map[string]string{"foo": "bar"}}}
|
||||
pod2 := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "two", Labels: map[string]string{"foo": "bar"}}}
|
||||
pod3 := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "tre", Labels: map[string]string{"foo": "biz"}}}
|
||||
|
||||
index.Add(pod1)
|
||||
index.Add(pod2)
|
||||
@ -52,7 +53,7 @@ func TestGetIndexFuncValues(t *testing.T) {
|
||||
}
|
||||
|
||||
func testUsersIndexFunc(obj interface{}) ([]string, error) {
|
||||
pod := obj.(*api.Pod)
|
||||
pod := obj.(*v1.Pod)
|
||||
usersString := pod.Annotations["users"]
|
||||
|
||||
return strings.Split(usersString, ","), nil
|
||||
@ -61,9 +62,9 @@ func testUsersIndexFunc(obj interface{}) ([]string, error) {
|
||||
func TestMultiIndexKeys(t *testing.T) {
|
||||
index := NewIndexer(MetaNamespaceKeyFunc, Indexers{"byUser": testUsersIndexFunc})
|
||||
|
||||
pod1 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "one", Annotations: map[string]string{"users": "ernie,bert"}}}
|
||||
pod2 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "two", Annotations: map[string]string{"users": "bert,oscar"}}}
|
||||
pod3 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "tre", Annotations: map[string]string{"users": "ernie,elmo"}}}
|
||||
pod1 := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "one", Annotations: map[string]string{"users": "ernie,bert"}}}
|
||||
pod2 := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "two", Annotations: map[string]string{"users": "bert,oscar"}}}
|
||||
pod3 := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "tre", Annotations: map[string]string{"users": "ernie,elmo"}}}
|
||||
|
||||
index.Add(pod1)
|
||||
index.Add(pod2)
|
||||
@ -121,7 +122,7 @@ func TestMultiIndexKeys(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
copyOfPod2 := obj.(*api.Pod)
|
||||
copyOfPod2 := obj.(*v1.Pod)
|
||||
copyOfPod2.Annotations["users"] = "oscar"
|
||||
index.Update(copyOfPod2)
|
||||
bertPods, err = index.ByIndex("byUser", "bert")
|
||||
|
51
pkg/client/cache/listers.go
vendored
51
pkg/client/cache/listers.go
vendored
@ -20,15 +20,16 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
|
||||
certificates "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
policy "k8s.io/kubernetes/pkg/apis/policy/v1beta1"
|
||||
storageinternal "k8s.io/kubernetes/pkg/apis/storage"
|
||||
storage "k8s.io/kubernetes/pkg/apis/storage/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
@ -50,7 +51,7 @@ func ListAll(store Store, selector labels.Selector, appendFn AppendFunc) error {
|
||||
}
|
||||
|
||||
func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selector, appendFn AppendFunc) error {
|
||||
if namespace == api.NamespaceAll {
|
||||
if namespace == v1.NamespaceAll {
|
||||
for _, m := range indexer.List() {
|
||||
metadata, err := meta.Accessor(m)
|
||||
if err != nil {
|
||||
@ -63,7 +64,7 @@ func ListAllByNamespace(indexer Indexer, namespace string, selector labels.Selec
|
||||
return nil
|
||||
}
|
||||
|
||||
items, err := indexer.Index(NamespaceIndex, &api.ObjectMeta{Namespace: namespace})
|
||||
items, err := indexer.Index(NamespaceIndex, &v1.ObjectMeta{Namespace: namespace})
|
||||
if err != nil {
|
||||
// Ignore error; do slow search without index.
|
||||
glog.Warningf("can not retrieve list of objects using index : %v", err)
|
||||
@ -170,7 +171,7 @@ func (s *genericNamespaceLister) Get(name string) (runtime.Object, error) {
|
||||
|
||||
// NodeConditionPredicate is a function that indicates whether the given node's conditions meet
|
||||
// some set of criteria defined by the function.
|
||||
type NodeConditionPredicate func(node *api.Node) bool
|
||||
type NodeConditionPredicate func(node *v1.Node) bool
|
||||
|
||||
// StoreToNodeLister makes a Store have the List method of the client.NodeInterface
|
||||
// The Store must contain (only) Nodes.
|
||||
@ -178,9 +179,9 @@ type StoreToNodeLister struct {
|
||||
Store
|
||||
}
|
||||
|
||||
func (s *StoreToNodeLister) List() (machines api.NodeList, err error) {
|
||||
func (s *StoreToNodeLister) List() (machines v1.NodeList, err error) {
|
||||
for _, m := range s.Store.List() {
|
||||
machines.Items = append(machines.Items, *(m.(*api.Node)))
|
||||
machines.Items = append(machines.Items, *(m.(*v1.Node)))
|
||||
}
|
||||
return machines, nil
|
||||
}
|
||||
@ -199,9 +200,9 @@ type storeToNodeConditionLister struct {
|
||||
}
|
||||
|
||||
// List returns a list of nodes that match the conditions defined by the predicate functions in the storeToNodeConditionLister.
|
||||
func (s storeToNodeConditionLister) List() (nodes []*api.Node, err error) {
|
||||
func (s storeToNodeConditionLister) List() (nodes []*v1.Node, err error) {
|
||||
for _, m := range s.store.List() {
|
||||
node := m.(*api.Node)
|
||||
node := m.(*v1.Node)
|
||||
if s.predicate(node) {
|
||||
nodes = append(nodes, node)
|
||||
} else {
|
||||
@ -236,7 +237,7 @@ func (s *StoreToDaemonSetLister) List() (dss extensions.DaemonSetList, err error
|
||||
|
||||
// GetPodDaemonSets returns a list of daemon sets managing a pod.
|
||||
// Returns an error if and only if no matching daemon sets are found.
|
||||
func (s *StoreToDaemonSetLister) GetPodDaemonSets(pod *api.Pod) (daemonSets []extensions.DaemonSet, err error) {
|
||||
func (s *StoreToDaemonSetLister) GetPodDaemonSets(pod *v1.Pod) (daemonSets []extensions.DaemonSet, err error) {
|
||||
var selector labels.Selector
|
||||
var daemonSet extensions.DaemonSet
|
||||
|
||||
@ -274,17 +275,17 @@ type StoreToEndpointsLister struct {
|
||||
}
|
||||
|
||||
// List lists all endpoints in the store.
|
||||
func (s *StoreToEndpointsLister) List() (services api.EndpointsList, err error) {
|
||||
func (s *StoreToEndpointsLister) List() (services v1.EndpointsList, err error) {
|
||||
for _, m := range s.Store.List() {
|
||||
services.Items = append(services.Items, *(m.(*api.Endpoints)))
|
||||
services.Items = append(services.Items, *(m.(*v1.Endpoints)))
|
||||
}
|
||||
return services, nil
|
||||
}
|
||||
|
||||
// GetServiceEndpoints returns the endpoints of a service, matched on service name.
|
||||
func (s *StoreToEndpointsLister) GetServiceEndpoints(svc *api.Service) (ep api.Endpoints, err error) {
|
||||
func (s *StoreToEndpointsLister) GetServiceEndpoints(svc *v1.Service) (ep v1.Endpoints, err error) {
|
||||
for _, m := range s.Store.List() {
|
||||
ep = *m.(*api.Endpoints)
|
||||
ep = *m.(*v1.Endpoints)
|
||||
if svc.Name == ep.Name && svc.Namespace == ep.Namespace {
|
||||
return ep, nil
|
||||
}
|
||||
@ -299,8 +300,8 @@ type StoreToPVFetcher struct {
|
||||
}
|
||||
|
||||
// GetPersistentVolumeInfo returns cached data for the PersistentVolume 'id'.
|
||||
func (s *StoreToPVFetcher) GetPersistentVolumeInfo(id string) (*api.PersistentVolume, error) {
|
||||
o, exists, err := s.Get(&api.PersistentVolume{ObjectMeta: api.ObjectMeta{Name: id}})
|
||||
func (s *StoreToPVFetcher) GetPersistentVolumeInfo(id string) (*v1.PersistentVolume, error) {
|
||||
o, exists, err := s.Get(&v1.PersistentVolume{ObjectMeta: v1.ObjectMeta{Name: id}})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retrieving PersistentVolume '%v' from cache: %v", id, err)
|
||||
@ -310,7 +311,7 @@ func (s *StoreToPVFetcher) GetPersistentVolumeInfo(id string) (*api.PersistentVo
|
||||
return nil, fmt.Errorf("PersistentVolume '%v' not found", id)
|
||||
}
|
||||
|
||||
return o.(*api.PersistentVolume), nil
|
||||
return o.(*v1.PersistentVolume), nil
|
||||
}
|
||||
|
||||
// StoreToStatefulSetLister gives a store List and Exists methods. The store must contain only StatefulSets.
|
||||
@ -345,7 +346,7 @@ func (s *StoreToStatefulSetLister) StatefulSets(namespace string) storeStatefulS
|
||||
}
|
||||
|
||||
// GetPodStatefulSets returns a list of StatefulSets managing a pod. Returns an error only if no matching StatefulSets are found.
|
||||
func (s *StoreToStatefulSetLister) GetPodStatefulSets(pod *api.Pod) (psList []apps.StatefulSet, err error) {
|
||||
func (s *StoreToStatefulSetLister) GetPodStatefulSets(pod *v1.Pod) (psList []apps.StatefulSet, err error) {
|
||||
var selector labels.Selector
|
||||
var ps apps.StatefulSet
|
||||
|
||||
@ -404,7 +405,7 @@ type StoreToPodDisruptionBudgetLister struct {
|
||||
}
|
||||
|
||||
// GetPodPodDisruptionBudgets returns a list of PodDisruptionBudgets matching a pod. Returns an error only if no matching PodDisruptionBudgets are found.
|
||||
func (s *StoreToPodDisruptionBudgetLister) GetPodPodDisruptionBudgets(pod *api.Pod) (pdbList []policy.PodDisruptionBudget, err error) {
|
||||
func (s *StoreToPodDisruptionBudgetLister) GetPodPodDisruptionBudgets(pod *v1.Pod) (pdbList []policy.PodDisruptionBudget, err error) {
|
||||
var selector labels.Selector
|
||||
|
||||
if len(pod.Labels) == 0 {
|
||||
@ -466,13 +467,13 @@ func (s *storageClassLister) List(selector labels.Selector) (ret []*storage.Stor
|
||||
|
||||
// List returns a list of storage classes
|
||||
func (s *storageClassLister) Get(name string) (*storage.StorageClass, error) {
|
||||
key := &storage.StorageClass{ObjectMeta: api.ObjectMeta{Name: name}}
|
||||
key := &storage.StorageClass{ObjectMeta: v1.ObjectMeta{Name: name}}
|
||||
obj, exists, err := s.indexer.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(storage.Resource("storageclass"), name)
|
||||
return nil, errors.NewNotFound(storageinternal.Resource("storageclass"), name)
|
||||
}
|
||||
return obj.(*storage.StorageClass), nil
|
||||
}
|
||||
|
89
pkg/client/cache/listers_core.go
vendored
89
pkg/client/cache/listers_core.go
vendored
@ -21,6 +21,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
@ -40,9 +41,9 @@ type StoreToPodLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToPodLister) List(selector labels.Selector) (ret []*api.Pod, err error) {
|
||||
func (s *StoreToPodLister) List(selector labels.Selector) (ret []*v1.Pod, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Pod))
|
||||
ret = append(ret, m.(*v1.Pod))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
@ -56,14 +57,14 @@ type storePodsNamespacer struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storePodsNamespacer) List(selector labels.Selector) (ret []*api.Pod, err error) {
|
||||
func (s storePodsNamespacer) List(selector labels.Selector) (ret []*v1.Pod, err error) {
|
||||
err = ListAllByNamespace(s.Indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Pod))
|
||||
ret = append(ret, m.(*v1.Pod))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storePodsNamespacer) Get(name string) (*api.Pod, error) {
|
||||
func (s storePodsNamespacer) Get(name string) (*v1.Pod, error) {
|
||||
obj, exists, err := s.Indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -71,7 +72,7 @@ func (s storePodsNamespacer) Get(name string) (*api.Pod, error) {
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("pod"), name)
|
||||
}
|
||||
return obj.(*api.Pod), nil
|
||||
return obj.(*v1.Pod), nil
|
||||
}
|
||||
|
||||
// StoreToServiceLister helps list services
|
||||
@ -79,9 +80,9 @@ type StoreToServiceLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToServiceLister) List(selector labels.Selector) (ret []*api.Service, err error) {
|
||||
func (s *StoreToServiceLister) List(selector labels.Selector) (ret []*v1.Service, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Service))
|
||||
ret = append(ret, m.(*v1.Service))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
@ -95,14 +96,14 @@ type storeServicesNamespacer struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeServicesNamespacer) List(selector labels.Selector) (ret []*api.Service, err error) {
|
||||
func (s storeServicesNamespacer) List(selector labels.Selector) (ret []*v1.Service, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Service))
|
||||
ret = append(ret, m.(*v1.Service))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeServicesNamespacer) Get(name string) (*api.Service, error) {
|
||||
func (s storeServicesNamespacer) Get(name string) (*v1.Service, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -110,12 +111,12 @@ func (s storeServicesNamespacer) Get(name string) (*api.Service, error) {
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("service"), name)
|
||||
}
|
||||
return obj.(*api.Service), nil
|
||||
return obj.(*v1.Service), nil
|
||||
}
|
||||
|
||||
// TODO: Move this back to scheduler as a helper function that takes a Store,
|
||||
// rather than a method of StoreToServiceLister.
|
||||
func (s *StoreToServiceLister) GetPodServices(pod *api.Pod) (services []*api.Service, err error) {
|
||||
func (s *StoreToServiceLister) GetPodServices(pod *v1.Pod) (services []*v1.Service, err error) {
|
||||
allServices, err := s.Services(pod.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -141,9 +142,9 @@ type StoreToReplicationControllerLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToReplicationControllerLister) List(selector labels.Selector) (ret []*api.ReplicationController, err error) {
|
||||
func (s *StoreToReplicationControllerLister) List(selector labels.Selector) (ret []*v1.ReplicationController, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ReplicationController))
|
||||
ret = append(ret, m.(*v1.ReplicationController))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
@ -157,14 +158,14 @@ type storeReplicationControllersNamespacer struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeReplicationControllersNamespacer) List(selector labels.Selector) (ret []*api.ReplicationController, err error) {
|
||||
func (s storeReplicationControllersNamespacer) List(selector labels.Selector) (ret []*v1.ReplicationController, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ReplicationController))
|
||||
ret = append(ret, m.(*v1.ReplicationController))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeReplicationControllersNamespacer) Get(name string) (*api.ReplicationController, error) {
|
||||
func (s storeReplicationControllersNamespacer) Get(name string) (*v1.ReplicationController, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -172,24 +173,24 @@ func (s storeReplicationControllersNamespacer) Get(name string) (*api.Replicatio
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("replicationcontroller"), name)
|
||||
}
|
||||
return obj.(*api.ReplicationController), nil
|
||||
return obj.(*v1.ReplicationController), nil
|
||||
}
|
||||
|
||||
// GetPodControllers returns a list of replication controllers managing a pod. Returns an error only if no matching controllers are found.
|
||||
func (s *StoreToReplicationControllerLister) GetPodControllers(pod *api.Pod) (controllers []*api.ReplicationController, err error) {
|
||||
func (s *StoreToReplicationControllerLister) GetPodControllers(pod *v1.Pod) (controllers []*v1.ReplicationController, err error) {
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no controllers found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
}
|
||||
|
||||
key := &api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: pod.Namespace}}
|
||||
key := &v1.ReplicationController{ObjectMeta: v1.ObjectMeta{Namespace: pod.Namespace}}
|
||||
items, err := s.Indexer.Index(NamespaceIndex, key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, m := range items {
|
||||
rc := m.(*api.ReplicationController)
|
||||
rc := m.(*v1.ReplicationController)
|
||||
selector := labels.Set(rc.Spec.Selector).AsSelectorPreValidated()
|
||||
|
||||
// If an rc with a nil or empty selector creeps in, it should match nothing, not everything.
|
||||
@ -209,9 +210,9 @@ type StoreToServiceAccountLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToServiceAccountLister) List(selector labels.Selector) (ret []*api.ServiceAccount, err error) {
|
||||
func (s *StoreToServiceAccountLister) List(selector labels.Selector) (ret []*v1.ServiceAccount, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ServiceAccount))
|
||||
ret = append(ret, m.(*v1.ServiceAccount))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
@ -225,14 +226,14 @@ type storeServiceAccountsNamespacer struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeServiceAccountsNamespacer) List(selector labels.Selector) (ret []*api.ServiceAccount, err error) {
|
||||
func (s storeServiceAccountsNamespacer) List(selector labels.Selector) (ret []*v1.ServiceAccount, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.ServiceAccount))
|
||||
ret = append(ret, m.(*v1.ServiceAccount))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeServiceAccountsNamespacer) Get(name string) (*api.ServiceAccount, error) {
|
||||
func (s storeServiceAccountsNamespacer) Get(name string) (*v1.ServiceAccount, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -240,7 +241,7 @@ func (s storeServiceAccountsNamespacer) Get(name string) (*api.ServiceAccount, e
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("serviceaccount"), name)
|
||||
}
|
||||
return obj.(*api.ServiceAccount), nil
|
||||
return obj.(*v1.ServiceAccount), nil
|
||||
}
|
||||
|
||||
// StoreToLimitRangeLister helps list limit ranges
|
||||
@ -248,9 +249,9 @@ type StoreToLimitRangeLister struct {
|
||||
Indexer Indexer
|
||||
}
|
||||
|
||||
func (s *StoreToLimitRangeLister) List(selector labels.Selector) (ret []*api.LimitRange, err error) {
|
||||
func (s *StoreToLimitRangeLister) List(selector labels.Selector) (ret []*v1.LimitRange, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.LimitRange))
|
||||
ret = append(ret, m.(*v1.LimitRange))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
@ -261,9 +262,9 @@ type StoreToPersistentVolumeClaimLister struct {
|
||||
}
|
||||
|
||||
// List returns all persistentvolumeclaims that match the specified selector
|
||||
func (s *StoreToPersistentVolumeClaimLister) List(selector labels.Selector) (ret []*api.PersistentVolumeClaim, err error) {
|
||||
func (s *StoreToPersistentVolumeClaimLister) List(selector labels.Selector) (ret []*v1.PersistentVolumeClaim, err error) {
|
||||
err = ListAll(s.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.PersistentVolumeClaim))
|
||||
ret = append(ret, m.(*v1.PersistentVolumeClaim))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
@ -277,14 +278,14 @@ type storeLimitRangesNamespacer struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storeLimitRangesNamespacer) List(selector labels.Selector) (ret []*api.LimitRange, err error) {
|
||||
func (s storeLimitRangesNamespacer) List(selector labels.Selector) (ret []*v1.LimitRange, err error) {
|
||||
err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.LimitRange))
|
||||
ret = append(ret, m.(*v1.LimitRange))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storeLimitRangesNamespacer) Get(name string) (*api.LimitRange, error) {
|
||||
func (s storeLimitRangesNamespacer) Get(name string) (*v1.LimitRange, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -292,7 +293,7 @@ func (s storeLimitRangesNamespacer) Get(name string) (*api.LimitRange, error) {
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("limitrange"), name)
|
||||
}
|
||||
return obj.(*api.LimitRange), nil
|
||||
return obj.(*v1.LimitRange), nil
|
||||
}
|
||||
|
||||
// PersistentVolumeClaims returns all claims in a specified namespace.
|
||||
@ -305,14 +306,14 @@ type storePersistentVolumeClaimsNamespacer struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
func (s storePersistentVolumeClaimsNamespacer) List(selector labels.Selector) (ret []*api.PersistentVolumeClaim, err error) {
|
||||
func (s storePersistentVolumeClaimsNamespacer) List(selector labels.Selector) (ret []*v1.PersistentVolumeClaim, err error) {
|
||||
err = ListAllByNamespace(s.Indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.PersistentVolumeClaim))
|
||||
ret = append(ret, m.(*v1.PersistentVolumeClaim))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (s storePersistentVolumeClaimsNamespacer) Get(name string) (*api.PersistentVolumeClaim, error) {
|
||||
func (s storePersistentVolumeClaimsNamespacer) Get(name string) (*v1.PersistentVolumeClaim, error) {
|
||||
obj, exists, err := s.Indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -320,7 +321,7 @@ func (s storePersistentVolumeClaimsNamespacer) Get(name string) (*api.Persistent
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("persistentvolumeclaims"), name)
|
||||
}
|
||||
return obj.(*api.PersistentVolumeClaim), nil
|
||||
return obj.(*v1.PersistentVolumeClaim), nil
|
||||
}
|
||||
|
||||
// IndexerToNamespaceLister gives an Indexer List method
|
||||
@ -329,14 +330,14 @@ type IndexerToNamespaceLister struct {
|
||||
}
|
||||
|
||||
// List returns a list of namespaces
|
||||
func (i *IndexerToNamespaceLister) List(selector labels.Selector) (ret []*api.Namespace, err error) {
|
||||
func (i *IndexerToNamespaceLister) List(selector labels.Selector) (ret []*v1.Namespace, err error) {
|
||||
err = ListAll(i.Indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*api.Namespace))
|
||||
ret = append(ret, m.(*v1.Namespace))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (i *IndexerToNamespaceLister) Get(name string) (*api.Namespace, error) {
|
||||
func (i *IndexerToNamespaceLister) Get(name string) (*v1.Namespace, error) {
|
||||
obj, exists, err := i.Indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -344,5 +345,5 @@ func (i *IndexerToNamespaceLister) Get(name string) (*api.Namespace, error) {
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(api.Resource("namespace"), name)
|
||||
}
|
||||
return obj.(*api.Namespace), nil
|
||||
return obj.(*v1.Namespace), nil
|
||||
}
|
||||
|
13
pkg/client/cache/listers_extensions.go
vendored
13
pkg/client/cache/listers_extensions.go
vendored
@ -19,10 +19,11 @@ package cache
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensionsinternal "k8s.io/kubernetes/pkg/apis/extensions"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
@ -71,7 +72,7 @@ func (s storeDeploymentsNamespacer) Get(name string) (*extensions.Deployment, er
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(extensions.Resource("deployment"), name)
|
||||
return nil, errors.NewNotFound(extensionsinternal.Resource("deployment"), name)
|
||||
}
|
||||
return obj.(*extensions.Deployment), nil
|
||||
}
|
||||
@ -107,7 +108,7 @@ func (s *StoreToDeploymentLister) GetDeploymentsForReplicaSet(rs *extensions.Rep
|
||||
|
||||
// GetDeploymentsForDeployments returns a list of deployments managing a pod. Returns an error only if no matching deployments are found.
|
||||
// TODO eliminate shallow copies
|
||||
func (s *StoreToDeploymentLister) GetDeploymentsForPod(pod *api.Pod) (deployments []*extensions.Deployment, err error) {
|
||||
func (s *StoreToDeploymentLister) GetDeploymentsForPod(pod *v1.Pod) (deployments []*extensions.Deployment, err error) {
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no deployments found for Pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
@ -172,13 +173,13 @@ func (s storeReplicaSetsNamespacer) Get(name string) (*extensions.ReplicaSet, er
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(extensions.Resource("replicaset"), name)
|
||||
return nil, errors.NewNotFound(extensionsinternal.Resource("replicaset"), name)
|
||||
}
|
||||
return obj.(*extensions.ReplicaSet), nil
|
||||
}
|
||||
|
||||
// GetPodReplicaSets returns a list of ReplicaSets managing a pod. Returns an error only if no matching ReplicaSets are found.
|
||||
func (s *StoreToReplicaSetLister) GetPodReplicaSets(pod *api.Pod) (rss []*extensions.ReplicaSet, err error) {
|
||||
func (s *StoreToReplicaSetLister) GetPodReplicaSets(pod *v1.Pod) (rss []*extensions.ReplicaSet, err error) {
|
||||
if len(pod.Labels) == 0 {
|
||||
err = fmt.Errorf("no ReplicaSets found for pod %v because it has no labels", pod.Name)
|
||||
return
|
||||
|
2
pkg/client/cache/listers_rbac.go
vendored
2
pkg/client/cache/listers_rbac.go
vendored
@ -18,7 +18,7 @@ package cache
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
rbac "k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
)
|
||||
|
||||
|
190
pkg/client/cache/listers_test.go
vendored
190
pkg/client/cache/listers_test.go
vendored
@ -19,10 +19,10 @@ package cache
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apierrors "k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
@ -31,7 +31,7 @@ func TestStoreToNodeLister(t *testing.T) {
|
||||
store := NewStore(MetaNamespaceKeyFunc)
|
||||
ids := sets.NewString("foo", "bar", "baz")
|
||||
for id := range ids {
|
||||
store.Add(&api.Node{ObjectMeta: api.ObjectMeta{Name: id}})
|
||||
store.Add(&v1.Node{ObjectMeta: v1.ObjectMeta{Name: id}})
|
||||
}
|
||||
sml := StoreToNodeLister{store}
|
||||
|
||||
@ -50,44 +50,44 @@ func TestStoreToNodeLister(t *testing.T) {
|
||||
|
||||
func TestStoreToNodeConditionLister(t *testing.T) {
|
||||
store := NewStore(MetaNamespaceKeyFunc)
|
||||
nodes := []*api.Node{
|
||||
nodes := []*v1.Node{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "foo"},
|
||||
Status: v1.NodeStatus{
|
||||
Conditions: []v1.NodeCondition{
|
||||
{
|
||||
Type: api.NodeReady,
|
||||
Status: api.ConditionTrue,
|
||||
Type: v1.NodeReady,
|
||||
Status: v1.ConditionTrue,
|
||||
},
|
||||
{
|
||||
Type: api.NodeOutOfDisk,
|
||||
Status: api.ConditionFalse,
|
||||
Type: v1.NodeOutOfDisk,
|
||||
Status: v1.ConditionFalse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "bar"},
|
||||
Status: v1.NodeStatus{
|
||||
Conditions: []v1.NodeCondition{
|
||||
{
|
||||
Type: api.NodeOutOfDisk,
|
||||
Status: api.ConditionTrue,
|
||||
Type: v1.NodeOutOfDisk,
|
||||
Status: v1.ConditionTrue,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "baz"},
|
||||
Status: api.NodeStatus{
|
||||
Conditions: []api.NodeCondition{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "baz"},
|
||||
Status: v1.NodeStatus{
|
||||
Conditions: []v1.NodeCondition{
|
||||
{
|
||||
Type: api.NodeReady,
|
||||
Status: api.ConditionFalse,
|
||||
Type: v1.NodeReady,
|
||||
Status: v1.ConditionFalse,
|
||||
},
|
||||
{
|
||||
Type: api.NodeOutOfDisk,
|
||||
Status: api.ConditionUnknown,
|
||||
Type: v1.NodeOutOfDisk,
|
||||
Status: v1.ConditionUnknown,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -97,9 +97,9 @@ func TestStoreToNodeConditionLister(t *testing.T) {
|
||||
store.Add(n)
|
||||
}
|
||||
|
||||
predicate := func(node *api.Node) bool {
|
||||
predicate := func(node *v1.Node) bool {
|
||||
for _, cond := range node.Status.Conditions {
|
||||
if cond.Type == api.NodeOutOfDisk && cond.Status == api.ConditionTrue {
|
||||
if cond.Type == v1.NodeOutOfDisk && cond.Status == v1.ConditionTrue {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -126,65 +126,65 @@ func TestStoreToNodeConditionLister(t *testing.T) {
|
||||
func TestStoreToReplicationControllerLister(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
inRCs []*api.ReplicationController
|
||||
list func(StoreToReplicationControllerLister) ([]*api.ReplicationController, error)
|
||||
inRCs []*v1.ReplicationController
|
||||
list func(StoreToReplicationControllerLister) ([]*v1.ReplicationController, error)
|
||||
outRCNames sets.String
|
||||
expectErr bool
|
||||
onlyIfIndexedByNamespace bool
|
||||
}{
|
||||
{
|
||||
description: "Verify we can search all namespaces",
|
||||
inRCs: []*api.ReplicationController{
|
||||
inRCs: []*v1.ReplicationController{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "hmm", Namespace: "hmm"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "hmm", Namespace: "hmm"},
|
||||
},
|
||||
},
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*api.ReplicationController, error) {
|
||||
return lister.ReplicationControllers(api.NamespaceAll).List(labels.Set{}.AsSelectorPreValidated())
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*v1.ReplicationController, error) {
|
||||
return lister.ReplicationControllers(v1.NamespaceAll).List(labels.Set{}.AsSelectorPreValidated())
|
||||
},
|
||||
outRCNames: sets.NewString("hmm", "foo"),
|
||||
},
|
||||
{
|
||||
description: "Verify we can search a specific namespace",
|
||||
inRCs: []*api.ReplicationController{
|
||||
inRCs: []*v1.ReplicationController{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "hmm", Namespace: "hmm"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "hmm", Namespace: "hmm"},
|
||||
},
|
||||
},
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*api.ReplicationController, error) {
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*v1.ReplicationController, error) {
|
||||
return lister.ReplicationControllers("hmm").List(labels.Set{}.AsSelectorPreValidated())
|
||||
},
|
||||
outRCNames: sets.NewString("hmm"),
|
||||
},
|
||||
{
|
||||
description: "Basic listing with all labels and no selectors",
|
||||
inRCs: []*api.ReplicationController{
|
||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||
inRCs: []*v1.ReplicationController{
|
||||
{ObjectMeta: v1.ObjectMeta{Name: "basic"}},
|
||||
},
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*api.ReplicationController, error) {
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*v1.ReplicationController, error) {
|
||||
return lister.List(labels.Everything())
|
||||
},
|
||||
outRCNames: sets.NewString("basic"),
|
||||
},
|
||||
{
|
||||
description: "No pod labels",
|
||||
inRCs: []*api.ReplicationController{
|
||||
inRCs: []*v1.ReplicationController{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
Spec: api.ReplicationControllerSpec{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
Spec: v1.ReplicationControllerSpec{
|
||||
Selector: map[string]string{"foo": "baz"},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*api.ReplicationController, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{Name: "pod1", Namespace: "ns"},
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*v1.ReplicationController, error) {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "pod1", Namespace: "ns"},
|
||||
}
|
||||
return lister.GetPodControllers(pod)
|
||||
},
|
||||
@ -193,14 +193,14 @@ func TestStoreToReplicationControllerLister(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "No RC selectors",
|
||||
inRCs: []*api.ReplicationController{
|
||||
inRCs: []*v1.ReplicationController{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
},
|
||||
},
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*api.ReplicationController, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*v1.ReplicationController, error) {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
Namespace: "ns",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
@ -213,23 +213,23 @@ func TestStoreToReplicationControllerLister(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Matching labels to selectors and namespace",
|
||||
inRCs: []*api.ReplicationController{
|
||||
inRCs: []*v1.ReplicationController{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Spec: api.ReplicationControllerSpec{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "foo"},
|
||||
Spec: v1.ReplicationControllerSpec{
|
||||
Selector: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||
Spec: api.ReplicationControllerSpec{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||
Spec: v1.ReplicationControllerSpec{
|
||||
Selector: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*api.ReplicationController, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
list: func(lister StoreToReplicationControllerLister) ([]*v1.ReplicationController, error) {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
Namespace: "ns",
|
||||
@ -290,7 +290,7 @@ func TestStoreToReplicaSetLister(t *testing.T) {
|
||||
// Basic listing with all labels and no selectors
|
||||
{
|
||||
inRSs: []*extensions.ReplicaSet{
|
||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||
{ObjectMeta: v1.ObjectMeta{Name: "basic"}},
|
||||
},
|
||||
list: func() ([]*extensions.ReplicaSet, error) {
|
||||
return lister.List(labels.Everything())
|
||||
@ -301,15 +301,15 @@ func TestStoreToReplicaSetLister(t *testing.T) {
|
||||
{
|
||||
inRSs: []*extensions.ReplicaSet{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
Spec: extensions.ReplicaSetSpec{
|
||||
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "baz"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func() ([]*extensions.ReplicaSet, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{Name: "pod1", Namespace: "ns"},
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "pod1", Namespace: "ns"},
|
||||
}
|
||||
return lister.GetPodReplicaSets(pod)
|
||||
},
|
||||
@ -320,12 +320,12 @@ func TestStoreToReplicaSetLister(t *testing.T) {
|
||||
{
|
||||
inRSs: []*extensions.ReplicaSet{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
},
|
||||
},
|
||||
list: func() ([]*extensions.ReplicaSet, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
Namespace: "ns",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
@ -340,21 +340,21 @@ func TestStoreToReplicaSetLister(t *testing.T) {
|
||||
{
|
||||
inRSs: []*extensions.ReplicaSet{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "foo"},
|
||||
Spec: extensions.ReplicaSetSpec{
|
||||
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||
Spec: extensions.ReplicaSetSpec{
|
||||
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func() ([]*extensions.ReplicaSet, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
Namespace: "ns",
|
||||
@ -402,7 +402,7 @@ func TestStoreToDaemonSetLister(t *testing.T) {
|
||||
// Basic listing
|
||||
{
|
||||
inDSs: []*extensions.DaemonSet{
|
||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||
{ObjectMeta: v1.ObjectMeta{Name: "basic"}},
|
||||
},
|
||||
list: func() ([]extensions.DaemonSet, error) {
|
||||
list, err := lister.List()
|
||||
@ -413,9 +413,9 @@ func TestStoreToDaemonSetLister(t *testing.T) {
|
||||
// Listing multiple daemon sets
|
||||
{
|
||||
inDSs: []*extensions.DaemonSet{
|
||||
{ObjectMeta: api.ObjectMeta{Name: "basic"}},
|
||||
{ObjectMeta: api.ObjectMeta{Name: "complex"}},
|
||||
{ObjectMeta: api.ObjectMeta{Name: "complex2"}},
|
||||
{ObjectMeta: v1.ObjectMeta{Name: "basic"}},
|
||||
{ObjectMeta: v1.ObjectMeta{Name: "complex"}},
|
||||
{ObjectMeta: v1.ObjectMeta{Name: "complex2"}},
|
||||
},
|
||||
list: func() ([]extensions.DaemonSet, error) {
|
||||
list, err := lister.List()
|
||||
@ -427,15 +427,15 @@ func TestStoreToDaemonSetLister(t *testing.T) {
|
||||
{
|
||||
inDSs: []*extensions.DaemonSet{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
Spec: extensions.DaemonSetSpec{
|
||||
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "baz"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func() ([]extensions.DaemonSet, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{Name: "pod1", Namespace: "ns"},
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "pod1", Namespace: "ns"},
|
||||
}
|
||||
return lister.GetPodDaemonSets(pod)
|
||||
},
|
||||
@ -446,12 +446,12 @@ func TestStoreToDaemonSetLister(t *testing.T) {
|
||||
{
|
||||
inDSs: []*extensions.DaemonSet{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "basic", Namespace: "ns"},
|
||||
},
|
||||
},
|
||||
list: func() ([]extensions.DaemonSet, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
Namespace: "ns",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
@ -466,21 +466,21 @@ func TestStoreToDaemonSetLister(t *testing.T) {
|
||||
{
|
||||
inDSs: []*extensions.DaemonSet{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "foo"},
|
||||
Spec: extensions.DaemonSetSpec{
|
||||
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "bar", Namespace: "ns"},
|
||||
Spec: extensions.DaemonSetSpec{
|
||||
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: func() ([]extensions.DaemonSet, error) {
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
Namespace: "ns",
|
||||
@ -527,25 +527,25 @@ func TestStoreToPodLister(t *testing.T) {
|
||||
for _, store := range stores {
|
||||
ids := []string{"foo", "bar", "baz"}
|
||||
for _, id := range ids {
|
||||
store.Add(&api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
store.Add(&v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "other",
|
||||
Name: id,
|
||||
Labels: map[string]string{"name": id},
|
||||
},
|
||||
})
|
||||
}
|
||||
store.Add(&api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
store.Add(&v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "quux",
|
||||
Namespace: api.NamespaceDefault,
|
||||
Namespace: v1.NamespaceDefault,
|
||||
Labels: map[string]string{"name": "quux"},
|
||||
},
|
||||
})
|
||||
spl := StoreToPodLister{store}
|
||||
|
||||
// Verify that we can always look up by Namespace.
|
||||
defaultPods, err := spl.Pods(api.NamespaceDefault).List(labels.Set{}.AsSelectorPreValidated())
|
||||
defaultPods, err := spl.Pods(v1.NamespaceDefault).List(labels.Set{}.AsSelectorPreValidated())
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
} else if e, a := 1, len(defaultPods); e != a {
|
||||
@ -583,17 +583,17 @@ func TestStoreToPodLister(t *testing.T) {
|
||||
|
||||
func TestStoreToServiceLister(t *testing.T) {
|
||||
store := NewIndexer(MetaNamespaceKeyFunc, Indexers{NamespaceIndex: MetaNamespaceIndexFunc})
|
||||
store.Add(&api.Service{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Spec: api.ServiceSpec{
|
||||
store.Add(&v1.Service{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "foo"},
|
||||
Spec: v1.ServiceSpec{
|
||||
Selector: map[string]string{},
|
||||
},
|
||||
})
|
||||
store.Add(&api.Service{ObjectMeta: api.ObjectMeta{Name: "bar"}})
|
||||
store.Add(&v1.Service{ObjectMeta: v1.ObjectMeta{Name: "bar"}})
|
||||
ssl := StoreToServiceLister{store}
|
||||
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "foopod",
|
||||
Labels: map[string]string{"role": "foo"},
|
||||
},
|
||||
|
23
pkg/client/cache/listwatch.go
vendored
23
pkg/client/cache/listwatch.go
vendored
@ -21,6 +21,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
@ -31,16 +32,16 @@ import (
|
||||
type ListerWatcher interface {
|
||||
// List should return a list type object; the Items field will be extracted, and the
|
||||
// ResourceVersion field will be used to start the watch in the right place.
|
||||
List(options api.ListOptions) (runtime.Object, error)
|
||||
List(options v1.ListOptions) (runtime.Object, error)
|
||||
// Watch should begin a watch at the specified version.
|
||||
Watch(options api.ListOptions) (watch.Interface, error)
|
||||
Watch(options v1.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// ListFunc knows how to list resources
|
||||
type ListFunc func(options api.ListOptions) (runtime.Object, error)
|
||||
type ListFunc func(options v1.ListOptions) (runtime.Object, error)
|
||||
|
||||
// WatchFunc knows how to watch resources
|
||||
type WatchFunc func(options api.ListOptions) (watch.Interface, error)
|
||||
type WatchFunc func(options v1.ListOptions) (watch.Interface, error)
|
||||
|
||||
// ListWatch knows how to list and watch a set of apiserver resources. It satisfies the ListerWatcher interface.
|
||||
// It is a convenience function for users of NewReflector, etc.
|
||||
@ -57,7 +58,7 @@ type Getter interface {
|
||||
|
||||
// NewListWatchFromClient creates a new ListWatch from the specified client, resource, namespace and field selector.
|
||||
func NewListWatchFromClient(c Getter, resource string, namespace string, fieldSelector fields.Selector) *ListWatch {
|
||||
listFunc := func(options api.ListOptions) (runtime.Object, error) {
|
||||
listFunc := func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return c.Get().
|
||||
Namespace(namespace).
|
||||
Resource(resource).
|
||||
@ -66,7 +67,7 @@ func NewListWatchFromClient(c Getter, resource string, namespace string, fieldSe
|
||||
Do().
|
||||
Get()
|
||||
}
|
||||
watchFunc := func(options api.ListOptions) (watch.Interface, error) {
|
||||
watchFunc := func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Get().
|
||||
Prefix("watch").
|
||||
Namespace(namespace).
|
||||
@ -78,7 +79,7 @@ func NewListWatchFromClient(c Getter, resource string, namespace string, fieldSe
|
||||
return &ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}
|
||||
}
|
||||
|
||||
func timeoutFromListOptions(options api.ListOptions) time.Duration {
|
||||
func timeoutFromListOptions(options v1.ListOptions) time.Duration {
|
||||
if options.TimeoutSeconds != nil {
|
||||
return time.Duration(*options.TimeoutSeconds) * time.Second
|
||||
}
|
||||
@ -86,12 +87,12 @@ func timeoutFromListOptions(options api.ListOptions) time.Duration {
|
||||
}
|
||||
|
||||
// List a set of apiserver resources
|
||||
func (lw *ListWatch) List(options api.ListOptions) (runtime.Object, error) {
|
||||
func (lw *ListWatch) List(options v1.ListOptions) (runtime.Object, error) {
|
||||
return lw.ListFunc(options)
|
||||
}
|
||||
|
||||
// Watch a set of apiserver resources
|
||||
func (lw *ListWatch) Watch(options api.ListOptions) (watch.Interface, error) {
|
||||
func (lw *ListWatch) Watch(options v1.ListOptions) (watch.Interface, error) {
|
||||
return lw.WatchFunc(options)
|
||||
}
|
||||
|
||||
@ -101,7 +102,7 @@ func ListWatchUntil(timeout time.Duration, lw ListerWatcher, conditions ...watch
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
list, err := lw.List(api.ListOptions{})
|
||||
list, err := lw.List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -153,7 +154,7 @@ func ListWatchUntil(timeout time.Duration, lw ListerWatcher, conditions ...watch
|
||||
}
|
||||
currResourceVersion := metaObj.GetResourceVersion()
|
||||
|
||||
watchInterface, err := lw.Watch(api.ListOptions{ResourceVersion: currResourceVersion})
|
||||
watchInterface, err := lw.Watch(v1.ListOptions{ResourceVersion: currResourceVersion})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
44
pkg/client/cache/listwatch_test.go
vendored
44
pkg/client/cache/listwatch_test.go
vendored
@ -22,9 +22,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
@ -60,7 +60,7 @@ func buildLocation(resourcePath string, query url.Values) string {
|
||||
}
|
||||
|
||||
func TestListWatchesCanList(t *testing.T) {
|
||||
fieldSelectorQueryParamName := unversioned.FieldSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String())
|
||||
fieldSelectorQueryParamName := unversioned.FieldSelectorQueryParam(registered.GroupOrDie(v1.GroupName).GroupVersion.String())
|
||||
table := []struct {
|
||||
location string
|
||||
resource string
|
||||
@ -69,18 +69,18 @@ func TestListWatchesCanList(t *testing.T) {
|
||||
}{
|
||||
// Node
|
||||
{
|
||||
location: testapi.Default.ResourcePath("nodes", api.NamespaceAll, ""),
|
||||
location: testapi.Default.ResourcePath("nodes", v1.NamespaceAll, ""),
|
||||
resource: "nodes",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: v1.NamespaceAll,
|
||||
fieldSelector: parseSelectorOrDie(""),
|
||||
},
|
||||
// pod with "assigned" field selector.
|
||||
{
|
||||
location: buildLocation(
|
||||
testapi.Default.ResourcePath("pods", api.NamespaceAll, ""),
|
||||
testapi.Default.ResourcePath("pods", v1.NamespaceAll, ""),
|
||||
buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})),
|
||||
resource: "pods",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: v1.NamespaceAll,
|
||||
fieldSelector: fields.Set{"spec.host": ""}.AsSelector(),
|
||||
},
|
||||
// pod in namespace "foo"
|
||||
@ -101,16 +101,16 @@ func TestListWatchesCanList(t *testing.T) {
|
||||
}
|
||||
server := httptest.NewServer(&handler)
|
||||
defer server.Close()
|
||||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion}})
|
||||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: ®istered.GroupOrDie(v1.GroupName).GroupVersion}})
|
||||
lw := NewListWatchFromClient(client.Core().RESTClient(), item.resource, item.namespace, item.fieldSelector)
|
||||
// This test merely tests that the correct request is made.
|
||||
lw.List(api.ListOptions{})
|
||||
lw.List(v1.ListOptions{})
|
||||
handler.ValidateRequest(t, item.location, "GET", nil)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListWatchesCanWatch(t *testing.T) {
|
||||
fieldSelectorQueryParamName := unversioned.FieldSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String())
|
||||
fieldSelectorQueryParamName := unversioned.FieldSelectorQueryParam(registered.GroupOrDie(v1.GroupName).GroupVersion.String())
|
||||
table := []struct {
|
||||
rv string
|
||||
location string
|
||||
@ -121,30 +121,30 @@ func TestListWatchesCanWatch(t *testing.T) {
|
||||
// Node
|
||||
{
|
||||
location: buildLocation(
|
||||
testapi.Default.ResourcePathWithPrefix("watch", "nodes", api.NamespaceAll, ""),
|
||||
testapi.Default.ResourcePathWithPrefix("watch", "nodes", v1.NamespaceAll, ""),
|
||||
buildQueryValues(url.Values{})),
|
||||
rv: "",
|
||||
resource: "nodes",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: v1.NamespaceAll,
|
||||
fieldSelector: parseSelectorOrDie(""),
|
||||
},
|
||||
{
|
||||
location: buildLocation(
|
||||
testapi.Default.ResourcePathWithPrefix("watch", "nodes", api.NamespaceAll, ""),
|
||||
testapi.Default.ResourcePathWithPrefix("watch", "nodes", v1.NamespaceAll, ""),
|
||||
buildQueryValues(url.Values{"resourceVersion": []string{"42"}})),
|
||||
rv: "42",
|
||||
resource: "nodes",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: v1.NamespaceAll,
|
||||
fieldSelector: parseSelectorOrDie(""),
|
||||
},
|
||||
// pod with "assigned" field selector.
|
||||
{
|
||||
location: buildLocation(
|
||||
testapi.Default.ResourcePathWithPrefix("watch", "pods", api.NamespaceAll, ""),
|
||||
testapi.Default.ResourcePathWithPrefix("watch", "pods", v1.NamespaceAll, ""),
|
||||
buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}})),
|
||||
rv: "0",
|
||||
resource: "pods",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: v1.NamespaceAll,
|
||||
fieldSelector: fields.Set{"spec.host": ""}.AsSelector(),
|
||||
},
|
||||
// pod with namespace foo and assigned field selector
|
||||
@ -167,10 +167,10 @@ func TestListWatchesCanWatch(t *testing.T) {
|
||||
}
|
||||
server := httptest.NewServer(&handler)
|
||||
defer server.Close()
|
||||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion}})
|
||||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: ®istered.GroupOrDie(v1.GroupName).GroupVersion}})
|
||||
lw := NewListWatchFromClient(client.Core().RESTClient(), item.resource, item.namespace, item.fieldSelector)
|
||||
// This test merely tests that the correct request is made.
|
||||
lw.Watch(api.ListOptions{ResourceVersion: item.rv})
|
||||
lw.Watch(v1.ListOptions{ResourceVersion: item.rv})
|
||||
handler.ValidateRequest(t, item.location, "GET", nil)
|
||||
}
|
||||
}
|
||||
@ -180,22 +180,22 @@ type lw struct {
|
||||
watch watch.Interface
|
||||
}
|
||||
|
||||
func (w lw) List(options api.ListOptions) (runtime.Object, error) {
|
||||
func (w lw) List(options v1.ListOptions) (runtime.Object, error) {
|
||||
return w.list, nil
|
||||
}
|
||||
|
||||
func (w lw) Watch(options api.ListOptions) (watch.Interface, error) {
|
||||
func (w lw) Watch(options v1.ListOptions) (watch.Interface, error) {
|
||||
return w.watch, nil
|
||||
}
|
||||
|
||||
func TestListWatchUntil(t *testing.T) {
|
||||
fw := watch.NewFake()
|
||||
go func() {
|
||||
var obj *api.Pod
|
||||
var obj *v1.Pod
|
||||
fw.Modify(obj)
|
||||
}()
|
||||
listwatch := lw{
|
||||
list: &api.PodList{Items: []api.Pod{{}}},
|
||||
list: &v1.PodList{Items: []v1.Pod{{}}},
|
||||
watch: fw,
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ func TestListWatchUntil(t *testing.T) {
|
||||
if lastEvent.Type != watch.Modified {
|
||||
t.Fatalf("expected MODIFIED event type, got %v", lastEvent.Type)
|
||||
}
|
||||
if got, isPod := lastEvent.Object.(*api.Pod); !isPod {
|
||||
if got, isPod := lastEvent.Object.(*v1.Pod); !isPod {
|
||||
t.Fatalf("expected a pod event, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
14
pkg/client/cache/mutation_detector_test.go
vendored
14
pkg/client/cache/mutation_detector_test.go
vendored
@ -22,7 +22,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
@ -30,15 +30,15 @@ import (
|
||||
func TestMutationDetector(t *testing.T) {
|
||||
fakeWatch := watch.NewFake()
|
||||
lw := &testLW{
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return fakeWatch, nil
|
||||
},
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
return &api.PodList{}, nil
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{}, nil
|
||||
},
|
||||
}
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "anything",
|
||||
Labels: map[string]string{"check": "foo"},
|
||||
},
|
||||
@ -48,7 +48,7 @@ func TestMutationDetector(t *testing.T) {
|
||||
addReceived := make(chan bool)
|
||||
mutationFound := make(chan bool)
|
||||
|
||||
informer := NewSharedInformer(lw, &api.Pod{}, 1*time.Second).(*sharedIndexInformer)
|
||||
informer := NewSharedInformer(lw, &v1.Pod{}, 1*time.Second).(*sharedIndexInformer)
|
||||
informer.cacheMutationDetector = &defaultCacheMutationDetector{
|
||||
name: "name",
|
||||
period: 1 * time.Second,
|
||||
|
6
pkg/client/cache/reflector.go
vendored
6
pkg/client/cache/reflector.go
vendored
@ -34,9 +34,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
@ -239,7 +239,7 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
// Explicitly set "0" as resource version - it's fine for the List()
|
||||
// to be served from cache and potentially be delayed relative to
|
||||
// etcd contents. Reflector framework will catch up via Watch() eventually.
|
||||
options := api.ListOptions{ResourceVersion: "0"}
|
||||
options := v1.ListOptions{ResourceVersion: "0"}
|
||||
list, err := r.listerWatcher.List(options)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: Failed to list %v: %v", r.name, r.expectedType, err)
|
||||
@ -278,7 +278,7 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
|
||||
for {
|
||||
timemoutseconds := int64(minWatchTimeout.Seconds() * (rand.Float64() + 1.0))
|
||||
options = api.ListOptions{
|
||||
options = v1.ListOptions{
|
||||
ResourceVersion: resourceVersion,
|
||||
// We want to avoid situations of hanging watchers. Stop any wachers that do not
|
||||
// receive any events within the timeout window.
|
||||
|
98
pkg/client/cache/reflector_test.go
vendored
98
pkg/client/cache/reflector_test.go
vendored
@ -24,8 +24,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
@ -34,27 +34,27 @@ import (
|
||||
var nevererrc chan error
|
||||
|
||||
type testLW struct {
|
||||
ListFunc func(options api.ListOptions) (runtime.Object, error)
|
||||
WatchFunc func(options api.ListOptions) (watch.Interface, error)
|
||||
ListFunc func(options v1.ListOptions) (runtime.Object, error)
|
||||
WatchFunc func(options v1.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
func (t *testLW) List(options api.ListOptions) (runtime.Object, error) {
|
||||
func (t *testLW) List(options v1.ListOptions) (runtime.Object, error) {
|
||||
return t.ListFunc(options)
|
||||
}
|
||||
func (t *testLW) Watch(options api.ListOptions) (watch.Interface, error) {
|
||||
func (t *testLW) Watch(options v1.ListOptions) (watch.Interface, error) {
|
||||
return t.WatchFunc(options)
|
||||
}
|
||||
|
||||
func TestCloseWatchChannelOnError(t *testing.T) {
|
||||
r := NewReflector(&testLW{}, &api.Pod{}, NewStore(MetaNamespaceKeyFunc), 0)
|
||||
pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}}
|
||||
r := NewReflector(&testLW{}, &v1.Pod{}, NewStore(MetaNamespaceKeyFunc), 0)
|
||||
pod := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "bar"}}
|
||||
fw := watch.NewFake()
|
||||
r.listerWatcher = &testLW{
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return fw, nil
|
||||
},
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil
|
||||
},
|
||||
}
|
||||
go r.ListAndWatch(wait.NeverStop)
|
||||
@ -73,20 +73,20 @@ func TestCloseWatchChannelOnError(t *testing.T) {
|
||||
func TestRunUntil(t *testing.T) {
|
||||
stopCh := make(chan struct{})
|
||||
store := NewStore(MetaNamespaceKeyFunc)
|
||||
r := NewReflector(&testLW{}, &api.Pod{}, store, 0)
|
||||
r := NewReflector(&testLW{}, &v1.Pod{}, store, 0)
|
||||
fw := watch.NewFake()
|
||||
r.listerWatcher = &testLW{
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return fw, nil
|
||||
},
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil
|
||||
},
|
||||
}
|
||||
r.RunUntil(stopCh)
|
||||
// Synchronously add a dummy pod into the watch channel so we
|
||||
// know the RunUntil go routine is in the watch handler.
|
||||
fw.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}})
|
||||
fw.Add(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "bar"}})
|
||||
close(stopCh)
|
||||
select {
|
||||
case _, ok := <-fw.ResultChan():
|
||||
@ -101,7 +101,7 @@ func TestRunUntil(t *testing.T) {
|
||||
|
||||
func TestReflectorResyncChan(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &api.Pod{}, s, time.Millisecond)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, time.Millisecond)
|
||||
a, _ := g.resyncChan()
|
||||
b := time.After(wait.ForeverTestTimeout)
|
||||
select {
|
||||
@ -114,7 +114,7 @@ func TestReflectorResyncChan(t *testing.T) {
|
||||
|
||||
func BenchmarkReflectorResyncChanMany(b *testing.B) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &api.Pod{}, s, 25*time.Millisecond)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 25*time.Millisecond)
|
||||
// The improvement to this (calling the timer's Stop() method) makes
|
||||
// this benchmark about 40% faster.
|
||||
for i := 0; i < b.N; i++ {
|
||||
@ -126,7 +126,7 @@ func BenchmarkReflectorResyncChanMany(b *testing.B) {
|
||||
|
||||
func TestReflectorWatchHandlerError(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &api.Pod{}, s, 0)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
fw := watch.NewFake()
|
||||
go func() {
|
||||
fw.Stop()
|
||||
@ -140,15 +140,15 @@ func TestReflectorWatchHandlerError(t *testing.T) {
|
||||
|
||||
func TestReflectorWatchHandler(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &api.Pod{}, s, 0)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
fw := watch.NewFake()
|
||||
s.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}})
|
||||
s.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}})
|
||||
s.Add(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "foo"}})
|
||||
s.Add(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "bar"}})
|
||||
go func() {
|
||||
fw.Add(&api.Service{ObjectMeta: api.ObjectMeta{Name: "rejected"}})
|
||||
fw.Delete(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}})
|
||||
fw.Modify(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "55"}})
|
||||
fw.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "32"}})
|
||||
fw.Add(&v1.Service{ObjectMeta: v1.ObjectMeta{Name: "rejected"}})
|
||||
fw.Delete(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "foo"}})
|
||||
fw.Modify(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "bar", ResourceVersion: "55"}})
|
||||
fw.Add(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "baz", ResourceVersion: "32"}})
|
||||
fw.Stop()
|
||||
}()
|
||||
var resumeRV string
|
||||
@ -157,12 +157,12 @@ func TestReflectorWatchHandler(t *testing.T) {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
mkPod := func(id string, rv string) *api.Pod {
|
||||
return &api.Pod{ObjectMeta: api.ObjectMeta{Name: id, ResourceVersion: rv}}
|
||||
mkPod := func(id string, rv string) *v1.Pod {
|
||||
return &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: id, ResourceVersion: rv}}
|
||||
}
|
||||
|
||||
table := []struct {
|
||||
Pod *api.Pod
|
||||
Pod *v1.Pod
|
||||
exists bool
|
||||
}{
|
||||
{mkPod("foo", ""), false},
|
||||
@ -178,7 +178,7 @@ func TestReflectorWatchHandler(t *testing.T) {
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
if e, a := item.Pod.ResourceVersion, obj.(*api.Pod).ResourceVersion; e != a {
|
||||
if e, a := item.Pod.ResourceVersion, obj.(*v1.Pod).ResourceVersion; e != a {
|
||||
t.Errorf("%v: expected %v, got %v", item.Pod, e, a)
|
||||
}
|
||||
}
|
||||
@ -196,7 +196,7 @@ func TestReflectorWatchHandler(t *testing.T) {
|
||||
|
||||
func TestReflectorStopWatch(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &api.Pod{}, s, 0)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
fw := watch.NewFake()
|
||||
var resumeRV string
|
||||
stopWatch := make(chan struct{}, 1)
|
||||
@ -215,7 +215,7 @@ func TestReflectorListAndWatch(t *testing.T) {
|
||||
// inject an error.
|
||||
expectedRVs := []string{"1", "3"}
|
||||
lw := &testLW{
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
rv := options.ResourceVersion
|
||||
fw := watch.NewFake()
|
||||
if e, a := expectedRVs[0], rv; e != a {
|
||||
@ -227,12 +227,12 @@ func TestReflectorListAndWatch(t *testing.T) {
|
||||
go func() { createdFakes <- fw }()
|
||||
return fw, nil
|
||||
},
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil
|
||||
},
|
||||
}
|
||||
s := NewFIFO(MetaNamespaceKeyFunc)
|
||||
r := NewReflector(lw, &api.Pod{}, s, 0)
|
||||
r := NewReflector(lw, &v1.Pod{}, s, 0)
|
||||
go r.ListAndWatch(wait.NeverStop)
|
||||
|
||||
ids := []string{"foo", "bar", "baz", "qux", "zoo"}
|
||||
@ -242,7 +242,7 @@ func TestReflectorListAndWatch(t *testing.T) {
|
||||
fw = <-createdFakes
|
||||
}
|
||||
sendingRV := strconv.FormatUint(uint64(i+2), 10)
|
||||
fw.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: id, ResourceVersion: sendingRV}})
|
||||
fw.Add(&v1.Pod{ObjectMeta: v1.ObjectMeta{Name: id, ResourceVersion: sendingRV}})
|
||||
if sendingRV == "3" {
|
||||
// Inject a failure.
|
||||
fw.Stop()
|
||||
@ -252,7 +252,7 @@ func TestReflectorListAndWatch(t *testing.T) {
|
||||
|
||||
// Verify we received the right ids with the right resource versions.
|
||||
for i, id := range ids {
|
||||
pod := Pop(s).(*api.Pod)
|
||||
pod := Pop(s).(*v1.Pod)
|
||||
if e, a := id, pod.Name; e != a {
|
||||
t.Errorf("%v: Expected %v, got %v", i, e, a)
|
||||
}
|
||||
@ -267,18 +267,18 @@ func TestReflectorListAndWatch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReflectorListAndWatchWithErrors(t *testing.T) {
|
||||
mkPod := func(id string, rv string) *api.Pod {
|
||||
return &api.Pod{ObjectMeta: api.ObjectMeta{Name: id, ResourceVersion: rv}}
|
||||
mkPod := func(id string, rv string) *v1.Pod {
|
||||
return &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: id, ResourceVersion: rv}}
|
||||
}
|
||||
mkList := func(rv string, pods ...*api.Pod) *api.PodList {
|
||||
list := &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: rv}}
|
||||
mkList := func(rv string, pods ...*v1.Pod) *v1.PodList {
|
||||
list := &v1.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: rv}}
|
||||
for _, pod := range pods {
|
||||
list.Items = append(list.Items, *pod)
|
||||
}
|
||||
return list
|
||||
}
|
||||
table := []struct {
|
||||
list *api.PodList
|
||||
list *v1.PodList
|
||||
listErr error
|
||||
events []watch.Event
|
||||
watchErr error
|
||||
@ -317,7 +317,7 @@ func TestReflectorListAndWatchWithErrors(t *testing.T) {
|
||||
current := s.List()
|
||||
checkMap := map[string]string{}
|
||||
for _, item := range current {
|
||||
pod := item.(*api.Pod)
|
||||
pod := item.(*v1.Pod)
|
||||
checkMap[pod.Name] = pod.ResourceVersion
|
||||
}
|
||||
for _, pod := range item.list.Items {
|
||||
@ -331,7 +331,7 @@ func TestReflectorListAndWatchWithErrors(t *testing.T) {
|
||||
}
|
||||
watchRet, watchErr := item.events, item.watchErr
|
||||
lw := &testLW{
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if watchErr != nil {
|
||||
return nil, watchErr
|
||||
}
|
||||
@ -345,11 +345,11 @@ func TestReflectorListAndWatchWithErrors(t *testing.T) {
|
||||
}()
|
||||
return fw, nil
|
||||
},
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return item.list, item.listErr
|
||||
},
|
||||
}
|
||||
r := NewReflector(lw, &api.Pod{}, s, 0)
|
||||
r := NewReflector(lw, &v1.Pod{}, s, 0)
|
||||
r.ListAndWatch(wait.NeverStop)
|
||||
}
|
||||
}
|
||||
@ -369,16 +369,16 @@ func TestReflectorResync(t *testing.T) {
|
||||
}
|
||||
|
||||
lw := &testLW{
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
fw := watch.NewFake()
|
||||
return fw, nil
|
||||
},
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "0"}}, nil
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "0"}}, nil
|
||||
},
|
||||
}
|
||||
resyncPeriod := 1 * time.Millisecond
|
||||
r := NewReflector(lw, &api.Pod{}, s, resyncPeriod)
|
||||
r := NewReflector(lw, &v1.Pod{}, s, resyncPeriod)
|
||||
if err := r.ListAndWatch(stopCh); err != nil {
|
||||
// error from Resync is not propaged up to here.
|
||||
t.Errorf("expected error %v", err)
|
||||
|
@ -41,6 +41,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apimachinery/registered:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
@ -148,14 +149,47 @@ type EventSinkImpl struct {
|
||||
Interface EventInterface
|
||||
}
|
||||
|
||||
func (e *EventSinkImpl) Create(event *api.Event) (*api.Event, error) {
|
||||
return e.Interface.CreateWithEventNamespace(event)
|
||||
func (e *EventSinkImpl) Create(event *v1.Event) (*v1.Event, error) {
|
||||
internalEvent := &api.Event{}
|
||||
err := v1.Convert_v1_Event_To_api_Event(event, internalEvent, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = e.Interface.CreateWithEventNamespace(internalEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (e *EventSinkImpl) Update(event *api.Event) (*api.Event, error) {
|
||||
return e.Interface.UpdateWithEventNamespace(event)
|
||||
func (e *EventSinkImpl) Update(event *v1.Event) (*v1.Event, error) {
|
||||
internalEvent := &api.Event{}
|
||||
err := v1.Convert_v1_Event_To_api_Event(event, internalEvent, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = e.Interface.UpdateWithEventNamespace(internalEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (e *EventSinkImpl) Patch(event *api.Event, data []byte) (*api.Event, error) {
|
||||
return e.Interface.PatchWithEventNamespace(event, data)
|
||||
func (e *EventSinkImpl) Patch(event *v1.Event, data []byte) (*v1.Event, error) {
|
||||
internalEvent := &api.Event{}
|
||||
err := v1.Convert_v1_Event_To_api_Event(event, internalEvent, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
internalEvent, err = e.Interface.PatchWithEventNamespace(internalEvent, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
externalEvent := &v1.Event{}
|
||||
err = v1.Convert_api_Event_To_v1_Event(internalEvent, externalEvent, nil)
|
||||
if err != nil {
|
||||
// Patch succeeded, no need to report the failed conversion
|
||||
return event, nil
|
||||
}
|
||||
return externalEvent, nil
|
||||
}
|
||||
|
23
pkg/client/conditions/BUILD
Normal file
23
pkg/client/conditions/BUILD
Normal file
@ -0,0 +1,23 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["conditions.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/watch:go_default_library",
|
||||
],
|
||||
)
|
164
pkg/client/conditions/conditions.go
Normal file
164
pkg/client/conditions/conditions.go
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright 2014 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 conditions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
// ErrPodCompleted is returned by PodRunning or PodContainerRunning to indicate that
|
||||
// the pod has already reached completed state.
|
||||
var ErrPodCompleted = fmt.Errorf("pod ran to completion")
|
||||
|
||||
// ErrContainerTerminated is returned by PodContainerRunning in the intermediate
|
||||
// state where the pod indicates it's still running, but its container is already terminated
|
||||
var ErrContainerTerminated = fmt.Errorf("container terminated")
|
||||
|
||||
// PodRunning returns true if the pod is running, false if the pod has not yet reached running state,
|
||||
// returns ErrPodCompleted if the pod has run to completion, or an error in any other case.
|
||||
func PodRunning(event watch.Event) (bool, error) {
|
||||
switch event.Type {
|
||||
case watch.Deleted:
|
||||
return false, errors.NewNotFound(unversioned.GroupResource{Resource: "pods"}, "")
|
||||
}
|
||||
switch t := event.Object.(type) {
|
||||
case *v1.Pod:
|
||||
switch t.Status.Phase {
|
||||
case v1.PodRunning:
|
||||
return true, nil
|
||||
case v1.PodFailed, v1.PodSucceeded:
|
||||
return false, ErrPodCompleted
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PodCompleted returns true if the pod has run to completion, false if the pod has not yet
|
||||
// reached running state, or an error in any other case.
|
||||
func PodCompleted(event watch.Event) (bool, error) {
|
||||
switch event.Type {
|
||||
case watch.Deleted:
|
||||
return false, errors.NewNotFound(unversioned.GroupResource{Resource: "pods"}, "")
|
||||
}
|
||||
switch t := event.Object.(type) {
|
||||
case *v1.Pod:
|
||||
switch t.Status.Phase {
|
||||
case v1.PodFailed, v1.PodSucceeded:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PodRunningAndReady returns true if the pod is running and ready, false if the pod has not
|
||||
// yet reached those states, returns ErrPodCompleted if the pod has run to completion, or
|
||||
// an error in any other case.
|
||||
func PodRunningAndReady(event watch.Event) (bool, error) {
|
||||
switch event.Type {
|
||||
case watch.Deleted:
|
||||
return false, errors.NewNotFound(unversioned.GroupResource{Resource: "pods"}, "")
|
||||
}
|
||||
switch t := event.Object.(type) {
|
||||
case *v1.Pod:
|
||||
switch t.Status.Phase {
|
||||
case v1.PodFailed, v1.PodSucceeded:
|
||||
return false, ErrPodCompleted
|
||||
case v1.PodRunning:
|
||||
return v1.IsPodReady(t), nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PodNotPending returns true if the pod has left the pending state, false if it has not,
|
||||
// or an error in any other case (such as if the pod was deleted).
|
||||
func PodNotPending(event watch.Event) (bool, error) {
|
||||
switch event.Type {
|
||||
case watch.Deleted:
|
||||
return false, errors.NewNotFound(unversioned.GroupResource{Resource: "pods"}, "")
|
||||
}
|
||||
switch t := event.Object.(type) {
|
||||
case *v1.Pod:
|
||||
switch t.Status.Phase {
|
||||
case v1.PodPending:
|
||||
return false, nil
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PodContainerRunning returns false until the named container has ContainerStatus running (at least once),
|
||||
// and will return an error if the pod is deleted, runs to completion, or the container pod is not available.
|
||||
func PodContainerRunning(containerName string) watch.ConditionFunc {
|
||||
return func(event watch.Event) (bool, error) {
|
||||
switch event.Type {
|
||||
case watch.Deleted:
|
||||
return false, errors.NewNotFound(unversioned.GroupResource{Resource: "pods"}, "")
|
||||
}
|
||||
switch t := event.Object.(type) {
|
||||
case *v1.Pod:
|
||||
switch t.Status.Phase {
|
||||
case v1.PodRunning, v1.PodPending:
|
||||
case v1.PodFailed, v1.PodSucceeded:
|
||||
return false, ErrPodCompleted
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
for _, s := range t.Status.ContainerStatuses {
|
||||
if s.Name != containerName {
|
||||
continue
|
||||
}
|
||||
if s.State.Terminated != nil {
|
||||
return false, ErrContainerTerminated
|
||||
}
|
||||
return s.State.Running != nil, nil
|
||||
}
|
||||
for _, s := range t.Status.InitContainerStatuses {
|
||||
if s.Name != containerName {
|
||||
continue
|
||||
}
|
||||
if s.State.Terminated != nil {
|
||||
return false, ErrContainerTerminated
|
||||
}
|
||||
return s.State.Running != nil, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceAccountHasSecrets returns true if the service account has at least one secret,
|
||||
// false if it does not, or an error.
|
||||
func ServiceAccountHasSecrets(event watch.Event) (bool, error) {
|
||||
switch event.Type {
|
||||
case watch.Deleted:
|
||||
return false, errors.NewNotFound(unversioned.GroupResource{Resource: "serviceaccounts"}, "")
|
||||
}
|
||||
switch t := event.Object.(type) {
|
||||
case *v1.ServiceAccount:
|
||||
return len(t.Secrets) > 0, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
@ -32,10 +32,10 @@ go_test(
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/fake:go_default_library",
|
||||
"//pkg/client/leaderelection/resourcelock:go_default_library",
|
||||
"//pkg/client/record:go_default_library",
|
||||
"//pkg/client/testing/core:go_default_library",
|
||||
|
@ -26,10 +26,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
fakeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
fakeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/fake"
|
||||
rl "k8s.io/kubernetes/pkg/client/leaderelection/resourcelock"
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||
@ -67,7 +67,7 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "create",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, action.(core.CreateAction).GetObject().(*api.Endpoints), nil
|
||||
return true, action.(core.CreateAction).GetObject().(*v1.Endpoints), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -83,8 +83,8 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "get",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, &api.Endpoints{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
return true, &v1.Endpoints{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: action.GetNamespace(),
|
||||
Name: action.(core.GetAction).GetName(),
|
||||
},
|
||||
@ -94,7 +94,7 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "update",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, action.(core.CreateAction).GetObject().(*api.Endpoints), nil
|
||||
return true, action.(core.CreateAction).GetObject().(*v1.Endpoints), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -112,8 +112,8 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "get",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, &api.Endpoints{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
return true, &v1.Endpoints{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: action.GetNamespace(),
|
||||
Name: action.(core.GetAction).GetName(),
|
||||
Annotations: map[string]string{
|
||||
@ -126,7 +126,7 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "update",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, action.(core.CreateAction).GetObject().(*api.Endpoints), nil
|
||||
return true, action.(core.CreateAction).GetObject().(*v1.Endpoints), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -146,8 +146,8 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "get",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, &api.Endpoints{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
return true, &v1.Endpoints{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: action.GetNamespace(),
|
||||
Name: action.(core.GetAction).GetName(),
|
||||
Annotations: map[string]string{
|
||||
@ -172,8 +172,8 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "get",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, &api.Endpoints{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
return true, &v1.Endpoints{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: action.GetNamespace(),
|
||||
Name: action.(core.GetAction).GetName(),
|
||||
Annotations: map[string]string{
|
||||
@ -186,7 +186,7 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
{
|
||||
verb: "update",
|
||||
reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, action.(core.CreateAction).GetObject().(*api.Endpoints), nil
|
||||
return true, action.(core.CreateAction).GetObject().(*v1.Endpoints), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -205,7 +205,7 @@ func TestTryAcquireOrRenew(t *testing.T) {
|
||||
var reportedLeader string
|
||||
|
||||
lock := rl.EndpointsLock{
|
||||
EndpointsMeta: api.ObjectMeta{Namespace: "foo", Name: "bar"},
|
||||
EndpointsMeta: v1.ObjectMeta{Namespace: "foo", Name: "bar"},
|
||||
LockConfig: rl.ResourceLockConfig{
|
||||
Identity: "baz",
|
||||
EventRecorder: &record.FakeRecorder{},
|
||||
|
@ -18,9 +18,9 @@ go_library(
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/record:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -21,17 +21,17 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
)
|
||||
|
||||
type EndpointsLock struct {
|
||||
// EndpointsMeta should contain a Name and a Namespace of an
|
||||
// Endpoints object that the LeaderElector will attempt to lead.
|
||||
EndpointsMeta api.ObjectMeta
|
||||
EndpointsMeta v1.ObjectMeta
|
||||
Client clientset.Interface
|
||||
LockConfig ResourceLockConfig
|
||||
e *api.Endpoints
|
||||
e *v1.Endpoints
|
||||
}
|
||||
|
||||
func (el *EndpointsLock) Get() (*LeaderElectionRecord, error) {
|
||||
@ -58,8 +58,8 @@ func (el *EndpointsLock) Create(ler LeaderElectionRecord) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
el.e, err = el.Client.Core().Endpoints(el.EndpointsMeta.Namespace).Create(&api.Endpoints{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
el.e, err = el.Client.Core().Endpoints(el.EndpointsMeta.Namespace).Create(&v1.Endpoints{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: el.EndpointsMeta.Name,
|
||||
Namespace: el.EndpointsMeta.Namespace,
|
||||
Annotations: map[string]string{
|
||||
@ -87,7 +87,7 @@ func (el *EndpointsLock) Update(ler LeaderElectionRecord) error {
|
||||
// RecordEvent in leader election while adding meta-data
|
||||
func (el *EndpointsLock) RecordEvent(s string) {
|
||||
events := fmt.Sprintf("%v %v", el.LockConfig.Identity, s)
|
||||
el.LockConfig.EventRecorder.Eventf(&api.Endpoints{ObjectMeta: el.e.ObjectMeta}, api.EventTypeNormal, "LeaderElection", events)
|
||||
el.LockConfig.EventRecorder.Eventf(&v1.Endpoints{ObjectMeta: el.e.ObjectMeta}, v1.EventTypeNormal, "LeaderElection", events)
|
||||
}
|
||||
|
||||
// Describe is used to convert details on current resource lock
|
||||
|
@ -15,10 +15,13 @@ go_library(
|
||||
srcs = [
|
||||
"expansion_generated.go",
|
||||
"job.go",
|
||||
"job_expansion.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/errors:go_default_library",
|
||||
"//pkg/api/unversioned:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/batch:go_default_library",
|
||||
"//pkg/apis/batch/v1:go_default_library",
|
||||
"//pkg/client/cache:go_default_library",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user