Merge pull request #24362 from ArtfulCoder/hostname-field

Automatic merge from submit-queue

Promote Pod Hostname & Subdomain to fields (were annotations)

Deprecating the podHostName, subdomain and PodHostnames annotations and created corresponding new fields for them on PodSpec and Endpoints types.

Annotation doc: #22564
Annotation code: #20688
This commit is contained in:
k8s-merge-robot 2016-04-29 01:06:45 -07:00
commit ad67363c12
42 changed files with 979 additions and 343 deletions

View File

@ -1160,6 +1160,14 @@
"$ref": "v1.LocalObjectReference" "$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" "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."
} }
} }
}, },

View File

@ -1165,6 +1165,14 @@
"$ref": "v1.LocalObjectReference" "$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" "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."
} }
} }
}, },

View File

@ -6699,6 +6699,14 @@
"$ref": "v1.LocalObjectReference" "$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" "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."
} }
} }
}, },

View File

@ -15501,6 +15501,10 @@
"type": "string", "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." "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": { "targetRef": {
"$ref": "v1.ObjectReference", "$ref": "v1.ObjectReference",
"description": "Reference to object providing the endpoint." "description": "Reference to object providing the endpoint."
@ -16820,6 +16824,14 @@
"$ref": "v1.LocalObjectReference" "$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" "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."
} }
} }
}, },

View File

@ -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`. 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. 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. 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. 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". 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. 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 "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>". If the annotation is specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
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" 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. 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"}}'. 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 <hostname>.<service name>.<pod namespace>.svc.<cluster domain> If the Endpoints are for a headless service, then A records will be created with the format <hostname>.<service name>.<pod namespace>.svc.<cluster domain>
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". 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. 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? ## How do I find the DNS server?
The DNS server itself runs as a Kubernetes Service. This gives it a stable IP 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 address. When you run the SkyDNS service, you want to assign a static IP to use for

View File

@ -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 { 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 idx := range e.Subsets {
for subIdx := range e.Subsets[idx].Addresses { 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)) b, err := json.Marshal(getSkyMsg(endpointIP, 0))
if err != nil { if err != nil {
return err return err
} }
recordValue := string(b) recordValue := string(b)
recordLabel := getHash(recordValue) var recordLabel string
if serializedPodHostnames := e.Annotations[endpoints.PodHostnamesAnnotation]; len(serializedPodHostnames) > 0 { if hostLabel, exists := getHostname(address, podHostnames); exists {
podHostnames := map[string]endpoints.HostRecord{} recordLabel = hostLabel
err := json.Unmarshal([]byte(serializedPodHostnames), &podHostnames) } else {
if err != nil { recordLabel = getHash(recordValue)
return err
}
if hostRecord, exists := podHostnames[string(endpointIP)]; exists {
if validation.IsDNS1123Label(hostRecord.HostName) {
recordLabel = hostRecord.HostName
}
}
} }
recordKey := buildDNSNameString(subdomain, recordLabel) recordKey := buildDNSNameString(subdomain, recordLabel)
glog.V(2).Infof("Setting DNS record: %v -> %q\n", recordKey, recordValue) 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 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) { func (ks *kube2sky) getServiceFromEndpoints(e *kapi.Endpoints) (*kapi.Service, error) {
key, err := kcache.MetaNamespaceKeyFunc(e) key, err := kcache.MetaNamespaceKeyFunc(e)
if err != nil { if err != nil {

View File

@ -50,7 +50,7 @@ spec:
- name: etcd-storage - name: etcd-storage
mountPath: /var/etcd/data mountPath: /var/etcd/data
- name: kube2sky - name: kube2sky
image: gcr.io/google_containers/kube2sky:1.14 image: gcr.io/google_containers/kube2sky-amd64:1.15
resources: resources:
# TODO: Set memory limits when we've profiled the container for large # TODO: Set memory limits when we've profiled the container for large
# clusters, then set request = limit to keep this container in # clusters, then set request = limit to keep this container in

View File

@ -1244,7 +1244,7 @@ Examples:<br>
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-15 01:05:48 UTC Last updated 2016-04-27 19:28:56 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -2122,7 +2122,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-22 03:24:34 UTC Last updated 2016-04-27 19:28:56 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -3544,6 +3544,20 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostname</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the hostname of the Pod If not specified, the pod&#8217;s hostname will be set to a system-defined value.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">subdomain</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If specified, the fully qualified Pod hostname will be "&lt;hostname&gt;.&lt;subdomain&gt;.&lt;pod namespace&gt;.svc.&lt;cluster domain&gt;". If not specified, the pod will not have a domainname at all.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -3882,7 +3896,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-15 09:27:17 UTC Last updated 2016-04-27 19:28:50 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -2122,7 +2122,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-22 03:24:25 UTC Last updated 2016-04-27 19:28:50 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -3403,6 +3403,20 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostname</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the hostname of the Pod If not specified, the pod&#8217;s hostname will be set to a system-defined value.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">subdomain</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If specified, the fully qualified Pod hostname will be "&lt;hostname&gt;.&lt;subdomain&gt;.&lt;pod namespace&gt;.svc.&lt;cluster domain&gt;". If not specified, the pod will not have a domainname at all.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -5872,7 +5886,7 @@ Both these may change in the future. Incoming requests are matched against the h
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-15 09:26:56 UTC Last updated 2016-04-27 19:28:44 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -13309,7 +13309,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-22 03:24:17 UTC Last updated 2016-04-27 19:28:44 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -4145,6 +4145,20 @@ The resulting set of endpoints can be viewed as:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostname</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specifies the hostname of the Pod If not specified, the pod&#8217;s hostname will be set to a system-defined value.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">subdomain</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If specified, the fully qualified Pod hostname will be "&lt;hostname&gt;.&lt;subdomain&gt;.&lt;pod namespace&gt;.svc.&lt;cluster domain&gt;". If not specified, the pod will not have a domainname at all.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -7687,6 +7701,13 @@ The resulting set of endpoints can be viewed as:<br>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostname</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The Hostname of this endpoint</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">targetRef</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">targetRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Reference to object providing the endpoint.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Reference to object providing the endpoint.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
@ -7742,7 +7763,7 @@ The resulting set of endpoints can be viewed as:<br>
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-21 02:45:03 UTC Last updated 2016-04-27 19:28:36 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -30700,7 +30700,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2016-04-22 03:24:07 UTC Last updated 2016-04-27 19:28:36 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -661,6 +661,7 @@ func DeepCopy_api_EmptyDirVolumeSource(in EmptyDirVolumeSource, out *EmptyDirVol
func DeepCopy_api_EndpointAddress(in EndpointAddress, out *EndpointAddress, c *conversion.Cloner) error { func DeepCopy_api_EndpointAddress(in EndpointAddress, out *EndpointAddress, c *conversion.Cloner) error {
out.IP = in.IP out.IP = in.IP
out.Hostname = in.Hostname
if in.TargetRef != nil { if in.TargetRef != nil {
in, out := in.TargetRef, &out.TargetRef in, out := in.TargetRef, &out.TargetRef
*out = new(ObjectReference) *out = new(ObjectReference)
@ -2158,6 +2159,8 @@ func DeepCopy_api_PodSpec(in PodSpec, out *PodSpec, c *conversion.Cloner) error
} else { } else {
out.ImagePullSecrets = nil out.ImagePullSecrets = nil
} }
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil return nil
} }

View File

@ -29,11 +29,13 @@ import (
) )
const ( const (
// TODO: to be deleted after v1.3 is released
// Its value is the json representation of map[string(IP)][HostRecord] // Its value is the json representation of map[string(IP)][HostRecord]
// example: '{"10.245.1.6":{"HostName":"my-webserver"}}' // example: '{"10.245.1.6":{"HostName":"my-webserver"}}'
PodHostnamesAnnotation = "endpoints.beta.kubernetes.io/hostnames-map" PodHostnamesAnnotation = "endpoints.beta.kubernetes.io/hostnames-map"
) )
// TODO: to be deleted after v1.3 is released
type HostRecord struct { type HostRecord struct {
HostName string HostName string
} }

View File

@ -24,9 +24,11 @@ import (
) )
const ( 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' // 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" 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" // The annotation value is a string specifying the subdomain e.g. "my-web-service"
// If specified, on the the pod itself, "<hostname>.my-web-service.<namespace>.svc.<cluster domain>" would resolve to // If specified, on the the pod itself, "<hostname>.my-web-service.<namespace>.svc.<cluster domain>" would resolve to
// the pod's IP. // the pod's IP.

View File

@ -23218,7 +23218,7 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) {
} else { } else {
yysep2 := !z.EncBinary() yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [11]bool var yyq2 [13]bool
_, _, _ = yysep2, yyq2, yy2arr2 _, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false const yyr2 bool = false
yyq2[2] = x.RestartPolicy != "" yyq2[2] = x.RestartPolicy != ""
@ -23229,9 +23229,11 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) {
yyq2[8] = x.NodeName != "" yyq2[8] = x.NodeName != ""
yyq2[9] = x.SecurityContext != nil yyq2[9] = x.SecurityContext != nil
yyq2[10] = len(x.ImagePullSecrets) != 0 yyq2[10] = len(x.ImagePullSecrets) != 0
yyq2[11] = x.Hostname != ""
yyq2[12] = x.Subdomain != ""
var yynn2 int var yynn2 int
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
r.EncodeArrayStart(11) r.EncodeArrayStart(13)
} else { } else {
yynn2 = 3 yynn2 = 3
for _, b := range yyq2 { 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 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234) z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else { } else {
@ -23705,6 +23757,18 @@ func (x *PodSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv19), d) 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: default:
z.DecStructFieldNotFound(-1, yys3) z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3 } // end switch yys3
@ -23716,16 +23780,16 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d) z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r _, _, _ = h, z, r
var yyj21 int var yyj23 int
var yyb21 bool var yyb23 bool
var yyhl21 bool = l >= 0 var yyhl23 bool = l >= 0
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23733,21 +23797,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Volumes = nil x.Volumes = nil
} else { } else {
yyv22 := &x.Volumes yyv24 := &x.Volumes
yym23 := z.DecBinary() yym25 := z.DecBinary()
_ = yym23 _ = yym25
if false { if false {
} else { } else {
h.decSliceVolume((*[]Volume)(yyv22), d) h.decSliceVolume((*[]Volume)(yyv24), d)
} }
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23755,21 +23819,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Containers = nil x.Containers = nil
} else { } else {
yyv24 := &x.Containers yyv26 := &x.Containers
yym25 := z.DecBinary() yym27 := z.DecBinary()
_ = yym25 _ = yym27
if false { if false {
} else { } else {
h.decSliceContainer((*[]Container)(yyv24), d) h.decSliceContainer((*[]Container)(yyv26), d)
} }
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23779,13 +23843,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.RestartPolicy = RestartPolicy(r.DecodeString()) x.RestartPolicy = RestartPolicy(r.DecodeString())
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23798,20 +23862,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if x.TerminationGracePeriodSeconds == nil { if x.TerminationGracePeriodSeconds == nil {
x.TerminationGracePeriodSeconds = new(int64) x.TerminationGracePeriodSeconds = new(int64)
} }
yym28 := z.DecBinary() yym30 := z.DecBinary()
_ = yym28 _ = yym30
if false { if false {
} else { } else {
*((*int64)(x.TerminationGracePeriodSeconds)) = int64(r.DecodeInt(64)) *((*int64)(x.TerminationGracePeriodSeconds)) = int64(r.DecodeInt(64))
} }
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23824,20 +23888,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if x.ActiveDeadlineSeconds == nil { if x.ActiveDeadlineSeconds == nil {
x.ActiveDeadlineSeconds = new(int64) x.ActiveDeadlineSeconds = new(int64)
} }
yym30 := z.DecBinary() yym32 := z.DecBinary()
_ = yym30 _ = yym32
if false { if false {
} else { } else {
*((*int64)(x.ActiveDeadlineSeconds)) = int64(r.DecodeInt(64)) *((*int64)(x.ActiveDeadlineSeconds)) = int64(r.DecodeInt(64))
} }
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23847,13 +23911,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.DNSPolicy = DNSPolicy(r.DecodeString()) x.DNSPolicy = DNSPolicy(r.DecodeString())
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23861,21 +23925,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.NodeSelector = nil x.NodeSelector = nil
} else { } else {
yyv32 := &x.NodeSelector yyv34 := &x.NodeSelector
yym33 := z.DecBinary() yym35 := z.DecBinary()
_ = yym33 _ = yym35
if false { if false {
} else { } else {
z.F.DecMapStringStringX(yyv32, false, d) z.F.DecMapStringStringX(yyv34, false, d)
} }
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23885,13 +23949,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.ServiceAccountName = string(r.DecodeString()) x.ServiceAccountName = string(r.DecodeString())
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23901,13 +23965,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.NodeName = string(r.DecodeString()) x.NodeName = string(r.DecodeString())
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23922,13 +23986,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} }
x.SecurityContext.CodecDecodeSelf(d) x.SecurityContext.CodecDecodeSelf(d)
} }
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23936,26 +24000,58 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.ImagePullSecrets = nil x.ImagePullSecrets = nil
} else { } else {
yyv37 := &x.ImagePullSecrets yyv39 := &x.ImagePullSecrets
yym38 := z.DecBinary() yym40 := z.DecBinary()
_ = yym38 _ = yym40
if false { if false {
} else { } 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 { for {
yyj21++ yyj23++
if yyhl21 { if yyhl23 {
yyb21 = yyj21 > l yyb23 = yyj23 > l
} else { } else {
yyb21 = r.CheckBreak() yyb23 = r.CheckBreak()
} }
if yyb21 { if yyb23 {
break break
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj21-1, "") z.DecStructFieldNotFound(yyj23-1, "")
} }
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} }
@ -31387,12 +31483,13 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) {
} else { } else {
yysep2 := !z.EncBinary() yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [2]bool var yyq2 [3]bool
_, _, _ = yysep2, yyq2, yy2arr2 _, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false const yyr2 bool = false
yyq2[1] = x.Hostname != ""
var yynn2 int var yynn2 int
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
r.EncodeArrayStart(2) r.EncodeArrayStart(3)
} else { } else {
yynn2 = 2 yynn2 = 2
for _, b := range yyq2 { for _, b := range yyq2 {
@ -31422,6 +31519,31 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) {
r.EncodeString(codecSelferC_UTF81234, string(x.IP)) 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 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234) z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if x.TargetRef == nil { if x.TargetRef == nil {
@ -31506,6 +31628,12 @@ func (x *EndpointAddress) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
} else { } else {
x.IP = string(r.DecodeString()) x.IP = string(r.DecodeString())
} }
case "hostname":
if r.TryDecodeAsNil() {
x.Hostname = ""
} else {
x.Hostname = string(r.DecodeString())
}
case "TargetRef": case "TargetRef":
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
if x.TargetRef != nil { if x.TargetRef != nil {
@ -31528,16 +31656,16 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d) z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r _, _, _ = h, z, r
var yyj6 int var yyj7 int
var yyb6 bool var yyb7 bool
var yyhl6 bool = l >= 0 var yyhl7 bool = l >= 0
yyj6++ yyj7++
if yyhl6 { if yyhl7 {
yyb6 = yyj6 > l yyb7 = yyj7 > l
} else { } else {
yyb6 = r.CheckBreak() yyb7 = r.CheckBreak()
} }
if yyb6 { if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -31547,13 +31675,29 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
} else { } else {
x.IP = string(r.DecodeString()) x.IP = string(r.DecodeString())
} }
yyj6++ yyj7++
if yyhl6 { if yyhl7 {
yyb6 = yyj6 > l yyb7 = yyj7 > l
} else { } 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) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -31569,17 +31713,17 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
x.TargetRef.CodecDecodeSelf(d) x.TargetRef.CodecDecodeSelf(d)
} }
for { for {
yyj6++ yyj7++
if yyhl6 { if yyhl7 {
yyb6 = yyj6 > l yyb7 = yyj7 > l
} else { } else {
yyb6 = r.CheckBreak() yyb7 = r.CheckBreak()
} }
if yyb6 { if yyb7 {
break break
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj6-1, "") z.DecStructFieldNotFound(yyj7-1, "")
} }
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} }
@ -50513,7 +50657,7 @@ func (x codecSelfer1234) decSlicePod(v *[]Pod, d *codec1978.Decoder) {
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 496) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 528)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -51584,7 +51728,7 @@ func (x codecSelfer1234) decSlicePodTemplate(v *[]PodTemplate, d *codec1978.Deco
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 520) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 552)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -52536,7 +52680,7 @@ func (x codecSelfer1234) decSliceEndpointAddress(v *[]EndpointAddress, d *codec1
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 24) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -1229,6 +1229,12 @@ type PodSpec struct {
// If specified, these secrets will be passed to individual puller implementations for them to use. For example, // 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. // in the case of docker, only DockerConfig type secrets are honored.
ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty"` 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 "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
// 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. // 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. // kubernetes components, like kube-proxy, are not IPv6 ready.
// TODO: This should allow hostname or IP, see #4447. // TODO: This should allow hostname or IP, see #4447.
IP string 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. // Optional: The kubernetes object related to the entry point.
TargetRef *ObjectReference TargetRef *ObjectReference
} }

View File

@ -338,6 +338,8 @@ func Convert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversi
} else { } else {
out.ImagePullSecrets = nil out.ImagePullSecrets = nil
} }
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil return nil
} }
@ -419,7 +421,8 @@ func Convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversi
} else { } else {
out.ImagePullSecrets = nil out.ImagePullSecrets = nil
} }
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil return nil
} }

View File

@ -1619,6 +1619,7 @@ func autoConvert_v1_EndpointAddress_To_api_EndpointAddress(in *EndpointAddress,
defaulting.(func(*EndpointAddress))(in) defaulting.(func(*EndpointAddress))(in)
} }
out.IP = in.IP out.IP = in.IP
out.Hostname = in.Hostname
if in.TargetRef != nil { if in.TargetRef != nil {
in, out := &in.TargetRef, &out.TargetRef in, out := &in.TargetRef, &out.TargetRef
*out = new(api.ObjectReference) *out = new(api.ObjectReference)
@ -1640,6 +1641,7 @@ func autoConvert_api_EndpointAddress_To_v1_EndpointAddress(in *api.EndpointAddre
defaulting.(func(*api.EndpointAddress))(in) defaulting.(func(*api.EndpointAddress))(in)
} }
out.IP = in.IP out.IP = in.IP
out.Hostname = in.Hostname
if in.TargetRef != nil { if in.TargetRef != nil {
in, out := &in.TargetRef, &out.TargetRef in, out := &in.TargetRef, &out.TargetRef
*out = new(ObjectReference) *out = new(ObjectReference)
@ -5357,6 +5359,8 @@ func autoConvert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conv
} else { } else {
out.ImagePullSecrets = nil out.ImagePullSecrets = nil
} }
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil return nil
} }

View File

@ -639,6 +639,7 @@ func DeepCopy_v1_EmptyDirVolumeSource(in EmptyDirVolumeSource, out *EmptyDirVolu
func DeepCopy_v1_EndpointAddress(in EndpointAddress, out *EndpointAddress, c *conversion.Cloner) error { func DeepCopy_v1_EndpointAddress(in EndpointAddress, out *EndpointAddress, c *conversion.Cloner) error {
out.IP = in.IP out.IP = in.IP
out.Hostname = in.Hostname
if in.TargetRef != nil { if in.TargetRef != nil {
in, out := in.TargetRef, &out.TargetRef in, out := in.TargetRef, &out.TargetRef
*out = new(ObjectReference) *out = new(ObjectReference)
@ -2106,6 +2107,8 @@ func DeepCopy_v1_PodSpec(in PodSpec, out *PodSpec, c *conversion.Cloner) error {
} else { } else {
out.ImagePullSecrets = nil out.ImagePullSecrets = nil
} }
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil return nil
} }

View File

@ -2050,6 +2050,10 @@ func (m *EndpointAddress) MarshalTo(data []byte) (int, error) {
} }
i += n26 i += n26
} }
data[i] = 0x1a
i++
i = encodeVarintGenerated(data, i, uint64(len(m.Hostname)))
i += copy(data[i:], m.Hostname)
return i, nil return i, nil
} }
@ -5358,6 +5362,18 @@ func (m *PodSpec) MarshalTo(data []byte) (int, error) {
i += n 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 return i, nil
} }
@ -7560,6 +7576,8 @@ func (m *EndpointAddress) Size() (n int) {
l = m.TargetRef.Size() l = m.TargetRef.Size()
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
} }
l = len(m.Hostname)
n += 1 + l + sovGenerated(uint64(l))
return n return n
} }
@ -8775,6 +8793,10 @@ func (m *PodSpec) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l)) 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 return n
} }
@ -13473,6 +13495,35 @@ func (m *EndpointAddress) Unmarshal(data []byte) error {
return err return err
} }
iNdEx = postIndex 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: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipGenerated(data[iNdEx:]) skippy, err := skipGenerated(data[iNdEx:])
@ -25543,6 +25594,64 @@ func (m *PodSpec) Unmarshal(data []byte) error {
return err return err
} }
iNdEx = postIndex 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: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipGenerated(data[iNdEx:]) skippy, err := skipGenerated(data[iNdEx:])

View File

@ -524,6 +524,9 @@ message EndpointAddress {
// TODO: This should allow hostname or IP, See #4447. // TODO: This should allow hostname or IP, See #4447.
optional string ip = 1; optional string ip = 1;
// The Hostname of this endpoint
optional string hostname = 3;
// Reference to object providing the endpoint. // Reference to object providing the endpoint.
optional ObjectReference targetRef = 2; optional ObjectReference targetRef = 2;
} }
@ -1946,6 +1949,14 @@ message PodSpec {
// in the case of docker, only DockerConfig type secrets are honored. // 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 // More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod
repeated LocalObjectReference imagePullSecrets = 15; 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 "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
// 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 // PodStatus represents information about the status of a pod. Status may trail the actual

View File

@ -22498,7 +22498,7 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) {
} else { } else {
yysep2 := !z.EncBinary() yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [15]bool var yyq2 [17]bool
_, _, _ = yysep2, yyq2, yy2arr2 _, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false const yyr2 bool = false
yyq2[0] = len(x.Volumes) != 0 yyq2[0] = len(x.Volumes) != 0
@ -22515,9 +22515,11 @@ func (x *PodSpec) CodecEncodeSelf(e *codec1978.Encoder) {
yyq2[12] = x.HostIPC != false yyq2[12] = x.HostIPC != false
yyq2[13] = x.SecurityContext != nil yyq2[13] = x.SecurityContext != nil
yyq2[14] = len(x.ImagePullSecrets) != 0 yyq2[14] = len(x.ImagePullSecrets) != 0
yyq2[15] = x.Hostname != ""
yyq2[16] = x.Subdomain != ""
var yynn2 int var yynn2 int
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
r.EncodeArrayStart(15) r.EncodeArrayStart(17)
} else { } else {
yynn2 = 1 yynn2 = 1
for _, b := range yyq2 { 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 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234) z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else { } else {
@ -23127,6 +23179,18 @@ func (x *PodSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
h.decSliceLocalObjectReference((*[]LocalObjectReference)(yyv23), d) 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: default:
z.DecStructFieldNotFound(-1, yys3) z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3 } // end switch yys3
@ -23138,16 +23202,16 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d) z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r _, _, _ = h, z, r
var yyj25 int var yyj27 int
var yyb25 bool var yyb27 bool
var yyhl25 bool = l >= 0 var yyhl27 bool = l >= 0
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23155,21 +23219,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Volumes = nil x.Volumes = nil
} else { } else {
yyv26 := &x.Volumes yyv28 := &x.Volumes
yym27 := z.DecBinary() yym29 := z.DecBinary()
_ = yym27 _ = yym29
if false { if false {
} else { } else {
h.decSliceVolume((*[]Volume)(yyv26), d) h.decSliceVolume((*[]Volume)(yyv28), d)
} }
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23177,21 +23241,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Containers = nil x.Containers = nil
} else { } else {
yyv28 := &x.Containers yyv30 := &x.Containers
yym29 := z.DecBinary() yym31 := z.DecBinary()
_ = yym29 _ = yym31
if false { if false {
} else { } else {
h.decSliceContainer((*[]Container)(yyv28), d) h.decSliceContainer((*[]Container)(yyv30), d)
} }
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23201,13 +23265,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.RestartPolicy = RestartPolicy(r.DecodeString()) x.RestartPolicy = RestartPolicy(r.DecodeString())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23220,20 +23284,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if x.TerminationGracePeriodSeconds == nil { if x.TerminationGracePeriodSeconds == nil {
x.TerminationGracePeriodSeconds = new(int64) x.TerminationGracePeriodSeconds = new(int64)
} }
yym32 := z.DecBinary() yym34 := z.DecBinary()
_ = yym32 _ = yym34
if false { if false {
} else { } else {
*((*int64)(x.TerminationGracePeriodSeconds)) = int64(r.DecodeInt(64)) *((*int64)(x.TerminationGracePeriodSeconds)) = int64(r.DecodeInt(64))
} }
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23246,20 +23310,20 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if x.ActiveDeadlineSeconds == nil { if x.ActiveDeadlineSeconds == nil {
x.ActiveDeadlineSeconds = new(int64) x.ActiveDeadlineSeconds = new(int64)
} }
yym34 := z.DecBinary() yym36 := z.DecBinary()
_ = yym34 _ = yym36
if false { if false {
} else { } else {
*((*int64)(x.ActiveDeadlineSeconds)) = int64(r.DecodeInt(64)) *((*int64)(x.ActiveDeadlineSeconds)) = int64(r.DecodeInt(64))
} }
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23269,13 +23333,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.DNSPolicy = DNSPolicy(r.DecodeString()) x.DNSPolicy = DNSPolicy(r.DecodeString())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23283,21 +23347,21 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.NodeSelector = nil x.NodeSelector = nil
} else { } else {
yyv36 := &x.NodeSelector yyv38 := &x.NodeSelector
yym37 := z.DecBinary() yym39 := z.DecBinary()
_ = yym37 _ = yym39
if false { if false {
} else { } else {
z.F.DecMapStringStringX(yyv36, false, d) z.F.DecMapStringStringX(yyv38, false, d)
} }
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23307,13 +23371,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.ServiceAccountName = string(r.DecodeString()) x.ServiceAccountName = string(r.DecodeString())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23323,13 +23387,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.DeprecatedServiceAccount = string(r.DecodeString()) x.DeprecatedServiceAccount = string(r.DecodeString())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23339,13 +23403,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.NodeName = string(r.DecodeString()) x.NodeName = string(r.DecodeString())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23355,13 +23419,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.HostNetwork = bool(r.DecodeBool()) x.HostNetwork = bool(r.DecodeBool())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23371,13 +23435,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.HostPID = bool(r.DecodeBool()) x.HostPID = bool(r.DecodeBool())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23387,13 +23451,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} else { } else {
x.HostIPC = bool(r.DecodeBool()) x.HostIPC = bool(r.DecodeBool())
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23408,13 +23472,13 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
} }
x.SecurityContext.CodecDecodeSelf(d) x.SecurityContext.CodecDecodeSelf(d)
} }
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -23422,26 +23486,58 @@ func (x *PodSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.ImagePullSecrets = nil x.ImagePullSecrets = nil
} else { } else {
yyv45 := &x.ImagePullSecrets yyv47 := &x.ImagePullSecrets
yym46 := z.DecBinary() yym48 := z.DecBinary()
_ = yym46 _ = yym48
if false { if false {
} else { } 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 { for {
yyj25++ yyj27++
if yyhl25 { if yyhl27 {
yyb25 = yyj25 > l yyb27 = yyj27 > l
} else { } else {
yyb25 = r.CheckBreak() yyb27 = r.CheckBreak()
} }
if yyb25 { if yyb27 {
break break
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj25-1, "") z.DecStructFieldNotFound(yyj27-1, "")
} }
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} }
@ -31248,13 +31344,14 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) {
} else { } else {
yysep2 := !z.EncBinary() yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [2]bool var yyq2 [3]bool
_, _, _ = yysep2, yyq2, yy2arr2 _, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false const yyr2 bool = false
yyq2[1] = x.TargetRef != nil yyq2[1] = x.Hostname != ""
yyq2[2] = x.TargetRef != nil
var yynn2 int var yynn2 int
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
r.EncodeArrayStart(2) r.EncodeArrayStart(3)
} else { } else {
yynn2 = 1 yynn2 = 1
for _, b := range yyq2 { for _, b := range yyq2 {
@ -31287,6 +31384,31 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) {
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234) z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[1] { 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 { if x.TargetRef == nil {
r.EncodeNil() r.EncodeNil()
} else { } else {
@ -31296,7 +31418,7 @@ func (x *EndpointAddress) CodecEncodeSelf(e *codec1978.Encoder) {
r.EncodeNil() r.EncodeNil()
} }
} else { } else {
if yyq2[1] { if yyq2[2] {
z.EncSendContainerState(codecSelfer_containerMapKey1234) z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("targetRef")) r.EncodeString(codecSelferC_UTF81234, string("targetRef"))
z.EncSendContainerState(codecSelfer_containerMapValue1234) z.EncSendContainerState(codecSelfer_containerMapValue1234)
@ -31374,6 +31496,12 @@ func (x *EndpointAddress) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
} else { } else {
x.IP = string(r.DecodeString()) x.IP = string(r.DecodeString())
} }
case "hostname":
if r.TryDecodeAsNil() {
x.Hostname = ""
} else {
x.Hostname = string(r.DecodeString())
}
case "targetRef": case "targetRef":
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
if x.TargetRef != nil { if x.TargetRef != nil {
@ -31396,16 +31524,16 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d) z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r _, _, _ = h, z, r
var yyj6 int var yyj7 int
var yyb6 bool var yyb7 bool
var yyhl6 bool = l >= 0 var yyhl7 bool = l >= 0
yyj6++ yyj7++
if yyhl6 { if yyhl7 {
yyb6 = yyj6 > l yyb7 = yyj7 > l
} else { } else {
yyb6 = r.CheckBreak() yyb7 = r.CheckBreak()
} }
if yyb6 { if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -31415,13 +31543,29 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
} else { } else {
x.IP = string(r.DecodeString()) x.IP = string(r.DecodeString())
} }
yyj6++ yyj7++
if yyhl6 { if yyhl7 {
yyb6 = yyj6 > l yyb7 = yyj7 > l
} else { } 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) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -31437,17 +31581,17 @@ func (x *EndpointAddress) codecDecodeSelfFromArray(l int, d *codec1978.Decoder)
x.TargetRef.CodecDecodeSelf(d) x.TargetRef.CodecDecodeSelf(d)
} }
for { for {
yyj6++ yyj7++
if yyhl6 { if yyhl7 {
yyb6 = yyj6 > l yyb7 = yyj7 > l
} else { } else {
yyb6 = r.CheckBreak() yyb7 = r.CheckBreak()
} }
if yyb6 { if yyb7 {
break break
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj6-1, "") z.DecStructFieldNotFound(yyj7-1, "")
} }
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} }
@ -51518,7 +51662,7 @@ func (x codecSelfer1234) decSlicePod(v *[]Pod, d *codec1978.Decoder) {
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 520) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 552)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -51637,7 +51781,7 @@ func (x codecSelfer1234) decSlicePodTemplate(v *[]PodTemplate, d *codec1978.Deco
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 544) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 576)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -52589,7 +52733,7 @@ func (x codecSelfer1234) decSliceEndpointAddress(v *[]EndpointAddress, d *codec1
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 24) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 40)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -1494,6 +1494,12 @@ type PodSpec struct {
// in the case of docker, only DockerConfig type secrets are honored. // 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 // 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"` 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 "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
// 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. // 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. // kubernetes components, like kube-proxy, are not IPv6 ready.
// TODO: This should allow hostname or IP, See #4447. // TODO: This should allow hostname or IP, See #4447.
IP string `json:"ip" protobuf:"bytes,1,opt,name=ip"` 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. // Reference to object providing the endpoint.
TargetRef *ObjectReference `json:"targetRef,omitempty" protobuf:"bytes,2,opt,name=targetRef"` TargetRef *ObjectReference `json:"targetRef,omitempty" protobuf:"bytes,2,opt,name=targetRef"`
} }

View File

@ -334,6 +334,7 @@ func (EmptyDirVolumeSource) SwaggerDoc() map[string]string {
var map_EndpointAddress = map[string]string{ var map_EndpointAddress = map[string]string{
"": "EndpointAddress is a tuple that describes single IP address.", "": "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.", "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.", "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.", "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.", "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", "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 \"<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>\". If not specified, the pod will not have a domainname at all.",
} }
func (PodSpec) SwaggerDoc() map[string]string { func (PodSpec) SwaggerDoc() map[string]string {

View File

@ -1428,6 +1428,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")) 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 return allErrs
} }
@ -2278,7 +2287,7 @@ func ValidateSecret(secret *api.Secret) field.ErrorList {
if _, exists := secret.Data[api.TLSPrivateKeyKey]; !exists { if _, exists := secret.Data[api.TLSPrivateKeyKey]; !exists {
allErrs = append(allErrs, field.Required(dataPath.Key(api.TLSPrivateKeyKey), "")) 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: default:
// no-op // no-op
} }
@ -2592,6 +2601,9 @@ func validateEndpointSubsets(subsets []api.EndpointSubset, fldPath *field.Path)
for addr := range ss.Addresses { for addr := range ss.Addresses {
allErrs = append(allErrs, validateEndpointAddress(&ss.Addresses[addr], idxPath.Child("addresses").Index(addr))...) 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 { for port := range ss.Ports {
allErrs = append(allErrs, validateEndpointPort(&ss.Ports[port], len(ss.Ports) > 1, idxPath.Child("ports").Index(port))...) allErrs = append(allErrs, validateEndpointPort(&ss.Ports[port], len(ss.Ports) > 1, idxPath.Child("ports").Index(port))...)
} }
@ -2604,6 +2616,11 @@ func validateEndpointAddress(address *api.EndpointAddress, fldPath *field.Path)
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if !validation.IsValidIP(address.IP) { if !validation.IsValidIP(address.IP) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("ip"), address.IP, "must be a valid IP address")) 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 allErrs
} }
return validateIpIsNotLinkLocalOrLoopback(address.IP, fldPath.Child("ip")) return validateIpIsNotLinkLocalOrLoopback(address.IP, fldPath.Child("ip"))

View File

@ -1555,7 +1555,7 @@ func (x codecSelfer1234) decSlicePetSet(v *[]PetSet, d *codec1978.Decoder) {
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 592) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 624)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -1585,7 +1585,7 @@ func (x codecSelfer1234) decSlicePetSet(v *[]PetSet, d *codec1978.Decoder) {
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 616) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 648)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -2347,7 +2347,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) {
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 624) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 656)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -2867,7 +2867,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) {
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 640) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 672)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -15646,7 +15646,7 @@ func (x codecSelfer1234) decSliceDeployment(v *[]Deployment, d *codec1978.Decode
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 632) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 664)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -15765,7 +15765,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder)
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 552) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 584)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -16479,7 +16479,7 @@ func (x codecSelfer1234) decSliceReplicaSet(v *[]ReplicaSet, d *codec1978.Decode
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 560) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 592)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -19242,7 +19242,7 @@ func (x codecSelfer1234) decSliceDeployment(v *[]Deployment, d *codec1978.Decode
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 640) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 672)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -19361,7 +19361,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder)
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 568) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 600)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -19599,7 +19599,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) {
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 640) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 672)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]
@ -20432,7 +20432,7 @@ func (x codecSelfer1234) decSliceReplicaSet(v *[]ReplicaSet, d *codec1978.Decode
yyrg1 := len(yyv1) > 0 yyrg1 := len(yyv1) > 0
yyv21 := yyv1 yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 576) yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 608)
if yyrt1 { if yyrt1 {
if yyrl1 <= cap(yyv1) { if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1] yyv1 = yyv1[:yyrl1]

View File

@ -213,7 +213,7 @@ func (e *EndpointController) updatePod(old, cur interface{}) {
oldPod := cur.(*api.Pod) oldPod := cur.(*api.Pod)
// Only need to get the old services if the labels changed. // Only need to get the old services if the labels changed.
if !reflect.DeepEqual(newPod.Labels, oldPod.Labels) || if !reflect.DeepEqual(newPod.Labels, oldPod.Labels) ||
!hostNameAndDomainAnnotationsAreEqual(newPod.Annotations, oldPod.Annotations) { !hostNameAndDomainAreEqual(newPod, oldPod) {
oldServices, err := e.getPodServiceMemberships(oldPod) oldServices, err := e.getPodServiceMemberships(oldPod)
if err != nil { if err != nil {
glog.Errorf("Unable to get pod %v/%v's service memberships: %v", oldPod.Namespace, oldPod.Name, err) glog.Errorf("Unable to get pod %v/%v's service memberships: %v", oldPod.Namespace, oldPod.Name, err)
@ -226,15 +226,29 @@ func (e *EndpointController) updatePod(old, cur interface{}) {
} }
} }
func hostNameAndDomainAnnotationsAreEqual(annotation1, annotation2 map[string]string) bool { func hostNameAndDomainAreEqual(pod1, pod2 *api.Pod) bool {
if annotation1 == nil { return getHostname(pod1) == getHostname(pod2) &&
annotation1 = map[string]string{} getSubdomain(pod1) == getSubdomain(pod2)
}
func getHostname(pod *api.Pod) string {
if len(pod.Spec.Hostname) > 0 {
return pod.Spec.Hostname
} }
if annotation2 == nil { if pod.Annotations != nil {
annotation2 = map[string]string{} return pod.Annotations[utilpod.PodHostnameAnnotation]
} }
return annotation1[utilpod.PodHostnameAnnotation] == annotation2[utilpod.PodHostnameAnnotation] && return ""
annotation1[utilpod.PodSubdomainAnnotation] == annotation2[utilpod.PodSubdomainAnnotation] }
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. // When a pod is deleted, enqueue the services the pod used to be a member of.
@ -364,16 +378,6 @@ func (e *EndpointController) syncService(key string) {
continue 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} epp := api.EndpointPort{Name: portName, Port: portNum, Protocol: portProto}
epa := api.EndpointAddress{ epa := api.EndpointAddress{
IP: pod.Status.PodIP, IP: pod.Status.PodIP,
@ -384,6 +388,19 @@ func (e *EndpointController) syncService(key string) {
UID: pod.ObjectMeta.UID, UID: pod.ObjectMeta.UID,
ResourceVersion: pod.ObjectMeta.ResourceVersion, 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) { if api.IsPodReady(pod) {
subsets = append(subsets, api.EndpointSubset{ subsets = append(subsets, api.EndpointSubset{
Addresses: []api.EndpointAddress{epa}, Addresses: []api.EndpointAddress{epa},
@ -428,12 +445,10 @@ func (e *EndpointController) syncService(key string) {
serializedPodHostNames = string(b) serializedPodHostNames = string(b)
} }
podHostNamesAreEqual := verifyPodHostNamesAreEqual(serializedPodHostNames, currentEndpoints.Annotations)
newAnnotations := make(map[string]string) newAnnotations := make(map[string]string)
newAnnotations[endpoints.PodHostnamesAnnotation] = serializedPodHostNames newAnnotations[endpoints.PodHostnamesAnnotation] = serializedPodHostNames
if reflect.DeepEqual(currentEndpoints.Subsets, subsets) && 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) glog.V(5).Infof("endpoints are equal for %s/%s, skipping update", service.Namespace, service.Name)
return return
} }
@ -461,14 +476,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 // checkLeftoverEndpoints lists all currently existing endpoints and adds their
// service to the queue. This will detect endpoints that exist with no // service to the queue. This will detect endpoints that exist with no
// corresponding service; these endpoints need to be deleted. We only need to // corresponding service; these endpoints need to be deleted. We only need to

View File

@ -42,8 +42,8 @@ type HandlerRunner interface {
type RuntimeHelper interface { type RuntimeHelper interface {
GenerateRunContainerOptions(pod *api.Pod, container *api.Container, podIP string) (*RunContainerOptions, error) GenerateRunContainerOptions(pod *api.Pod, container *api.Container, podIP string) (*RunContainerOptions, error)
GetClusterDNS(pod *api.Pod) (dnsServers []string, dnsSearches []string, err error) GetClusterDNS(pod *api.Pod) (dnsServers []string, dnsSearches []string, err error)
GeneratePodHostNameAndDomain(pod *api.Pod) (hostname string, hostDomain string)
GetPodDir(podUID types.UID) 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. // ShouldContainerBeRestarted checks whether a container needs to be restarted.

View File

@ -88,8 +88,8 @@ func (f *fakeRuntimeHelper) GetClusterDNS(pod *api.Pod) ([]string, []string, err
} }
// This is not used by docker runtime. // This is not used by docker runtime.
func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string, error) {
return "", "" return "", "", nil
} }
func (f *fakeRuntimeHelper) GetPodDir(types.UID) string { func (f *fakeRuntimeHelper) GetPodDir(types.UID) string {

View File

@ -1379,7 +1379,7 @@ func makePortMappings(container *api.Container) (ports []kubecontainer.PortMappi
return return
} }
func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string, error) {
// TODO(vmarmol): Handle better. // TODO(vmarmol): Handle better.
// Cap hostname at 63 chars (specification is 64bytes which is 63 chars and the null terminating char). // Cap hostname at 63 chars (specification is 64bytes which is 63 chars and the null terminating char).
clusterDomain := kl.clusterDomain clusterDomain := kl.clusterDomain
@ -1389,10 +1389,18 @@ func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) {
podAnnotations = make(map[string]string) podAnnotations = make(map[string]string)
} }
hostname := pod.Name hostname := pod.Name
hostnameCandidate := podAnnotations[utilpod.PodHostnameAnnotation] if len(pod.Spec.Hostname) > 0 {
if utilvalidation.IsDNS1123Label(hostnameCandidate) { if utilvalidation.IsDNS1123Label(pod.Spec.Hostname) {
// use hostname annotation, if specified. hostname = pod.Spec.Hostname
hostname = hostnameCandidate } 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 { if len(hostname) > hostnameMaxLen {
hostname = hostname[:hostnameMaxLen] hostname = hostname[:hostnameMaxLen]
@ -1400,11 +1408,19 @@ func (kl *Kubelet) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) {
} }
hostDomain := "" hostDomain := ""
subdomainCandidate := pod.Annotations[utilpod.PodSubdomainAnnotation] if len(pod.Spec.Subdomain) > 0 {
if utilvalidation.IsDNS1123Label(subdomainCandidate) { if utilvalidation.IsDNS1123Label(pod.Spec.Subdomain) {
hostDomain = fmt.Sprintf("%s.%s.svc.%s", subdomainCandidate, pod.Namespace, clusterDomain) 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 // GenerateRunContainerOptions generates the RunContainerOptions, which can be used by
@ -1412,7 +1428,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) { func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Container, podIP string) (*kubecontainer.RunContainerOptions, error) {
var err error var err error
opts := &kubecontainer.RunContainerOptions{CgroupParent: kl.cgroupRoot} 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 opts.Hostname = hostname
vol, ok := kl.volumeManager.GetVolumes(pod.UID) vol, ok := kl.volumeManager.GetVolumes(pod.UID)
if !ok { if !ok {

View File

@ -164,8 +164,8 @@ func (f *fakeRuntimeHelper) GetClusterDNS(pod *api.Pod) ([]string, []string, err
return f.dnsServers, f.dnsSearches, f.err return f.dnsServers, f.dnsSearches, f.err
} }
func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string) { func (f *fakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *api.Pod) (string, string, error) {
return f.hostName, f.hostDomain return f.hostName, f.hostDomain, nil
} }
func (f *fakeRuntimeHelper) GetPodDir(podUID types.UID) string { func (f *fakeRuntimeHelper) GetPodDir(podUID types.UID) string {

View File

@ -858,9 +858,11 @@ func (r *Runtime) generateRunCommand(pod *api.Pod, uuid string) (string, error)
} }
// TODO(yifan): host domain is not being used. // 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, fmt.Sprintf("--hostname=%s", hostname))
runPrepared = append(runPrepared, uuid) runPrepared = append(runPrepared, uuid)
return strings.Join(runPrepared, " "), nil return strings.Join(runPrepared, " "), nil

View File

@ -42,8 +42,8 @@ var dnsServiceLabelSelector = labels.Set{
"kubernetes.io/cluster-service": "true", "kubernetes.io/cluster-service": "true",
}.AsSelector() }.AsSelector()
func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *api.Pod { func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string, useAnnotation bool) *api.Pod {
pod := &api.Pod{ dnsPod := &api.Pod{
TypeMeta: unversioned.TypeMeta{ TypeMeta: unversioned.TypeMeta{
Kind: "Pod", Kind: "Pod",
APIVersion: registered.GroupOrDie(api.GroupName).GroupVersion.String(), APIVersion: registered.GroupOrDie(api.GroupName).GroupVersion.String(),
@ -51,10 +51,6 @@ func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *api.Pod {
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "dns-test-" + string(util.NewUUID()), Name: "dns-test-" + string(util.NewUUID()),
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{
pod.PodHostnameAnnotation: dnsTestPodHostName,
pod.PodSubdomainAnnotation: dnsTestServiceName,
},
}, },
Spec: api.PodSpec{ Spec: api.PodSpec{
Volumes: []api.Volume{ 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) { 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") { if framework.ProviderIs("gce", "gke") {
namesToResolve = append(namesToResolve, "metadata") namesToResolve = append(namesToResolve, "metadata")
} }
hostFQDN := fmt.Sprintf("%s.%s.%s.svc.cluster.local", dnsTestPodHostName, dnsTestServiceName, f.Namespace.Name)
wheezyProbeCmd, wheezyFileNames := createProbeCommand(namesToResolve, nil, "wheezy", f.Namespace.Name) hostEntries := []string{hostFQDN, dnsTestPodHostName}
jessieProbeCmd, jessieFileNames := createProbeCommand(namesToResolve, nil, "jessie", f.Namespace.Name) 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 wheezy:" + wheezyProbeCmd + "\n")
By("Running these commands on jessie:" + jessieProbeCmd + "\n") By("Running these commands on jessie:" + jessieProbeCmd + "\n")
// Run a pod which probes DNS and exposes the results by HTTP. // Run a pod which probes DNS and exposes the results by HTTP.
By("creating a pod to probe DNS") 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...)) 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. // Run a pod which probes DNS and exposes the results by HTTP.
By("creating a pod to probe DNS") 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 pod.ObjectMeta.Labels = testServiceSelector
validateDNSResults(f, pod, append(wheezyFileNames, jessieFileNames...)) 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) 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) hostNames := []string{hostFQDN, podHostname}
jessieProbeCmd, jessieFileNames := createProbeCommand([]string{hostFQDN}, []string{hostFQDN, podHostname}, "jessie", f.Namespace.Name) 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 wheezy:" + wheezyProbeCmd + "\n")
By("Running these commands on jessie:" + jessieProbeCmd + "\n") By("Running these commands on jessie:" + jessieProbeCmd + "\n")
// Run a pod which probes DNS and exposes the results by HTTP. // Run a pod which probes DNS and exposes the results by HTTP.
By("creating a pod to probe DNS") 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.Labels = testServiceSelector
pod1.ObjectMeta.Annotations = map[string]string{ pod1.ObjectMeta.Annotations = map[string]string{
pod.PodHostnameAnnotation: podHostname, pod.PodHostnameAnnotation: podHostname,