From 8a3ed48808185ec410a7450796da790790e1d3bd Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 14 Apr 2016 10:45:29 -0700 Subject: [PATCH] Added Hostname and Subdomain field to Pod.Spec --- api/swagger-spec/apps_v1alpha1.json | 8 + api/swagger-spec/batch_v1.json | 8 + api/swagger-spec/extensions_v1beta1.json | 8 + api/swagger-spec/v1.json | 12 + cluster/addons/dns/README.md | 35 +- cluster/addons/dns/kube2sky/kube2sky.go | 51 ++- cluster/addons/dns/skydns-rc.yaml.in | 2 +- .../autoscaling/v1/definitions.html | 2 +- .../autoscaling/v1/operations.html | 2 +- docs/api-reference/batch/v1/definitions.html | 16 +- docs/api-reference/batch/v1/operations.html | 2 +- .../extensions/v1beta1/definitions.html | 16 +- .../extensions/v1beta1/operations.html | 2 +- docs/api-reference/v1/definitions.html | 23 +- docs/api-reference/v1/operations.html | 2 +- pkg/api/deep_copy_generated.go | 3 + pkg/api/endpoints/util.go | 2 + pkg/api/pod/util.go | 2 + pkg/api/types.generated.go | 364 +++++++++++----- pkg/api/types.go | 10 +- pkg/api/v1/conversion.go | 5 +- pkg/api/v1/conversion_generated.go | 4 + pkg/api/v1/deep_copy_generated.go | 3 + pkg/api/v1/generated.pb.go | 109 +++++ pkg/api/v1/generated.proto | 11 + pkg/api/v1/types.generated.go | 408 ++++++++++++------ pkg/api/v1/types.go | 9 +- pkg/api/v1/types_swagger_doc_generated.go | 3 + pkg/api/validation/validation.go | 19 +- pkg/apis/apps/types.generated.go | 2 +- pkg/apis/apps/v1alpha1/types.generated.go | 2 +- pkg/apis/batch/types.generated.go | 2 +- pkg/apis/batch/v1/types.generated.go | 2 +- pkg/apis/extensions/types.generated.go | 6 +- .../extensions/v1beta1/types.generated.go | 8 +- .../endpoint/endpoints_controller.go | 65 +-- pkg/kubelet/container/helpers.go | 2 +- pkg/kubelet/dockertools/manager_test.go | 4 +- pkg/kubelet/kubelet.go | 39 +- pkg/kubelet/rkt/fake_rkt_interface_test.go | 4 +- pkg/kubelet/rkt/rkt.go | 6 +- test/e2e/dns.go | 39 +- 42 files changed, 979 insertions(+), 343 deletions(-) diff --git a/api/swagger-spec/apps_v1alpha1.json b/api/swagger-spec/apps_v1alpha1.json index c33c0e49b88..7983e6b00cf 100644 --- a/api/swagger-spec/apps_v1alpha1.json +++ b/api/swagger-spec/apps_v1alpha1.json @@ -1160,6 +1160,14 @@ "$ref": "v1.LocalObjectReference" }, "description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod" + }, + "hostname": { + "type": "string", + "description": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value." + }, + "subdomain": { + "type": "string", + "description": "If specified, the fully qualified Pod hostname will be \"\u003chostname\u003e.\u003csubdomain\u003e.\u003cpod namespace\u003e.svc.\u003ccluster domain\u003e\". If not specified, the pod will not have a domainname at all." } } }, diff --git a/api/swagger-spec/batch_v1.json b/api/swagger-spec/batch_v1.json index 2d1ad338cf6..fa7b2082c5e 100644 --- a/api/swagger-spec/batch_v1.json +++ b/api/swagger-spec/batch_v1.json @@ -1165,6 +1165,14 @@ "$ref": "v1.LocalObjectReference" }, "description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod" + }, + "hostname": { + "type": "string", + "description": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value." + }, + "subdomain": { + "type": "string", + "description": "If specified, the fully qualified Pod hostname will be \"\u003chostname\u003e.\u003csubdomain\u003e.\u003cpod namespace\u003e.svc.\u003ccluster domain\u003e\". If not specified, the pod will not have a domainname at all." } } }, diff --git a/api/swagger-spec/extensions_v1beta1.json b/api/swagger-spec/extensions_v1beta1.json index da9fe368338..08a3aac7f29 100644 --- a/api/swagger-spec/extensions_v1beta1.json +++ b/api/swagger-spec/extensions_v1beta1.json @@ -6699,6 +6699,14 @@ "$ref": "v1.LocalObjectReference" }, "description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod" + }, + "hostname": { + "type": "string", + "description": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value." + }, + "subdomain": { + "type": "string", + "description": "If specified, the fully qualified Pod hostname will be \"\u003chostname\u003e.\u003csubdomain\u003e.\u003cpod namespace\u003e.svc.\u003ccluster domain\u003e\". If not specified, the pod will not have a domainname at all." } } }, diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index 4a668a4b2c3..fbe301224ad 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -15501,6 +15501,10 @@ "type": "string", "description": "The IP of this endpoint. May not be loopback (127.0.0.0/8), link-local (169.254.0.0/16), or link-local multicast ((224.0.0.0/24). IPv6 is also accepted but not fully supported on all platforms. Also, certain kubernetes components, like kube-proxy, are not IPv6 ready." }, + "hostname": { + "type": "string", + "description": "The Hostname of this endpoint" + }, "targetRef": { "$ref": "v1.ObjectReference", "description": "Reference to object providing the endpoint." @@ -16820,6 +16824,14 @@ "$ref": "v1.LocalObjectReference" }, "description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod" + }, + "hostname": { + "type": "string", + "description": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value." + }, + "subdomain": { + "type": "string", + "description": "If specified, the fully qualified Pod hostname will be \"\u003chostname\u003e.\u003csubdomain\u003e.\u003cpod namespace\u003e.svc.\u003ccluster domain\u003e\". If not specified, the pod will not have a domainname at all." } } }, diff --git a/cluster/addons/dns/README.md b/cluster/addons/dns/README.md index ff4a3216373..28758778529 100644 --- a/cluster/addons/dns/README.md +++ b/cluster/addons/dns/README.md @@ -60,24 +60,55 @@ When enabled, pods are assigned a DNS A record in the form of `pod-ip-address.my For example, a pod with ip `1.2.3.4` in the namespace `default` with a dns name of `cluster.local` would have an entry: `1-2-3-4.default.pod.cluster.local`. -####A Records and hostname Based on Pod Annotations - A Beta Feature in Kubernetes v1.2 +####A Records and hostname based on Pod's hostname and subdomain fields Currently when a pod is created, its hostname is the Pod's `metadata.name` value. + With v1.2, users can specify a Pod annotation, `pod.beta.kubernetes.io/hostname`, to specify what the Pod's hostname should be. If the annotation is specified, the annotation value takes precendence over the Pod's name, to be the hostname of the pod. For example, given a Pod with annotation `pod.beta.kubernetes.io/hostname: my-pod-name`, the Pod will have its hostname set to "my-pod-name". +With v1.3, the PodSpec has a `hostname` field, which can be used to specify the Pod's hostname. This field value takes precedence over the +`pod.beta.kubernetes.io/hostname` annotation value. + v1.2 introduces a beta feature where the user can specify a Pod annotation, `pod.beta.kubernetes.io/subdomain`, to specify what the Pod's subdomain should be. If the annotation is specified, the fully qualified Pod hostname will be "...svc.". For example, given a Pod with the hostname annotation set to "foo", and the subdomain annotation set to "bar", in namespace "my-namespace", the pod will set its own FQDN as "foo.bar.my-namespace.svc.cluster.local" +With v1.3, the PodSpec has a `subdomain` field, which can be used to specify the Pod's subdomain. This field value takes precedence over the +`pod.beta.kubernetes.io/subdomain` annotation value. + +Example: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: busybox + namespace: default +spec: + hostname: busybox-1 + subdomain: default + containers: + - image: busybox + command: + - sleep + - "3600" + name: busybox +``` + If there exists a headless service in the same namespace as the pod and with the same name as the subdomain, the cluster's KubeDNS Server will also return an A record for the Pod's fully qualified hostname. -Given a Pod with the hostname annotation set to "foo" and the subdomain annotation set to "bar", and a headless Service named "bar" in the same namespace, the pod will see it's own FQDN as "foo.bar.my-namespace.svc.cluster.local". DNS will serve an A record at that name, pointing to the Pod's IP. +Given a Pod with the hostname set to "foo" and the subdomain set to "bar", and a headless Service named "bar" in the same namespace, the pod will see it's own FQDN as "foo.bar.my-namespace.svc.cluster.local". DNS will serve an A record at that name, pointing to the Pod's IP. With v1.2, the Endpoints object also has a new annotation `endpoints.beta.kubernetes.io/hostnames-map`. Its value is the json representation of map[string(IP)][endpoints.HostRecord], for example: '{"10.245.1.6":{HostName: "my-webserver"}}'. If the Endpoints are for a headless service, then A records will be created with the format ...svc. For the example json, if endpoints are for a headless service named "bar", and one of the endpoints has IP "10.245.1.6", then a A record will be created with the name "my-webserver.bar.my-namespace.svc.cluster.local" and the A record lookup would return "10.245.1.6". This endpoints annotation generally does not need to be specified by end-users, but can used by the internal service controller to deliver the aforementioned feature. +With v1.3, The Endpoints object can specify the `hostname` for any endpoint, along with its IP. The hostname field takes precedence over the hostname value +that might have been specified via the `endpoints.beta.kubernetes.io/hostnames-map` annotation. + +With v1.3, the following annotations are deprecated: `pod.beta.kubernetes.io/hostname`, `pod.beta.kubernetes.io/subdomain`, `endpoints.beta.kubernetes.io/hostnames-map` + ## How do I find the DNS server? The DNS server itself runs as a Kubernetes Service. This gives it a stable IP address. When you run the SkyDNS service, you want to assign a static IP to use for diff --git a/cluster/addons/dns/kube2sky/kube2sky.go b/cluster/addons/dns/kube2sky/kube2sky.go index 08cf11a75f0..7d423b12db9 100644 --- a/cluster/addons/dns/kube2sky/kube2sky.go +++ b/cluster/addons/dns/kube2sky/kube2sky.go @@ -161,28 +161,27 @@ func getSkyMsg(ip string, port int) *skymsg.Service { } func (ks *kube2sky) generateRecordsForHeadlessService(subdomain string, e *kapi.Endpoints, svc *kapi.Service) error { - glog.V(4).Infof("Endpoints Annotations: %v", e.Annotations) + // TODO: remove this after v1.4 is released and the old annotations are EOL + podHostnames, err := getPodHostnamesFromAnnotation(e.Annotations) + if err != nil { + return err + } for idx := range e.Subsets { for subIdx := range e.Subsets[idx].Addresses { - endpointIP := e.Subsets[idx].Addresses[subIdx].IP + address := &e.Subsets[idx].Addresses[subIdx] + endpointIP := address.IP b, err := json.Marshal(getSkyMsg(endpointIP, 0)) if err != nil { return err } recordValue := string(b) - recordLabel := getHash(recordValue) - if serializedPodHostnames := e.Annotations[endpoints.PodHostnamesAnnotation]; len(serializedPodHostnames) > 0 { - podHostnames := map[string]endpoints.HostRecord{} - err := json.Unmarshal([]byte(serializedPodHostnames), &podHostnames) - if err != nil { - return err - } - if hostRecord, exists := podHostnames[string(endpointIP)]; exists { - if validation.IsDNS1123Label(hostRecord.HostName) { - recordLabel = hostRecord.HostName - } - } + var recordLabel string + if hostLabel, exists := getHostname(address, podHostnames); exists { + recordLabel = hostLabel + } else { + recordLabel = getHash(recordValue) } + recordKey := buildDNSNameString(subdomain, recordLabel) glog.V(2).Infof("Setting DNS record: %v -> %q\n", recordKey, recordValue) @@ -205,6 +204,30 @@ func (ks *kube2sky) generateRecordsForHeadlessService(subdomain string, e *kapi. return nil } +func getHostname(address *kapi.EndpointAddress, podHostnames map[string]endpoints.HostRecord) (string, bool) { + if len(address.Hostname) > 0 { + return address.Hostname, true + } + if hostRecord, exists := podHostnames[address.IP]; exists && validation.IsDNS1123Label(hostRecord.HostName) { + return hostRecord.HostName, true + } + return "", false +} + +func getPodHostnamesFromAnnotation(annotations map[string]string) (map[string]endpoints.HostRecord, error) { + hostnames := map[string]endpoints.HostRecord{} + + if annotations != nil { + if serializedHostnames, exists := annotations[endpoints.PodHostnamesAnnotation]; exists && len(serializedHostnames) > 0 { + err := json.Unmarshal([]byte(serializedHostnames), &hostnames) + if err != nil { + return nil, err + } + } + } + return hostnames, nil +} + func (ks *kube2sky) getServiceFromEndpoints(e *kapi.Endpoints) (*kapi.Service, error) { key, err := kcache.MetaNamespaceKeyFunc(e) if err != nil { diff --git a/cluster/addons/dns/skydns-rc.yaml.in b/cluster/addons/dns/skydns-rc.yaml.in index db581572a90..7938e905fe5 100644 --- a/cluster/addons/dns/skydns-rc.yaml.in +++ b/cluster/addons/dns/skydns-rc.yaml.in @@ -50,7 +50,7 @@ spec: - name: etcd-storage mountPath: /var/etcd/data - name: kube2sky - image: gcr.io/google_containers/kube2sky:1.14 + image: gcr.io/google_containers/kube2sky-amd64:1.15 resources: # TODO: Set memory limits when we've profiled the container for large # clusters, then set request = limit to keep this container in diff --git a/docs/api-reference/autoscaling/v1/definitions.html b/docs/api-reference/autoscaling/v1/definitions.html index 373baa117f1..8d4c1804853 100755 --- a/docs/api-reference/autoscaling/v1/definitions.html +++ b/docs/api-reference/autoscaling/v1/definitions.html @@ -1244,7 +1244,7 @@ Examples:
diff --git a/docs/api-reference/autoscaling/v1/operations.html b/docs/api-reference/autoscaling/v1/operations.html index a0a6370d375..59019034bea 100755 --- a/docs/api-reference/autoscaling/v1/operations.html +++ b/docs/api-reference/autoscaling/v1/operations.html @@ -2122,7 +2122,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } diff --git a/docs/api-reference/batch/v1/definitions.html b/docs/api-reference/batch/v1/definitions.html index f311cd020c7..5eb0b74beae 100755 --- a/docs/api-reference/batch/v1/definitions.html +++ b/docs/api-reference/batch/v1/definitions.html @@ -3544,6 +3544,20 @@ Populated by the system when a graceful deletion is requested. Read-only. More i

v1.LocalObjectReference array

+ +

hostname

+

Specifies the hostname of the Pod If not specified, the pod’s hostname will be set to a system-defined value.

+

false

+

string

+ + + +

subdomain

+

If specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>". If not specified, the pod will not have a domainname at all.

+

false

+

string

+ + @@ -3882,7 +3896,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i diff --git a/docs/api-reference/batch/v1/operations.html b/docs/api-reference/batch/v1/operations.html index f40d74ffd8c..74e9200e1e5 100755 --- a/docs/api-reference/batch/v1/operations.html +++ b/docs/api-reference/batch/v1/operations.html @@ -2122,7 +2122,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } diff --git a/docs/api-reference/extensions/v1beta1/definitions.html b/docs/api-reference/extensions/v1beta1/definitions.html index 6c0786756ee..ae92ec84e29 100755 --- a/docs/api-reference/extensions/v1beta1/definitions.html +++ b/docs/api-reference/extensions/v1beta1/definitions.html @@ -3403,6 +3403,20 @@ Populated by the system when a graceful deletion is requested. Read-only. More i

v1.LocalObjectReference array

+ +

hostname

+

Specifies the hostname of the Pod If not specified, the pod’s hostname will be set to a system-defined value.

+

false

+

string

+ + + +

subdomain

+

If specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>". If not specified, the pod will not have a domainname at all.

+

false

+

string

+ + @@ -5872,7 +5886,7 @@ Both these may change in the future. Incoming requests are matched against the h diff --git a/docs/api-reference/extensions/v1beta1/operations.html b/docs/api-reference/extensions/v1beta1/operations.html index 000249493af..4bd749ae70c 100755 --- a/docs/api-reference/extensions/v1beta1/operations.html +++ b/docs/api-reference/extensions/v1beta1/operations.html @@ -13309,7 +13309,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } diff --git a/docs/api-reference/v1/definitions.html b/docs/api-reference/v1/definitions.html index 5b20d37062f..13786879973 100755 --- a/docs/api-reference/v1/definitions.html +++ b/docs/api-reference/v1/definitions.html @@ -4145,6 +4145,20 @@ The resulting set of endpoints can be viewed as:

v1.LocalObjectReference array

+ +

hostname

+

Specifies the hostname of the Pod If not specified, the pod’s hostname will be set to a system-defined value.

+

false

+

string

+ + + +

subdomain

+

If specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>". If not specified, the pod will not have a domainname at all.

+

false

+

string

+ + @@ -7687,6 +7701,13 @@ The resulting set of endpoints can be viewed as:
+

hostname

+

The Hostname of this endpoint

+

false

+

string

+ + +

targetRef

Reference to object providing the endpoint.

false

@@ -7742,7 +7763,7 @@ The resulting set of endpoints can be viewed as:
diff --git a/docs/api-reference/v1/operations.html b/docs/api-reference/v1/operations.html index dac19da0090..d361579f843 100755 --- a/docs/api-reference/v1/operations.html +++ b/docs/api-reference/v1/operations.html @@ -30700,7 +30700,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } diff --git a/pkg/api/deep_copy_generated.go b/pkg/api/deep_copy_generated.go index 0458e6bb8d9..a2ccc83085b 100644 --- a/pkg/api/deep_copy_generated.go +++ b/pkg/api/deep_copy_generated.go @@ -661,6 +661,7 @@ func DeepCopy_api_EmptyDirVolumeSource(in EmptyDirVolumeSource, out *EmptyDirVol func DeepCopy_api_EndpointAddress(in EndpointAddress, out *EndpointAddress, c *conversion.Cloner) error { out.IP = in.IP + out.Hostname = in.Hostname if in.TargetRef != nil { in, out := in.TargetRef, &out.TargetRef *out = new(ObjectReference) @@ -2158,6 +2159,8 @@ func DeepCopy_api_PodSpec(in PodSpec, out *PodSpec, c *conversion.Cloner) error } else { out.ImagePullSecrets = nil } + out.Hostname = in.Hostname + out.Subdomain = in.Subdomain return nil } diff --git a/pkg/api/endpoints/util.go b/pkg/api/endpoints/util.go index 7758434a19d..501d58f2853 100644 --- a/pkg/api/endpoints/util.go +++ b/pkg/api/endpoints/util.go @@ -29,11 +29,13 @@ import ( ) 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 } diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index 6b00c7e7dfa..97a1b9e6e84 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -24,9 +24,11 @@ import ( ) 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 the pod itself, ".my-web-service..svc." would resolve to // the pod's IP. diff --git a/pkg/api/types.generated.go b/pkg/api/types.generated.go index 92fe66e789f..93977021a81 100644 --- a/pkg/api/types.generated.go +++ b/pkg/api/types.generated.go @@ -23218,7 +23218,7 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [11]bool + var yyq2 [13]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false yyq2[2] = x.RestartPolicy != "" @@ -23229,9 +23229,11 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) { yyq2[8] = x.NodeName != "" yyq2[9] = x.SecurityContext != nil yyq2[10] = len(x.ImagePullSecrets) != 0 + yyq2[11] = x.Hostname != "" + yyq2[12] = x.Subdomain != "" var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(11) + r.EncodeArrayStart(13) } else { yynn2 = 3 for _, b := range yyq2 { @@ -23529,6 +23531,56 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) { } } } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[11] { + yym41 := z.EncBinary() + _ = yym41 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[11] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("hostname")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym42 := z.EncBinary() + _ = yym42 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[12] { + yym44 := z.EncBinary() + _ = yym44 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Subdomain)) + } + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[12] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("subdomain")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym45 := z.EncBinary() + _ = yym45 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Subdomain)) + } + } + } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayEnd1234) } else { @@ -23705,6 +23757,18 @@ func (x *PodSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv19), d) } } + case "hostname": + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } + case "subdomain": + if r.TryDecodeAsNil() { + x.Subdomain = "" + } else { + x.Subdomain = string(r.DecodeString()) + } default: z.DecStructFieldNotFound(-1, yys3) } // end switch yys3 @@ -23716,16 +23780,16 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj21 int - var yyb21 bool - var yyhl21 bool = l >= 0 - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + var yyj23 int + var yyb23 bool + var yyhl23 bool = l >= 0 + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23733,21 +23797,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.Volumes = nil } else { - yyv22 := &x.Volumes - yym23 := z.DecBinary() - _ = yym23 + yyv24 := &x.Volumes + yym25 := z.DecBinary() + _ = yym25 if false { } else { - h.decSliceVolume((*[]Volume)(yyv22), d) + h.decSliceVolume((*[]Volume)(yyv24), d) } } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23755,21 +23819,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.Containers = nil } else { - yyv24 := &x.Containers - yym25 := z.DecBinary() - _ = yym25 + yyv26 := &x.Containers + yym27 := z.DecBinary() + _ = yym27 if false { } else { - h.decSliceContainer((*[]Container)(yyv24), d) + h.decSliceContainer((*[]Container)(yyv26), d) } } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23779,13 +23843,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.RestartPolicy = RestartPolicy(r.DecodeString()) } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23798,20 +23862,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if x.TerminationGracePeriodSeconds == nil { x.TerminationGracePeriodSeconds = new(int64) } - yym28 := z.DecBinary() - _ = yym28 + yym30 := z.DecBinary() + _ = yym30 if false { } else { *((*int64)(x.TerminationGracePeriodSeconds)) = int64(r.DecodeInt(64)) } } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23824,20 +23888,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if x.ActiveDeadlineSeconds == nil { x.ActiveDeadlineSeconds = new(int64) } - yym30 := z.DecBinary() - _ = yym30 + yym32 := z.DecBinary() + _ = yym32 if false { } else { *((*int64)(x.ActiveDeadlineSeconds)) = int64(r.DecodeInt(64)) } } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23847,13 +23911,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.DNSPolicy = DNSPolicy(r.DecodeString()) } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23861,21 +23925,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.NodeSelector = nil } else { - yyv32 := &x.NodeSelector - yym33 := z.DecBinary() - _ = yym33 + yyv34 := &x.NodeSelector + yym35 := z.DecBinary() + _ = yym35 if false { } else { - z.F.DecMapStringStringX(yyv32, false, d) + z.F.DecMapStringStringX(yyv34, false, d) } } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23885,13 +23949,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.ServiceAccountName = string(r.DecodeString()) } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23901,13 +23965,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.NodeName = string(r.DecodeString()) } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23922,13 +23986,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } x.SecurityContext.CodecDecodeSelf(d) } - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23936,26 +24000,58 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.ImagePullSecrets = nil } else { - yyv37 := &x.ImagePullSecrets - yym38 := z.DecBinary() - _ = yym38 + yyv39 := &x.ImagePullSecrets + yym40 := z.DecBinary() + _ = yym40 if false { } else { - h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv37), d) + h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv39), d) } } + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l + } else { + yyb23 = r.CheckBreak() + } + if yyb23 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l + } else { + yyb23 = r.CheckBreak() + } + if yyb23 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Subdomain = "" + } else { + x.Subdomain = string(r.DecodeString()) + } for { - yyj21++ - if yyhl21 { - yyb21 = yyj21 > l + yyj23++ + if yyhl23 { + yyb23 = yyj23 > l } else { - yyb21 = r.CheckBreak() + yyb23 = r.CheckBreak() } - if yyb21 { + if yyb23 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj21-1, "") + z.DecStructFieldNotFound(yyj23-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } @@ -31387,12 +31483,13 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [2]bool + var yyq2 [3]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false + yyq2[1] = x.Hostname != "" var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(2) + r.EncodeArrayStart(3) } else { yynn2 = 2 for _, b := range yyq2 { @@ -31422,6 +31519,31 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) { r.EncodeString(codecSelferC_UTF81234, string(x.IP)) } } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[1] { + yym7 := z.EncBinary() + _ = yym7 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[1] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("hostname")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym8 := z.EncBinary() + _ = yym8 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } + } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) if x.TargetRef == nil { @@ -31506,6 +31628,12 @@ func (x *EndpointAddress) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { } else { x.IP = string(r.DecodeString()) } + case "hostname": + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } case "TargetRef": if r.TryDecodeAsNil() { if x.TargetRef != nil { @@ -31528,16 +31656,16 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj6 int - var yyb6 bool - var yyhl6 bool = l >= 0 - yyj6++ - if yyhl6 { - yyb6 = yyj6 > l + var yyj7 int + var yyb7 bool + var yyhl7 bool = l >= 0 + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l } else { - yyb6 = r.CheckBreak() + yyb7 = r.CheckBreak() } - if yyb6 { + if yyb7 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -31547,13 +31675,29 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) } else { x.IP = string(r.DecodeString()) } - yyj6++ - if yyhl6 { - yyb6 = yyj6 > l + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l } else { - yyb6 = r.CheckBreak() + yyb7 = r.CheckBreak() } - if yyb6 { + if yyb7 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l + } else { + yyb7 = r.CheckBreak() + } + if yyb7 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -31569,17 +31713,17 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) x.TargetRef.CodecDecodeSelf(d) } for { - yyj6++ - if yyhl6 { - yyb6 = yyj6 > l + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l } else { - yyb6 = r.CheckBreak() + yyb7 = r.CheckBreak() } - if yyb6 { + if yyb7 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj6-1, "") + z.DecStructFieldNotFound(yyj7-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } @@ -50513,7 +50657,7 @@ func (x codecSelfer1234) decSlicePod(v *[]Pod, d *codec1978.Decoder) { yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 496) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 528) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -51584,7 +51728,7 @@ func (x codecSelfer1234) decSlicePodTemplate(v *[]PodTemplate, d *codec1978.Deco yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 520) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 552) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -52536,7 +52680,7 @@ func (x codecSelfer1234) decSliceEndpointAddress(v *[]EndpointAddress, d *codec1 yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 24) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/api/types.go b/pkg/api/types.go index 859f10ee66e..3a4a1809e9c 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -1229,6 +1229,12 @@ type PodSpec struct { // If specified, these secrets will be passed to individual puller implementations for them to use. For example, // in the case of docker, only DockerConfig type secrets are honored. ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty"` + // Specifies the hostname of the Pod. + // If not specified, the pod's hostname will be set to a system-defined value. + Hostname string `json:"hostname,omitempty"` + // If specified, the fully qualified Pod hostname will be "...svc.". + // If not specified, the pod will not have a domainname at all. + Subdomain string `json:"subdomain,omitempty"` } // PodSecurityContext holds pod-level security attributes and common container settings. @@ -1632,7 +1638,9 @@ type EndpointAddress struct { // kubernetes components, like kube-proxy, are not IPv6 ready. // TODO: This should allow hostname or IP, see #4447. IP string - + // Optional: Hostname of this endpoint + // Meant to be used by DNS servers etc. + Hostname string `json:"hostname,omitempty"` // Optional: The kubernetes object related to the entry point. TargetRef *ObjectReference } diff --git a/pkg/api/v1/conversion.go b/pkg/api/v1/conversion.go index 56ca88f3677..f99bab435ef 100644 --- a/pkg/api/v1/conversion.go +++ b/pkg/api/v1/conversion.go @@ -338,6 +338,8 @@ func Convert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversi } else { out.ImagePullSecrets = nil } + out.Hostname = in.Hostname + out.Subdomain = in.Subdomain return nil } @@ -419,7 +421,8 @@ func Convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversi } else { out.ImagePullSecrets = nil } - + out.Hostname = in.Hostname + out.Subdomain = in.Subdomain return nil } diff --git a/pkg/api/v1/conversion_generated.go b/pkg/api/v1/conversion_generated.go index 6be8cf507e1..6809c4e27e1 100644 --- a/pkg/api/v1/conversion_generated.go +++ b/pkg/api/v1/conversion_generated.go @@ -1619,6 +1619,7 @@ func autoConvert_v1_EndpointAddress_To_api_EndpointAddress(in *EndpointAddress, defaulting.(func(*EndpointAddress))(in) } out.IP = in.IP + out.Hostname = in.Hostname if in.TargetRef != nil { in, out := &in.TargetRef, &out.TargetRef *out = new(api.ObjectReference) @@ -1640,6 +1641,7 @@ func autoConvert_api_EndpointAddress_To_v1_EndpointAddress(in *api.EndpointAddre defaulting.(func(*api.EndpointAddress))(in) } out.IP = in.IP + out.Hostname = in.Hostname if in.TargetRef != nil { in, out := &in.TargetRef, &out.TargetRef *out = new(ObjectReference) @@ -5357,6 +5359,8 @@ func autoConvert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conv } else { out.ImagePullSecrets = nil } + out.Hostname = in.Hostname + out.Subdomain = in.Subdomain return nil } diff --git a/pkg/api/v1/deep_copy_generated.go b/pkg/api/v1/deep_copy_generated.go index 1597f9f3e15..f0a5fe9a046 100644 --- a/pkg/api/v1/deep_copy_generated.go +++ b/pkg/api/v1/deep_copy_generated.go @@ -639,6 +639,7 @@ func DeepCopy_v1_EmptyDirVolumeSource(in EmptyDirVolumeSource, out *EmptyDirVolu func DeepCopy_v1_EndpointAddress(in EndpointAddress, out *EndpointAddress, c *conversion.Cloner) error { out.IP = in.IP + out.Hostname = in.Hostname if in.TargetRef != nil { in, out := in.TargetRef, &out.TargetRef *out = new(ObjectReference) @@ -2106,6 +2107,8 @@ func DeepCopy_v1_PodSpec(in PodSpec, out *PodSpec, c *conversion.Cloner) error { } else { out.ImagePullSecrets = nil } + out.Hostname = in.Hostname + out.Subdomain = in.Subdomain return nil } diff --git a/pkg/api/v1/generated.pb.go b/pkg/api/v1/generated.pb.go index e42d2a40de1..c6c82b388cf 100644 --- a/pkg/api/v1/generated.pb.go +++ b/pkg/api/v1/generated.pb.go @@ -2050,6 +2050,10 @@ func (m *EndpointAddress) MarshalTo(data []byte) (int, error) { } i += n26 } + data[i] = 0x1a + i++ + i = encodeVarintGenerated(data, i, uint64(len(m.Hostname))) + i += copy(data[i:], m.Hostname) return i, nil } @@ -5358,6 +5362,18 @@ func (m *PodSpec) MarshalTo(data []byte) (int, error) { i += n } } + data[i] = 0x82 + i++ + data[i] = 0x1 + i++ + i = encodeVarintGenerated(data, i, uint64(len(m.Hostname))) + i += copy(data[i:], m.Hostname) + data[i] = 0x8a + i++ + data[i] = 0x1 + i++ + i = encodeVarintGenerated(data, i, uint64(len(m.Subdomain))) + i += copy(data[i:], m.Subdomain) return i, nil } @@ -7560,6 +7576,8 @@ func (m *EndpointAddress) Size() (n int) { l = m.TargetRef.Size() n += 1 + l + sovGenerated(uint64(l)) } + l = len(m.Hostname) + n += 1 + l + sovGenerated(uint64(l)) return n } @@ -8775,6 +8793,10 @@ func (m *PodSpec) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + l = len(m.Hostname) + n += 2 + l + sovGenerated(uint64(l)) + l = len(m.Subdomain) + n += 2 + l + sovGenerated(uint64(l)) return n } @@ -13473,6 +13495,35 @@ func (m *EndpointAddress) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hostname", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hostname = string(data[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(data[iNdEx:]) @@ -25543,6 +25594,64 @@ func (m *PodSpec) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hostname", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hostname = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Subdomain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Subdomain = string(data[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(data[iNdEx:]) diff --git a/pkg/api/v1/generated.proto b/pkg/api/v1/generated.proto index 04975e55aaa..2afd25d3f96 100644 --- a/pkg/api/v1/generated.proto +++ b/pkg/api/v1/generated.proto @@ -524,6 +524,9 @@ message EndpointAddress { // TODO: This should allow hostname or IP, See #4447. optional string ip = 1; + // The Hostname of this endpoint + optional string hostname = 3; + // Reference to object providing the endpoint. optional ObjectReference targetRef = 2; } @@ -1946,6 +1949,14 @@ message PodSpec { // in the case of docker, only DockerConfig type secrets are honored. // More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod repeated LocalObjectReference imagePullSecrets = 15; + + // Specifies the hostname of the Pod + // If not specified, the pod's hostname will be set to a system-defined value. + optional string hostname = 16; + + // If specified, the fully qualified Pod hostname will be "...svc.". + // If not specified, the pod will not have a domainname at all. + optional string subdomain = 17; } // PodStatus represents information about the status of a pod. Status may trail the actual diff --git a/pkg/api/v1/types.generated.go b/pkg/api/v1/types.generated.go index 84953e4198d..ec9c8dd97ce 100644 --- a/pkg/api/v1/types.generated.go +++ b/pkg/api/v1/types.generated.go @@ -22498,7 +22498,7 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [15]bool + var yyq2 [17]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false yyq2[0] = len(x.Volumes) != 0 @@ -22515,9 +22515,11 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) { yyq2[12] = x.HostIPC != false yyq2[13] = x.SecurityContext != nil yyq2[14] = len(x.ImagePullSecrets) != 0 + yyq2[15] = x.Hostname != "" + yyq2[16] = x.Subdomain != "" var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(15) + r.EncodeArrayStart(17) } else { yynn2 = 1 for _, b := range yyq2 { @@ -22927,6 +22929,56 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) { } } } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[15] { + yym53 := z.EncBinary() + _ = yym53 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[15] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("hostname")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym54 := z.EncBinary() + _ = yym54 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[16] { + yym56 := z.EncBinary() + _ = yym56 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Subdomain)) + } + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[16] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("subdomain")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym57 := z.EncBinary() + _ = yym57 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Subdomain)) + } + } + } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayEnd1234) } else { @@ -23127,6 +23179,18 @@ func (x *PodSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv23), d) } } + case "hostname": + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } + case "subdomain": + if r.TryDecodeAsNil() { + x.Subdomain = "" + } else { + x.Subdomain = string(r.DecodeString()) + } default: z.DecStructFieldNotFound(-1, yys3) } // end switch yys3 @@ -23138,16 +23202,16 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj25 int - var yyb25 bool - var yyhl25 bool = l >= 0 - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + var yyj27 int + var yyb27 bool + var yyhl27 bool = l >= 0 + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23155,21 +23219,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.Volumes = nil } else { - yyv26 := &x.Volumes - yym27 := z.DecBinary() - _ = yym27 + yyv28 := &x.Volumes + yym29 := z.DecBinary() + _ = yym29 if false { } else { - h.decSliceVolume((*[]Volume)(yyv26), d) + h.decSliceVolume((*[]Volume)(yyv28), d) } } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23177,21 +23241,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.Containers = nil } else { - yyv28 := &x.Containers - yym29 := z.DecBinary() - _ = yym29 + yyv30 := &x.Containers + yym31 := z.DecBinary() + _ = yym31 if false { } else { - h.decSliceContainer((*[]Container)(yyv28), d) + h.decSliceContainer((*[]Container)(yyv30), d) } } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23201,13 +23265,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.RestartPolicy = RestartPolicy(r.DecodeString()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23220,20 +23284,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if x.TerminationGracePeriodSeconds == nil { x.TerminationGracePeriodSeconds = new(int64) } - yym32 := z.DecBinary() - _ = yym32 + yym34 := z.DecBinary() + _ = yym34 if false { } else { *((*int64)(x.TerminationGracePeriodSeconds)) = int64(r.DecodeInt(64)) } } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23246,20 +23310,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if x.ActiveDeadlineSeconds == nil { x.ActiveDeadlineSeconds = new(int64) } - yym34 := z.DecBinary() - _ = yym34 + yym36 := z.DecBinary() + _ = yym36 if false { } else { *((*int64)(x.ActiveDeadlineSeconds)) = int64(r.DecodeInt(64)) } } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23269,13 +23333,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.DNSPolicy = DNSPolicy(r.DecodeString()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23283,21 +23347,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.NodeSelector = nil } else { - yyv36 := &x.NodeSelector - yym37 := z.DecBinary() - _ = yym37 + yyv38 := &x.NodeSelector + yym39 := z.DecBinary() + _ = yym39 if false { } else { - z.F.DecMapStringStringX(yyv36, false, d) + z.F.DecMapStringStringX(yyv38, false, d) } } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23307,13 +23371,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.ServiceAccountName = string(r.DecodeString()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23323,13 +23387,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.DeprecatedServiceAccount = string(r.DecodeString()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23339,13 +23403,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.NodeName = string(r.DecodeString()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23355,13 +23419,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.HostNetwork = bool(r.DecodeBool()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23371,13 +23435,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.HostPID = bool(r.DecodeBool()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23387,13 +23451,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } else { x.HostIPC = bool(r.DecodeBool()) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23408,13 +23472,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { } x.SecurityContext.CodecDecodeSelf(d) } - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -23422,26 +23486,58 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { if r.TryDecodeAsNil() { x.ImagePullSecrets = nil } else { - yyv45 := &x.ImagePullSecrets - yym46 := z.DecBinary() - _ = yym46 + yyv47 := &x.ImagePullSecrets + yym48 := z.DecBinary() + _ = yym48 if false { } else { - h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv45), d) + h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv47), d) } } + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l + } else { + yyb27 = r.CheckBreak() + } + if yyb27 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l + } else { + yyb27 = r.CheckBreak() + } + if yyb27 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Subdomain = "" + } else { + x.Subdomain = string(r.DecodeString()) + } for { - yyj25++ - if yyhl25 { - yyb25 = yyj25 > l + yyj27++ + if yyhl27 { + yyb27 = yyj27 > l } else { - yyb25 = r.CheckBreak() + yyb27 = r.CheckBreak() } - if yyb25 { + if yyb27 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj25-1, "") + z.DecStructFieldNotFound(yyj27-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } @@ -31248,13 +31344,14 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [2]bool + var yyq2 [3]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false - yyq2[1] = x.TargetRef != nil + yyq2[1] = x.Hostname != "" + yyq2[2] = x.TargetRef != nil var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(2) + r.EncodeArrayStart(3) } else { yynn2 = 1 for _, b := range yyq2 { @@ -31287,6 +31384,31 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) { if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) if yyq2[1] { + yym7 := z.EncBinary() + _ = yym7 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[1] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("hostname")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym8 := z.EncBinary() + _ = yym8 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Hostname)) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[2] { if x.TargetRef == nil { r.EncodeNil() } else { @@ -31296,7 +31418,7 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) { r.EncodeNil() } } else { - if yyq2[1] { + if yyq2[2] { z.EncSendContainerState(codecSelfer_containerMapKey1234) r.EncodeString(codecSelferC_UTF81234, string("targetRef")) z.EncSendContainerState(codecSelfer_containerMapValue1234) @@ -31374,6 +31496,12 @@ func (x *EndpointAddress) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { } else { x.IP = string(r.DecodeString()) } + case "hostname": + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } case "targetRef": if r.TryDecodeAsNil() { if x.TargetRef != nil { @@ -31396,16 +31524,16 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj6 int - var yyb6 bool - var yyhl6 bool = l >= 0 - yyj6++ - if yyhl6 { - yyb6 = yyj6 > l + var yyj7 int + var yyb7 bool + var yyhl7 bool = l >= 0 + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l } else { - yyb6 = r.CheckBreak() + yyb7 = r.CheckBreak() } - if yyb6 { + if yyb7 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -31415,13 +31543,29 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) } else { x.IP = string(r.DecodeString()) } - yyj6++ - if yyhl6 { - yyb6 = yyj6 > l + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l } else { - yyb6 = r.CheckBreak() + yyb7 = r.CheckBreak() } - if yyb6 { + if yyb7 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Hostname = "" + } else { + x.Hostname = string(r.DecodeString()) + } + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l + } else { + yyb7 = r.CheckBreak() + } + if yyb7 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -31437,17 +31581,17 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) x.TargetRef.CodecDecodeSelf(d) } for { - yyj6++ - if yyhl6 { - yyb6 = yyj6 > l + yyj7++ + if yyhl7 { + yyb7 = yyj7 > l } else { - yyb6 = r.CheckBreak() + yyb7 = r.CheckBreak() } - if yyb6 { + if yyb7 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj6-1, "") + z.DecStructFieldNotFound(yyj7-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } @@ -51518,7 +51662,7 @@ func (x codecSelfer1234) decSlicePod(v *[]Pod, d *codec1978.Decoder) { yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 520) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 552) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -51637,7 +51781,7 @@ func (x codecSelfer1234) decSlicePodTemplate(v *[]PodTemplate, d *codec1978.Deco yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 544) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 576) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -52589,7 +52733,7 @@ func (x codecSelfer1234) decSliceEndpointAddress(v *[]EndpointAddress, d *codec1 yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 24) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/api/v1/types.go b/pkg/api/v1/types.go index a1dc2142539..75c780a8983 100644 --- a/pkg/api/v1/types.go +++ b/pkg/api/v1/types.go @@ -1494,6 +1494,12 @@ type PodSpec struct { // in the case of docker, only DockerConfig type secrets are honored. // More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,15,rep,name=imagePullSecrets"` + // Specifies the hostname of the Pod + // If not specified, the pod's hostname will be set to a system-defined value. + Hostname string `json:"hostname,omitempty" protobuf:"bytes,16,opt,name=hostname"` + // If specified, the fully qualified Pod hostname will be "...svc.". + // If not specified, the pod will not have a domainname at all. + Subdomain string `json:"subdomain,omitempty" protobuf:"bytes,17,opt,name=subdomain"` } // PodSecurityContext holds pod-level security attributes and common container settings. @@ -2006,7 +2012,8 @@ type EndpointAddress struct { // kubernetes components, like kube-proxy, are not IPv6 ready. // TODO: This should allow hostname or IP, See #4447. IP string `json:"ip" protobuf:"bytes,1,opt,name=ip"` - + // The Hostname of this endpoint + Hostname string `json:"hostname,omitempty" protobuf:"bytes,3,opt,name=hostname"` // Reference to object providing the endpoint. TargetRef *ObjectReference `json:"targetRef,omitempty" protobuf:"bytes,2,opt,name=targetRef"` } diff --git a/pkg/api/v1/types_swagger_doc_generated.go b/pkg/api/v1/types_swagger_doc_generated.go index 8a7b23dfed2..0cb6b868798 100644 --- a/pkg/api/v1/types_swagger_doc_generated.go +++ b/pkg/api/v1/types_swagger_doc_generated.go @@ -334,6 +334,7 @@ func (EmptyDirVolumeSource) SwaggerDoc() map[string]string { var map_EndpointAddress = map[string]string{ "": "EndpointAddress is a tuple that describes single IP address.", "ip": "The IP of this endpoint. May not be loopback (127.0.0.0/8), link-local (169.254.0.0/16), or link-local multicast ((224.0.0.0/24). IPv6 is also accepted but not fully supported on all platforms. Also, certain kubernetes components, like kube-proxy, are not IPv6 ready.", + "hostname": "The Hostname of this endpoint", "targetRef": "Reference to object providing the endpoint.", } @@ -1176,6 +1177,8 @@ var map_PodSpec = map[string]string{ "hostIPC": "Use the host's ipc namespace. Optional: Default to false.", "securityContext": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.", "imagePullSecrets": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod", + "hostname": "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.", + "subdomain": "If specified, the fully qualified Pod hostname will be \"...svc.\". If not specified, the pod will not have a domainname at all.", } func (PodSpec) SwaggerDoc() map[string]string { diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 2e3477b4495..a8ee0fcd6b4 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -1425,6 +1425,15 @@ func ValidatePodSpec(spec *api.PodSpec, fldPath *field.Path) field.ErrorList { allErrs = append(allErrs, field.Invalid(fldPath.Child("activeDeadlineSeconds"), spec.ActiveDeadlineSeconds, "must be greater than 0")) } } + + if len(spec.Hostname) > 0 && !validation.IsDNS1123Label(spec.Hostname) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("hostname"), spec.Hostname, DNS1123LabelErrorMsg)) + } + + if len(spec.Subdomain) > 0 && !validation.IsDNS1123Label(spec.Subdomain) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("subdomain"), spec.Subdomain, DNS1123LabelErrorMsg)) + } + return allErrs } @@ -2275,7 +2284,7 @@ func ValidateSecret(secret *api.Secret) field.ErrorList { if _, exists := secret.Data[api.TLSPrivateKeyKey]; !exists { allErrs = append(allErrs, field.Required(dataPath.Key(api.TLSPrivateKeyKey), "")) } - // TODO: Verify that the key matches the cert. + // TODO: Verify that the key matches the cert. default: // no-op } @@ -2589,6 +2598,9 @@ func validateEndpointSubsets(subsets []api.EndpointSubset, fldPath *field.Path) for addr := range ss.Addresses { allErrs = append(allErrs, validateEndpointAddress(&ss.Addresses[addr], idxPath.Child("addresses").Index(addr))...) } + for addr := range ss.NotReadyAddresses { + allErrs = append(allErrs, validateEndpointAddress(&ss.NotReadyAddresses[addr], idxPath.Child("notReadyAddresses").Index(addr))...) + } for port := range ss.Ports { allErrs = append(allErrs, validateEndpointPort(&ss.Ports[port], len(ss.Ports) > 1, idxPath.Child("ports").Index(port))...) } @@ -2601,6 +2613,11 @@ func validateEndpointAddress(address *api.EndpointAddress, fldPath *field.Path) allErrs := field.ErrorList{} if !validation.IsValidIP(address.IP) { allErrs = append(allErrs, field.Invalid(fldPath.Child("ip"), address.IP, "must be a valid IP address")) + } + if len(address.Hostname) > 0 && !validation.IsDNS1123Label(address.Hostname) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("hostname"), address.Hostname, DNS1123LabelErrorMsg)) + } + if len(allErrs) > 0 { return allErrs } return validateIpIsNotLinkLocalOrLoopback(address.IP, fldPath.Child("ip")) diff --git a/pkg/apis/apps/types.generated.go b/pkg/apis/apps/types.generated.go index a29c093d8e6..e642286d37a 100644 --- a/pkg/apis/apps/types.generated.go +++ b/pkg/apis/apps/types.generated.go @@ -1555,7 +1555,7 @@ func (x codecSelfer1234) decSlicePetSet(v *[]PetSet, d *codec1978.Decoder) { yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 592) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 624) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/apis/apps/v1alpha1/types.generated.go b/pkg/apis/apps/v1alpha1/types.generated.go index 29f07040c2b..3842bcf3146 100644 --- a/pkg/apis/apps/v1alpha1/types.generated.go +++ b/pkg/apis/apps/v1alpha1/types.generated.go @@ -1585,7 +1585,7 @@ func (x codecSelfer1234) decSlicePetSet(v *[]PetSet, d *codec1978.Decoder) { yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 616) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 648) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/apis/batch/types.generated.go b/pkg/apis/batch/types.generated.go index 3a873e3fde8..b764df80a9e 100644 --- a/pkg/apis/batch/types.generated.go +++ b/pkg/apis/batch/types.generated.go @@ -2347,7 +2347,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) { yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 624) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 656) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/apis/batch/v1/types.generated.go b/pkg/apis/batch/v1/types.generated.go index 2c07db2168e..d51d8831cf7 100644 --- a/pkg/apis/batch/v1/types.generated.go +++ b/pkg/apis/batch/v1/types.generated.go @@ -2867,7 +2867,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) { yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 640) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 672) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/apis/extensions/types.generated.go b/pkg/apis/extensions/types.generated.go index adbc20cd45a..71b140b9fdb 100644 --- a/pkg/apis/extensions/types.generated.go +++ b/pkg/apis/extensions/types.generated.go @@ -15646,7 +15646,7 @@ func (x codecSelfer1234) decSliceDeployment(v *[]Deployment, d *codec1978.Decode yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 632) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 664) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -15765,7 +15765,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder) yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 552) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 584) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -16479,7 +16479,7 @@ func (x codecSelfer1234) decSliceReplicaSet(v *[]ReplicaSet, d *codec1978.Decode yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 560) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 592) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/apis/extensions/v1beta1/types.generated.go b/pkg/apis/extensions/v1beta1/types.generated.go index dcc5fc5f9fe..606eaeecc5b 100644 --- a/pkg/apis/extensions/v1beta1/types.generated.go +++ b/pkg/apis/extensions/v1beta1/types.generated.go @@ -19242,7 +19242,7 @@ func (x codecSelfer1234) decSliceDeployment(v *[]Deployment, d *codec1978.Decode yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 640) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 672) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -19361,7 +19361,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder) yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 568) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 600) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -19599,7 +19599,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) { yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 640) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 672) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -20432,7 +20432,7 @@ func (x codecSelfer1234) decSliceReplicaSet(v *[]ReplicaSet, d *codec1978.Decode yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 576) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 608) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/controller/endpoint/endpoints_controller.go b/pkg/controller/endpoint/endpoints_controller.go index 26fdad8669c..751eac6594d 100644 --- a/pkg/controller/endpoint/endpoints_controller.go +++ b/pkg/controller/endpoint/endpoints_controller.go @@ -209,7 +209,7 @@ func (e *EndpointController) updatePod(old, cur interface{}) { oldPod := cur.(*api.Pod) // Only need to get the old services if the labels changed. if !reflect.DeepEqual(newPod.Labels, oldPod.Labels) || - !hostNameAndDomainAnnotationsAreEqual(newPod.Annotations, oldPod.Annotations) { + !hostNameAndDomainAreEqual(newPod, oldPod) { oldServices, err := e.getPodServiceMemberships(oldPod) if err != nil { glog.Errorf("Unable to get pod %v/%v's service memberships: %v", oldPod.Namespace, oldPod.Name, err) @@ -222,15 +222,29 @@ func (e *EndpointController) updatePod(old, cur interface{}) { } } -func hostNameAndDomainAnnotationsAreEqual(annotation1, annotation2 map[string]string) bool { - if annotation1 == nil { - annotation1 = map[string]string{} +func hostNameAndDomainAreEqual(pod1, pod2 *api.Pod) bool { + return getHostname(pod1) == getHostname(pod2) && + getSubdomain(pod1) == getSubdomain(pod2) +} + +func getHostname(pod *api.Pod) string { + if len(pod.Spec.Hostname) > 0 { + return pod.Spec.Hostname } - if annotation2 == nil { - annotation2 = map[string]string{} + if pod.Annotations != nil { + return pod.Annotations[utilpod.PodHostnameAnnotation] } - return annotation1[utilpod.PodHostnameAnnotation] == annotation2[utilpod.PodHostnameAnnotation] && - annotation1[utilpod.PodSubdomainAnnotation] == annotation2[utilpod.PodSubdomainAnnotation] + return "" +} + +func getSubdomain(pod *api.Pod) string { + if len(pod.Spec.Subdomain) > 0 { + return pod.Spec.Subdomain + } + if pod.Annotations != nil { + return pod.Annotations[utilpod.PodSubdomainAnnotation] + } + return "" } // When a pod is deleted, enqueue the services the pod used to be a member of. @@ -360,16 +374,6 @@ func (e *EndpointController) syncService(key string) { continue } - hostname := pod.Annotations[utilpod.PodHostnameAnnotation] - if len(hostname) > 0 && - pod.Annotations[utilpod.PodSubdomainAnnotation] == service.Name && - service.Namespace == pod.Namespace { - hostRecord := endpoints.HostRecord{ - HostName: hostname, - } - podHostNames[string(pod.Status.PodIP)] = hostRecord - } - epp := api.EndpointPort{Name: portName, Port: portNum, Protocol: portProto} epa := api.EndpointAddress{ IP: pod.Status.PodIP, @@ -380,6 +384,19 @@ func (e *EndpointController) syncService(key string) { UID: pod.ObjectMeta.UID, ResourceVersion: pod.ObjectMeta.ResourceVersion, }} + + hostname := getHostname(pod) + if len(hostname) > 0 && + getSubdomain(pod) == service.Name && + service.Namespace == pod.Namespace { + hostRecord := endpoints.HostRecord{ + HostName: hostname, + } + // TODO: stop populating podHostNames annotation in 1.4 + podHostNames[string(pod.Status.PodIP)] = hostRecord + epa.Hostname = hostname + } + if api.IsPodReady(pod) { subsets = append(subsets, api.EndpointSubset{ Addresses: []api.EndpointAddress{epa}, @@ -424,12 +441,10 @@ func (e *EndpointController) syncService(key string) { serializedPodHostNames = string(b) } - podHostNamesAreEqual := verifyPodHostNamesAreEqual(serializedPodHostNames, currentEndpoints.Annotations) - newAnnotations := make(map[string]string) newAnnotations[endpoints.PodHostnamesAnnotation] = serializedPodHostNames if reflect.DeepEqual(currentEndpoints.Subsets, subsets) && - reflect.DeepEqual(currentEndpoints.Labels, service.Labels) && podHostNamesAreEqual { + reflect.DeepEqual(currentEndpoints.Labels, service.Labels) { glog.V(5).Infof("endpoints are equal for %s/%s, skipping update", service.Namespace, service.Name) return } @@ -457,14 +472,6 @@ func (e *EndpointController) syncService(key string) { } } -func verifyPodHostNamesAreEqual(newPodHostNames string, oldAnnotations map[string]string) bool { - oldPodHostNames := "" - if oldAnnotations != nil { - oldPodHostNames = oldAnnotations[endpoints.PodHostnamesAnnotation] - } - return oldPodHostNames == newPodHostNames -} - // checkLeftoverEndpoints lists all currently existing endpoints and adds their // service to the queue. This will detect endpoints that exist with no // corresponding service; these endpoints need to be deleted. We only need to diff --git a/pkg/kubelet/container/helpers.go b/pkg/kubelet/container/helpers.go index 781080b6669..35291d02028 100644 --- a/pkg/kubelet/container/helpers.go +++ b/pkg/kubelet/container/helpers.go @@ -42,8 +42,8 @@ type HandlerRunner interface { type RuntimeHelper interface { GenerateRunContainerOptions(pod *api.Pod, container *api.Container, podIP string) (*RunContainerOptions, error) GetClusterDNS(pod *api.Pod) (dnsServers []string, dnsSearches []string, err error) - GeneratePodHostNameAndDomain(pod *api.Pod) (hostname string, hostDomain string) GetPodDir(podUID types.UID) string + GeneratePodHostNameAndDomain(pod *api.Pod) (hostname string, hostDomain string, err error) } // ShouldContainerBeRestarted checks whether a container needs to be restarted. diff --git a/pkg/kubelet/dockertools/manager_test.go b/pkg/kubelet/dockertools/manager_test.go index bf5f1b7c851..842b7f0c760 100644 --- a/pkg/kubelet/dockertools/manager_test.go +++ b/pkg/kubelet/dockertools/manager_test.go @@ -88,8 +88,8 @@ func (f *fakeRuntimeHelper) GetClusterDNS(pod *api.Pod) ([]string, []string, err } // This is not used by docker runtime. -func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { - return "", "" +func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string, error) { + return "", "", nil } func (f *fakeRuntimeHelper) GetPodDir(types.UID) string { diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 3d89c070848..0ac143897c2 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -1344,7 +1344,7 @@ func makePortMappings(container *api.Container) (ports []kubecontainer.PortMappi return } -func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { +func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string, error) { // TODO(vmarmol): Handle better. // Cap hostname at 63 chars (specification is 64bytes which is 63 chars and the null terminating char). clusterDomain := kl.clusterDomain @@ -1354,10 +1354,18 @@ func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { podAnnotations = make(map[string]string) } hostname := pod.Name - hostnameCandidate := podAnnotations[utilpod.PodHostnameAnnotation] - if utilvalidation.IsDNS1123Label(hostnameCandidate) { - // use hostname annotation, if specified. - hostname = hostnameCandidate + if len(pod.Spec.Hostname) > 0 { + if utilvalidation.IsDNS1123Label(pod.Spec.Hostname) { + hostname = pod.Spec.Hostname + } else { + return "", "", fmt.Errorf("Pod Hostname %q is not a valid DNS label.", pod.Spec.Hostname) + } + } else { + hostnameCandidate := podAnnotations[utilpod.PodHostnameAnnotation] + if utilvalidation.IsDNS1123Label(hostnameCandidate) { + // use hostname annotation, if specified. + hostname = hostnameCandidate + } } if len(hostname) > hostnameMaxLen { hostname = hostname[:hostnameMaxLen] @@ -1365,11 +1373,19 @@ func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { } hostDomain := "" - subdomainCandidate := pod.Annotations[utilpod.PodSubdomainAnnotation] - if utilvalidation.IsDNS1123Label(subdomainCandidate) { - hostDomain = fmt.Sprintf("%s.%s.svc.%s", subdomainCandidate, pod.Namespace, clusterDomain) + if len(pod.Spec.Subdomain) > 0 { + if utilvalidation.IsDNS1123Label(pod.Spec.Subdomain) { + hostDomain = fmt.Sprintf("%s.%s.svc.%s", pod.Spec.Subdomain, pod.Namespace, clusterDomain) + } else { + return "", "", fmt.Errorf("Pod Subdomain %q is not a valid DNS label.", pod.Spec.Subdomain) + } + } else { + subdomainCandidate := pod.Annotations[utilpod.PodSubdomainAnnotation] + if utilvalidation.IsDNS1123Label(subdomainCandidate) { + hostDomain = fmt.Sprintf("%s.%s.svc.%s", subdomainCandidate, pod.Namespace, clusterDomain) + } } - return hostname, hostDomain + return hostname, hostDomain, nil } // GenerateRunContainerOptions generates the RunContainerOptions, which can be used by @@ -1377,7 +1393,10 @@ func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Container, podIP string) (*kubecontainer.RunContainerOptions, error) { var err error opts := &kubecontainer.RunContainerOptions{CgroupParent: kl.cgroupRoot} - hostname, hostDomainName := kl.GeneratePodHostNameAndDomain(pod) + hostname, hostDomainName, err := kl.GeneratePodHostNameAndDomain(pod) + if err != nil { + return nil, err + } opts.Hostname = hostname vol, ok := kl.volumeManager.GetVolumes(pod.UID) if !ok { diff --git a/pkg/kubelet/rkt/fake_rkt_interface_test.go b/pkg/kubelet/rkt/fake_rkt_interface_test.go index 83b3874f7af..71906ea16e7 100644 --- a/pkg/kubelet/rkt/fake_rkt_interface_test.go +++ b/pkg/kubelet/rkt/fake_rkt_interface_test.go @@ -164,8 +164,8 @@ func (f *fakeRuntimeHelper) GetClusterDNS(pod *api.Pod) ([]string, []string, err return f.dnsServers, f.dnsSearches, f.err } -func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { - return f.hostName, f.hostDomain +func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string, error) { + return f.hostName, f.hostDomain, nil } func (f *fakeRuntimeHelper) GetPodDir(podUID types.UID) string { diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index a29cc08d69e..dd106c3b4ca 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -858,9 +858,11 @@ func (r *Runtime) generateRunCommand(pod *api.Pod, uuid string) (string, error) } // TODO(yifan): host domain is not being used. - hostname, _ = r.runtimeHelper.GeneratePodHostNameAndDomain(pod) + hostname, _, err = r.runtimeHelper.GeneratePodHostNameAndDomain(pod) + if err != nil { + return "", err + } } - runPrepared = append(runPrepared, fmt.Sprintf("--hostname=%s", hostname)) runPrepared = append(runPrepared, uuid) return strings.Join(runPrepared, " "), nil diff --git a/test/e2e/dns.go b/test/e2e/dns.go index 0a1e53c9941..f5bb50230a8 100644 --- a/test/e2e/dns.go +++ b/test/e2e/dns.go @@ -42,8 +42,8 @@ var dnsServiceLabelSelector = labels.Set{ "kubernetes.io/cluster-service": "true", }.AsSelector() -func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *api.Pod { - pod := &api.Pod{ +func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string, useAnnotation bool) *api.Pod { + dnsPod := &api.Pod{ TypeMeta: unversioned.TypeMeta{ Kind: "Pod", APIVersion: registered.GroupOrDie(api.GroupName).GroupVersion.String(), @@ -51,10 +51,6 @@ func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *api.Pod { ObjectMeta: api.ObjectMeta{ Name: "dns-test-" + string(util.NewUUID()), Namespace: namespace, - Annotations: map[string]string{ - pod.PodHostnameAnnotation: dnsTestPodHostName, - pod.PodSubdomainAnnotation: dnsTestServiceName, - }, }, Spec: api.PodSpec{ Volumes: []api.Volume{ @@ -108,7 +104,17 @@ func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *api.Pod { }, }, } - return pod + + if useAnnotation { + dnsPod.ObjectMeta.Annotations = map[string]string{ + pod.PodHostnameAnnotation: dnsTestPodHostName, + pod.PodSubdomainAnnotation: dnsTestServiceName, + } + } else { + dnsPod.Spec.Hostname = dnsTestPodHostName + dnsPod.Spec.Subdomain = dnsTestServiceName + } + return dnsPod } func createProbeCommand(namesToResolve []string, hostEntries []string, fileNamePrefix, namespace string) (string, []string) { @@ -268,15 +274,16 @@ var _ = framework.KubeDescribe("DNS", func() { if framework.ProviderIs("gce", "gke") { namesToResolve = append(namesToResolve, "metadata") } - - wheezyProbeCmd, wheezyFileNames := createProbeCommand(namesToResolve, nil, "wheezy", f.Namespace.Name) - jessieProbeCmd, jessieFileNames := createProbeCommand(namesToResolve, nil, "jessie", f.Namespace.Name) + hostFQDN := fmt.Sprintf("%s.%s.%s.svc.cluster.local", dnsTestPodHostName, dnsTestServiceName, f.Namespace.Name) + hostEntries := []string{hostFQDN, dnsTestPodHostName} + wheezyProbeCmd, wheezyFileNames := createProbeCommand(namesToResolve, hostEntries, "wheezy", f.Namespace.Name) + jessieProbeCmd, jessieFileNames := createProbeCommand(namesToResolve, hostEntries, "jessie", f.Namespace.Name) By("Running these commands on wheezy:" + wheezyProbeCmd + "\n") By("Running these commands on jessie:" + jessieProbeCmd + "\n") // Run a pod which probes DNS and exposes the results by HTTP. By("creating a pod to probe DNS") - pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, true) validateDNSResults(f, pod, append(wheezyFileNames, jessieFileNames...)) }) @@ -324,7 +331,7 @@ var _ = framework.KubeDescribe("DNS", func() { // Run a pod which probes DNS and exposes the results by HTTP. By("creating a pod to probe DNS") - pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, false) pod.ObjectMeta.Labels = testServiceSelector validateDNSResults(f, pod, append(wheezyFileNames, jessieFileNames...)) @@ -350,14 +357,16 @@ var _ = framework.KubeDescribe("DNS", func() { }() hostFQDN := fmt.Sprintf("%s.%s.%s.svc.cluster.local", podHostname, serviceName, f.Namespace.Name) - wheezyProbeCmd, wheezyFileNames := createProbeCommand([]string{hostFQDN}, []string{hostFQDN, podHostname}, "wheezy", f.Namespace.Name) - jessieProbeCmd, jessieFileNames := createProbeCommand([]string{hostFQDN}, []string{hostFQDN, podHostname}, "jessie", f.Namespace.Name) + hostNames := []string{hostFQDN, podHostname} + namesToResolve := []string{hostFQDN} + wheezyProbeCmd, wheezyFileNames := createProbeCommand(namesToResolve, hostNames, "wheezy", f.Namespace.Name) + jessieProbeCmd, jessieFileNames := createProbeCommand(namesToResolve, hostNames, "jessie", f.Namespace.Name) By("Running these commands on wheezy:" + wheezyProbeCmd + "\n") By("Running these commands on jessie:" + jessieProbeCmd + "\n") // Run a pod which probes DNS and exposes the results by HTTP. By("creating a pod to probe DNS") - pod1 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod1 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, true) pod1.ObjectMeta.Labels = testServiceSelector pod1.ObjectMeta.Annotations = map[string]string{ pod.PodHostnameAnnotation: podHostname,