Commit 819535b9 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #36245 from fraenkel/env_configmap

Automatic merge from submit-queue (batch tested with PRs 38433, 36245) Allow pods to define multiple environment variables from a whole ConfigMap Allow environment variables to be populated from ConfigMaps - ConfigMaps represent an entire set of EnvVars - EnvVars can override ConfigMaps fixes #26299
parents b202ebb7 94866b3b
......@@ -31656,6 +31656,9 @@
}
}
},
"v1.ConfigMapEnvSource": {
"description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables."
},
"v1.ConfigMapKeySelector": {
"description": "Selects a key from a ConfigMap.",
"required": [
......@@ -31714,6 +31717,13 @@
"$ref": "#/definitions/v1.EnvVar"
}
},
"envFrom": {
"description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
"type": "array",
"items": {
"$ref": "#/definitions/v1.EnvFromSource"
}
},
"image": {
"description": "Docker image name. More info: http://kubernetes.io/docs/user-guide/images",
"type": "string"
......@@ -32115,6 +32125,19 @@
}
}
},
"v1.EnvFromSource": {
"description": "EnvFromSource represents the source of a set of ConfigMaps",
"properties": {
"configMapRef": {
"description": "The ConfigMap to select from",
"$ref": "#/definitions/v1.ConfigMapEnvSource"
},
"prefix": {
"description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.",
"type": "string"
}
}
},
"v1.EnvVar": {
"description": "EnvVar represents an environment variable present in a Container.",
"required": [
......@@ -2148,6 +2148,13 @@
},
"description": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated."
},
"envFrom": {
"type": "array",
"items": {
"$ref": "v1.EnvFromSource"
},
"description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated."
},
"env": {
"type": "array",
"items": {
......@@ -2235,6 +2242,30 @@
}
}
},
"v1.EnvFromSource": {
"id": "v1.EnvFromSource",
"description": "EnvFromSource represents the source of a set of ConfigMaps",
"properties": {
"prefix": {
"type": "string",
"description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER."
},
"configMapRef": {
"$ref": "v1.ConfigMapEnvSource",
"description": "The ConfigMap to select from"
}
}
},
"v1.ConfigMapEnvSource": {
"id": "v1.ConfigMapEnvSource",
"description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.",
"properties": {
"name": {
"type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
}
}
},
"v1.EnvVar": {
"id": "v1.EnvVar",
"description": "EnvVar represents an environment variable present in a Container.",
......
......@@ -2153,6 +2153,13 @@
},
"description": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated."
},
"envFrom": {
"type": "array",
"items": {
"$ref": "v1.EnvFromSource"
},
"description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated."
},
"env": {
"type": "array",
"items": {
......@@ -2240,6 +2247,30 @@
}
}
},
"v1.EnvFromSource": {
"id": "v1.EnvFromSource",
"description": "EnvFromSource represents the source of a set of ConfigMaps",
"properties": {
"prefix": {
"type": "string",
"description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER."
},
"configMapRef": {
"$ref": "v1.ConfigMapEnvSource",
"description": "The ConfigMap to select from"
}
}
},
"v1.ConfigMapEnvSource": {
"id": "v1.ConfigMapEnvSource",
"description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.",
"properties": {
"name": {
"type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
}
}
},
"v1.EnvVar": {
"id": "v1.EnvVar",
"description": "EnvVar represents an environment variable present in a Container.",
......
......@@ -7950,6 +7950,13 @@
},
"description": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated."
},
"envFrom": {
"type": "array",
"items": {
"$ref": "v1.EnvFromSource"
},
"description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated."
},
"env": {
"type": "array",
"items": {
......@@ -8037,6 +8044,30 @@
}
}
},
"v1.EnvFromSource": {
"id": "v1.EnvFromSource",
"description": "EnvFromSource represents the source of a set of ConfigMaps",
"properties": {
"prefix": {
"type": "string",
"description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER."
},
"configMapRef": {
"$ref": "v1.ConfigMapEnvSource",
"description": "The ConfigMap to select from"
}
}
},
"v1.ConfigMapEnvSource": {
"id": "v1.ConfigMapEnvSource",
"description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.",
"properties": {
"name": {
"type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
}
}
},
"v1.EnvVar": {
"id": "v1.EnvVar",
"description": "EnvVar represents an environment variable present in a Container.",
......
......@@ -18617,6 +18617,13 @@
},
"description": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated."
},
"envFrom": {
"type": "array",
"items": {
"$ref": "v1.EnvFromSource"
},
"description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated."
},
"env": {
"type": "array",
"items": {
......@@ -18704,6 +18711,30 @@
}
}
},
"v1.EnvFromSource": {
"id": "v1.EnvFromSource",
"description": "EnvFromSource represents the source of a set of ConfigMaps",
"properties": {
"prefix": {
"type": "string",
"description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER."
},
"configMapRef": {
"$ref": "v1.ConfigMapEnvSource",
"description": "The ConfigMap to select from"
}
}
},
"v1.ConfigMapEnvSource": {
"id": "v1.ConfigMapEnvSource",
"description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.",
"properties": {
"name": {
"type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
}
}
},
"v1.EnvVar": {
"id": "v1.EnvVar",
"description": "EnvVar represents an environment variable present in a Container.",
......
......@@ -1754,6 +1754,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">envFrom</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.</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"><a href="#_v1_envfromsource">v1.EnvFromSource</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">env</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">List of environment variables to set in the container. Cannot be updated.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
......@@ -2550,6 +2557,47 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div>
<div class="sect2">
<h3 id="_v1_envfromsource">v1.EnvFromSource</h3>
<div class="paragraph">
<p>EnvFromSource represents the source of a set of ConfigMaps</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">prefix</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.</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">configMapRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The ConfigMap to select from</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"><a href="#_v1_configmapenvsource">v1.ConfigMapEnvSource</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_cindervolumesource">v1.CinderVolumeSource</h3>
<div class="paragraph">
<p>Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.</p>
......@@ -3924,6 +3972,43 @@ The StatefulSet guarantees that a given network identity will always map to the
</div>
<div class="sect2">
<h3 id="_v1_configmapenvsource">v1.ConfigMapEnvSource</h3>
<div class="paragraph">
<p>ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.</p>
</div>
<div class="paragraph">
<p>The contents of the target ConfigMap&#8217;s Data field will represent the key-value pairs as environment variables.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Name of the referent. More info: <a href="http://kubernetes.io/docs/user-guide/identifiers#names">http://kubernetes.io/docs/user-guide/identifiers#names</a></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>
</table>
</div>
<div class="sect2">
<h3 id="_v1_resourcefieldselector">v1.ResourceFieldSelector</h3>
<div class="paragraph">
<p>ResourceFieldSelector represents container resources (cpu, memory) and their output format</p>
......@@ -4875,7 +4960,7 @@ Examples:<br>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2016-12-19 12:58:07 UTC
Last updated 2017-01-03 16:09:30 UTC
</div>
</div>
</body>
......
......@@ -1658,6 +1658,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">envFrom</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.</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"><a href="#_v1_envfromsource">v1.EnvFromSource</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">env</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">List of environment variables to set in the container. Cannot be updated.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
......@@ -2461,6 +2468,47 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div>
<div class="sect2">
<h3 id="_v1_envfromsource">v1.EnvFromSource</h3>
<div class="paragraph">
<p>EnvFromSource represents the source of a set of ConfigMaps</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">prefix</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.</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">configMapRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The ConfigMap to select from</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"><a href="#_v1_configmapenvsource">v1.ConfigMapEnvSource</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_cindervolumesource">v1.CinderVolumeSource</h3>
<div class="paragraph">
<p>Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.</p>
......@@ -3911,6 +3959,43 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div>
<div class="sect2">
<h3 id="_v1_configmapenvsource">v1.ConfigMapEnvSource</h3>
<div class="paragraph">
<p>ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.</p>
</div>
<div class="paragraph">
<p>The contents of the target ConfigMap&#8217;s Data field will represent the key-value pairs as environment variables.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Name of the referent. More info: <a href="http://kubernetes.io/docs/user-guide/identifiers#names">http://kubernetes.io/docs/user-guide/identifiers#names</a></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>
</table>
</div>
<div class="sect2">
<h3 id="_v1_resourcefieldselector">v1.ResourceFieldSelector</h3>
<div class="paragraph">
<p>ResourceFieldSelector represents container resources (cpu, memory) and their output format</p>
......@@ -4807,7 +4892,7 @@ Examples:<br>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2016-12-16 14:44:32 UTC
Last updated 2017-01-03 16:09:51 UTC
</div>
</div>
</body>
......
......@@ -2268,6 +2268,47 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div>
<div class="sect2">
<h3 id="_v1_envfromsource">v1.EnvFromSource</h3>
<div class="paragraph">
<p>EnvFromSource represents the source of a set of ConfigMaps</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">prefix</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.</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">configMapRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The ConfigMap to select from</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"><a href="#_v1_configmapenvsource">v1.ConfigMapEnvSource</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_podaffinity">v1.PodAffinity</h3>
<div class="paragraph">
<p>Pod affinity is a group of inter pod affinity scheduling rules.</p>
......@@ -5377,6 +5418,13 @@ Both these may change in the future. Incoming requests are matched against the h
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">envFrom</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.</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"><a href="#_v1_envfromsource">v1.EnvFromSource</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">env</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">List of environment variables to set in the container. Cannot be updated.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
......@@ -6583,6 +6631,43 @@ Both these may change in the future. Incoming requests are matched against the h
</div>
<div class="sect2">
<h3 id="_v1_configmapenvsource">v1.ConfigMapEnvSource</h3>
<div class="paragraph">
<p>ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.</p>
</div>
<div class="paragraph">
<p>The contents of the target ConfigMap&#8217;s Data field will represent the key-value pairs as environment variables.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Name of the referent. More info: <a href="http://kubernetes.io/docs/user-guide/identifiers#names">http://kubernetes.io/docs/user-guide/identifiers#names</a></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>
</table>
</div>
<div class="sect2">
<h3 id="_v1_nodeaffinity">v1.NodeAffinity</h3>
<div class="paragraph">
<p>Node affinity is a group of node affinity scheduling rules.</p>
......@@ -6933,7 +7018,7 @@ Both these may change in the future. Incoming requests are matched against the h
</div>
<div id="footer">
<div id="footer-text">
Last updated 2017-01-02 13:56:15 UTC
Last updated 2017-01-03 16:10:07 UTC
</div>
</div>
</body>
......
......@@ -9639,6 +9639,9 @@
}
}
},
"v1.ConfigMapEnvSource": {
"description": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables."
},
"v1.ConfigMapKeySelector": {
"description": "Selects a key from a ConfigMap.",
"required": [
......@@ -9697,6 +9700,13 @@
"$ref": "#/definitions/v1.EnvVar"
}
},
"envFrom": {
"description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
"type": "array",
"items": {
"$ref": "#/definitions/v1.EnvFromSource"
}
},
"image": {
"description": "Docker image name. More info: http://kubernetes.io/docs/user-guide/images",
"type": "string"
......@@ -9813,6 +9823,19 @@
}
}
},
"v1.EnvFromSource": {
"description": "EnvFromSource represents the source of a set of ConfigMaps",
"properties": {
"configMapRef": {
"description": "The ConfigMap to select from",
"$ref": "#/definitions/v1.ConfigMapEnvSource"
},
"prefix": {
"description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.",
"type": "string"
}
}
},
"v1.EnvVar": {
"description": "EnvVar represents an environment variable present in a Container.",
"required": [
......
......@@ -376,6 +376,17 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
ev.ValueFrom.FieldRef.FieldPath = c.RandString()
}
},
func(ev *api.EnvFromSource, c fuzz.Continue) {
if c.RandBool() {
ev.Prefix = "p_"
}
if c.RandBool() {
c.Fuzz(&ev.ConfigMapRef)
}
},
func(cm *api.ConfigMapEnvSource, c fuzz.Continue) {
c.FuzzNoCustom(cm) // fuzz self without calling this function again
},
func(sc *api.SecurityContext, c fuzz.Continue) {
c.FuzzNoCustom(sc) // fuzz self without calling this function again
if c.RandBool() {
......
......@@ -1133,6 +1133,26 @@ type SecretKeySelector struct {
Key string
}
// EnvFromSource represents the source of a set of ConfigMaps
type EnvFromSource struct {
// An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.
// +optional
Prefix string
// The ConfigMap to select from.
//+optional
ConfigMapRef *ConfigMapEnvSource
}
// ConfigMapEnvSource selects a ConfigMap to populate the environment
// variables with.
//
// The contents of the target ConfigMap's Data field will represent the
// key-value pairs as environment variables.
type ConfigMapEnvSource struct {
// The ConfigMap to select from.
LocalObjectReference
}
// HTTPHeader describes a custom header to be used in HTTP probes
type HTTPHeader struct {
// The header field name
......@@ -1274,6 +1294,14 @@ type Container struct {
WorkingDir string
// +optional
Ports []ContainerPort
// List of sources to populate environment variables in the container.
// The keys defined within a source must be a C_IDENTIFIER. An invalid key
// will prevent the container from starting. When a key exists in multiple
// sources, the value associated with the last source will take precedence.
// Values defined by an Env with a duplicate key will take precedence.
// Cannot be updated.
// +optional
EnvFrom []EnvFromSource
// +optional
Env []EnvVar
// Compute resource requirements.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -271,6 +271,16 @@ message ConfigMap {
map<string, string> data = 2;
}
// ConfigMapEnvSource selects a ConfigMap to populate the environment
// variables with.
//
// The contents of the target ConfigMap's Data field will represent the
// key-value pairs as environment variables.
message ConfigMapEnvSource {
// The ConfigMap to select from.
optional LocalObjectReference localObjectReference = 1;
}
// Selects a key from a ConfigMap.
message ConfigMapKeySelector {
// The ConfigMap to select from.
......@@ -369,6 +379,15 @@ message Container {
// +optional
repeated ContainerPort ports = 6;
// List of sources to populate environment variables in the container.
// The keys defined within a source must be a C_IDENTIFIER. An invalid key
// will prevent the container from starting. When a key exists in multiple
// sources, the value associated with the last source will take precedence.
// Values defined by an Env with a duplicate key will take precedence.
// Cannot be updated.
// +optional
repeated EnvFromSource envFrom = 19;
// List of environment variables to set in the container.
// Cannot be updated.
// +optional
......@@ -771,6 +790,17 @@ message EndpointsList {
repeated Endpoints items = 2;
}
// EnvFromSource represents the source of a set of ConfigMaps
message EnvFromSource {
// An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.
// +optional
optional string prefix = 1;
// The ConfigMap to select from
// +optional
optional ConfigMapEnvSource configMapRef = 2;
}
// EnvVar represents an environment variable present in a Container.
message EnvVar {
// Name of the environment variable. Must be a C_IDENTIFIER.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1233,6 +1233,26 @@ type SecretKeySelector struct {
Key string `json:"key" protobuf:"bytes,2,opt,name=key"`
}
// EnvFromSource represents the source of a set of ConfigMaps
type EnvFromSource struct {
// An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.
// +optional
Prefix string `json:"prefix,omitempty" protobuf:"bytes,1,opt,name=prefix"`
// The ConfigMap to select from
// +optional
ConfigMapRef *ConfigMapEnvSource `json:"configMapRef,omitempty" protobuf:"bytes,2,opt,name=configMapRef"`
}
// ConfigMapEnvSource selects a ConfigMap to populate the environment
// variables with.
//
// The contents of the target ConfigMap's Data field will represent the
// key-value pairs as environment variables.
type ConfigMapEnvSource struct {
// The ConfigMap to select from.
LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
}
// HTTPHeader describes a custom header to be used in HTTP probes
type HTTPHeader struct {
// The header field name
......@@ -1409,6 +1429,14 @@ type Container struct {
// Cannot be updated.
// +optional
Ports []ContainerPort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"containerPort" protobuf:"bytes,6,rep,name=ports"`
// List of sources to populate environment variables in the container.
// The keys defined within a source must be a C_IDENTIFIER. An invalid key
// will prevent the container from starting. When a key exists in multiple
// sources, the value associated with the last source will take precedence.
// Values defined by an Env with a duplicate key will take precedence.
// Cannot be updated.
// +optional
EnvFrom []EnvFromSource `json:"envFrom,omitempty" protobuf:"bytes,19,rep,name=envFrom"`
// List of environment variables to set in the container.
// Cannot be updated.
// +optional
......
......@@ -180,6 +180,14 @@ func (ConfigMap) SwaggerDoc() map[string]string {
return map_ConfigMap
}
var map_ConfigMapEnvSource = map[string]string{
"": "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.",
}
func (ConfigMapEnvSource) SwaggerDoc() map[string]string {
return map_ConfigMapEnvSource
}
var map_ConfigMapKeySelector = map[string]string{
"": "Selects a key from a ConfigMap.",
"key": "The key to select.",
......@@ -217,6 +225,7 @@ var map_Container = map[string]string{
"args": "Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers#containers-and-commands",
"workingDir": "Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated.",
"ports": "List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Cannot be updated.",
"envFrom": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
"env": "List of environment variables to set in the container. Cannot be updated.",
"resources": "Compute Resources required by this container. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#resources",
"volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.",
......@@ -424,6 +433,16 @@ func (EndpointsList) SwaggerDoc() map[string]string {
return map_EndpointsList
}
var map_EnvFromSource = map[string]string{
"": "EnvFromSource represents the source of a set of ConfigMaps",
"prefix": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.",
"configMapRef": "The ConfigMap to select from",
}
func (EnvFromSource) SwaggerDoc() map[string]string {
return map_EnvFromSource
}
var map_EnvVar = map[string]string{
"": "EnvVar represents an environment variable present in a Container.",
"name": "Name of the environment variable. Must be a C_IDENTIFIER.",
......
......@@ -65,6 +65,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_ComponentStatusList_To_v1_ComponentStatusList,
Convert_v1_ConfigMap_To_api_ConfigMap,
Convert_api_ConfigMap_To_v1_ConfigMap,
Convert_v1_ConfigMapEnvSource_To_api_ConfigMapEnvSource,
Convert_api_ConfigMapEnvSource_To_v1_ConfigMapEnvSource,
Convert_v1_ConfigMapKeySelector_To_api_ConfigMapKeySelector,
Convert_api_ConfigMapKeySelector_To_v1_ConfigMapKeySelector,
Convert_v1_ConfigMapList_To_api_ConfigMapList,
......@@ -107,6 +109,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_Endpoints_To_v1_Endpoints,
Convert_v1_EndpointsList_To_api_EndpointsList,
Convert_api_EndpointsList_To_v1_EndpointsList,
Convert_v1_EnvFromSource_To_api_EnvFromSource,
Convert_api_EnvFromSource_To_v1_EnvFromSource,
Convert_v1_EnvVar_To_api_EnvVar,
Convert_api_EnvVar_To_v1_EnvVar,
Convert_v1_EnvVarSource_To_api_EnvVarSource,
......@@ -674,6 +678,28 @@ func Convert_api_ConfigMap_To_v1_ConfigMap(in *api.ConfigMap, out *ConfigMap, s
return autoConvert_api_ConfigMap_To_v1_ConfigMap(in, out, s)
}
func autoConvert_v1_ConfigMapEnvSource_To_api_ConfigMapEnvSource(in *ConfigMapEnvSource, out *api.ConfigMapEnvSource, s conversion.Scope) error {
if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
return err
}
return nil
}
func Convert_v1_ConfigMapEnvSource_To_api_ConfigMapEnvSource(in *ConfigMapEnvSource, out *api.ConfigMapEnvSource, s conversion.Scope) error {
return autoConvert_v1_ConfigMapEnvSource_To_api_ConfigMapEnvSource(in, out, s)
}
func autoConvert_api_ConfigMapEnvSource_To_v1_ConfigMapEnvSource(in *api.ConfigMapEnvSource, out *ConfigMapEnvSource, s conversion.Scope) error {
if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
return err
}
return nil
}
func Convert_api_ConfigMapEnvSource_To_v1_ConfigMapEnvSource(in *api.ConfigMapEnvSource, out *ConfigMapEnvSource, s conversion.Scope) error {
return autoConvert_api_ConfigMapEnvSource_To_v1_ConfigMapEnvSource(in, out, s)
}
func autoConvert_v1_ConfigMapKeySelector_To_api_ConfigMapKeySelector(in *ConfigMapKeySelector, out *api.ConfigMapKeySelector, s conversion.Scope) error {
if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
return err
......@@ -751,6 +777,7 @@ func autoConvert_v1_Container_To_api_Container(in *Container, out *api.Container
out.Args = *(*[]string)(unsafe.Pointer(&in.Args))
out.WorkingDir = in.WorkingDir
out.Ports = *(*[]api.ContainerPort)(unsafe.Pointer(&in.Ports))
out.EnvFrom = *(*[]api.EnvFromSource)(unsafe.Pointer(&in.EnvFrom))
out.Env = *(*[]api.EnvVar)(unsafe.Pointer(&in.Env))
if err := Convert_v1_ResourceRequirements_To_api_ResourceRequirements(&in.Resources, &out.Resources, s); err != nil {
return err
......@@ -779,6 +806,7 @@ func autoConvert_api_Container_To_v1_Container(in *api.Container, out *Container
out.Args = *(*[]string)(unsafe.Pointer(&in.Args))
out.WorkingDir = in.WorkingDir
out.Ports = *(*[]ContainerPort)(unsafe.Pointer(&in.Ports))
out.EnvFrom = *(*[]EnvFromSource)(unsafe.Pointer(&in.EnvFrom))
out.Env = *(*[]EnvVar)(unsafe.Pointer(&in.Env))
if err := Convert_api_ResourceRequirements_To_v1_ResourceRequirements(&in.Resources, &out.Resources, s); err != nil {
return err
......@@ -1190,6 +1218,26 @@ func Convert_api_EndpointsList_To_v1_EndpointsList(in *api.EndpointsList, out *E
return autoConvert_api_EndpointsList_To_v1_EndpointsList(in, out, s)
}
func autoConvert_v1_EnvFromSource_To_api_EnvFromSource(in *EnvFromSource, out *api.EnvFromSource, s conversion.Scope) error {
out.Prefix = in.Prefix
out.ConfigMapRef = (*api.ConfigMapEnvSource)(unsafe.Pointer(in.ConfigMapRef))
return nil
}
func Convert_v1_EnvFromSource_To_api_EnvFromSource(in *EnvFromSource, out *api.EnvFromSource, s conversion.Scope) error {
return autoConvert_v1_EnvFromSource_To_api_EnvFromSource(in, out, s)
}
func autoConvert_api_EnvFromSource_To_v1_EnvFromSource(in *api.EnvFromSource, out *EnvFromSource, s conversion.Scope) error {
out.Prefix = in.Prefix
out.ConfigMapRef = (*ConfigMapEnvSource)(unsafe.Pointer(in.ConfigMapRef))
return nil
}
func Convert_api_EnvFromSource_To_v1_EnvFromSource(in *api.EnvFromSource, out *EnvFromSource, s conversion.Scope) error {
return autoConvert_api_EnvFromSource_To_v1_EnvFromSource(in, out, s)
}
func autoConvert_v1_EnvVar_To_api_EnvVar(in *EnvVar, out *api.EnvVar, s conversion.Scope) error {
out.Name = in.Name
out.Value = in.Value
......
......@@ -50,6 +50,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ComponentStatus, InType: reflect.TypeOf(&ComponentStatus{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ComponentStatusList, InType: reflect.TypeOf(&ComponentStatusList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ConfigMap, InType: reflect.TypeOf(&ConfigMap{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ConfigMapEnvSource, InType: reflect.TypeOf(&ConfigMapEnvSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ConfigMapKeySelector, InType: reflect.TypeOf(&ConfigMapKeySelector{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ConfigMapList, InType: reflect.TypeOf(&ConfigMapList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ConfigMapVolumeSource, InType: reflect.TypeOf(&ConfigMapVolumeSource{})},
......@@ -71,6 +72,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_EndpointSubset, InType: reflect.TypeOf(&EndpointSubset{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Endpoints, InType: reflect.TypeOf(&Endpoints{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_EndpointsList, InType: reflect.TypeOf(&EndpointsList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_EnvFromSource, InType: reflect.TypeOf(&EnvFromSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_EnvVar, InType: reflect.TypeOf(&EnvVar{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_EnvVarSource, InType: reflect.TypeOf(&EnvVarSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Event, InType: reflect.TypeOf(&Event{})},
......@@ -464,6 +466,15 @@ func DeepCopy_v1_ConfigMap(in interface{}, out interface{}, c *conversion.Cloner
}
}
func DeepCopy_v1_ConfigMapEnvSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ConfigMapEnvSource)
out := out.(*ConfigMapEnvSource)
out.LocalObjectReference = in.LocalObjectReference
return nil
}
}
func DeepCopy_v1_ConfigMapKeySelector(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ConfigMapKeySelector)
......@@ -552,6 +563,17 @@ func DeepCopy_v1_Container(in interface{}, out interface{}, c *conversion.Cloner
} else {
out.Ports = nil
}
if in.EnvFrom != nil {
in, out := &in.EnvFrom, &out.EnvFrom
*out = make([]EnvFromSource, len(*in))
for i := range *in {
if err := DeepCopy_v1_EnvFromSource(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.EnvFrom = nil
}
if in.Env != nil {
in, out := &in.Env, &out.Env
*out = make([]EnvVar, len(*in))
......@@ -962,6 +984,22 @@ func DeepCopy_v1_EndpointsList(in interface{}, out interface{}, c *conversion.Cl
}
}
func DeepCopy_v1_EnvFromSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*EnvFromSource)
out := out.(*EnvFromSource)
out.Prefix = in.Prefix
if in.ConfigMapRef != nil {
in, out := &in.ConfigMapRef, &out.ConfigMapRef
*out = new(ConfigMapEnvSource)
**out = **in
} else {
out.ConfigMapRef = nil
}
return nil
}
}
func DeepCopy_v1_EnvVar(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*EnvVar)
......
......@@ -1427,6 +1427,30 @@ func validateContainerResourceFieldSelector(fs *api.ResourceFieldSelector, expre
return allErrs
}
func validateEnvFrom(vars []api.EnvFromSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for i, ev := range vars {
idxPath := fldPath.Index(i)
if len(ev.Prefix) > 0 {
for _, msg := range validation.IsCIdentifier(ev.Prefix) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("prefix"), ev.Prefix, msg))
}
}
if ev.ConfigMapRef != nil {
allErrs = append(allErrs, validateConfigMapEnvSource(ev.ConfigMapRef, idxPath.Child("configMapRef"))...)
}
}
return allErrs
}
func validateConfigMapEnvSource(configMapSource *api.ConfigMapEnvSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(configMapSource.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
}
return allErrs
}
var validContainerResourceDivisorForCPU = sets.NewString("1m", "1")
var validContainerResourceDivisorForMemory = sets.NewString("1", "1k", "1M", "1G", "1T", "1P", "1E", "1Ki", "1Mi", "1Gi", "1Ti", "1Pi", "1Ei")
......
......@@ -2719,6 +2719,65 @@ func TestValidateEnv(t *testing.T) {
}
}
func TestValidateEnvFrom(t *testing.T) {
successCase := []api.EnvFromSource{
{
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
},
},
{
Prefix: "pre_",
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
},
},
}
if errs := validateEnvFrom(successCase, field.NewPath("field")); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
errorCases := []struct {
name string
envs []api.EnvFromSource
expectedError string
}{
{
name: "zero-length name",
envs: []api.EnvFromSource{
{
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{Name: ""}},
},
},
expectedError: "field[0].configMapRef.name: Required value",
},
{
name: "invalid prefix",
envs: []api.EnvFromSource{
{
Prefix: "a.b",
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{Name: "abc"}},
},
},
expectedError: `field[0].prefix: Invalid value: "a.b": ` + idErrMsg,
},
}
for _, tc := range errorCases {
if errs := validateEnvFrom(tc.envs, field.NewPath("field")); len(errs) == 0 {
t.Errorf("expected failure for %s", tc.name)
} else {
for i := range errs {
str := errs[i].Error()
if str != "" && !strings.Contains(str, tc.expectedError) {
t.Errorf("%s: expected error detail either empty or %q, got %q", tc.name, tc.expectedError, str)
}
}
}
}
}
func TestValidateVolumeMounts(t *testing.T) {
volumes := sets.NewString("abc", "123", "abc-123")
......
......@@ -52,6 +52,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ComponentStatus, InType: reflect.TypeOf(&ComponentStatus{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ComponentStatusList, InType: reflect.TypeOf(&ComponentStatusList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConfigMap, InType: reflect.TypeOf(&ConfigMap{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConfigMapEnvSource, InType: reflect.TypeOf(&ConfigMapEnvSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConfigMapKeySelector, InType: reflect.TypeOf(&ConfigMapKeySelector{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConfigMapList, InType: reflect.TypeOf(&ConfigMapList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConfigMapVolumeSource, InType: reflect.TypeOf(&ConfigMapVolumeSource{})},
......@@ -74,6 +75,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_EndpointSubset, InType: reflect.TypeOf(&EndpointSubset{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Endpoints, InType: reflect.TypeOf(&Endpoints{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_EndpointsList, InType: reflect.TypeOf(&EndpointsList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_EnvFromSource, InType: reflect.TypeOf(&EnvFromSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_EnvVar, InType: reflect.TypeOf(&EnvVar{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_EnvVarSource, InType: reflect.TypeOf(&EnvVarSource{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Event, InType: reflect.TypeOf(&Event{})},
......@@ -467,6 +469,15 @@ func DeepCopy_api_ConfigMap(in interface{}, out interface{}, c *conversion.Clone
}
}
func DeepCopy_api_ConfigMapEnvSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ConfigMapEnvSource)
out := out.(*ConfigMapEnvSource)
out.LocalObjectReference = in.LocalObjectReference
return nil
}
}
func DeepCopy_api_ConfigMapKeySelector(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ConfigMapKeySelector)
......@@ -555,6 +566,17 @@ func DeepCopy_api_Container(in interface{}, out interface{}, c *conversion.Clone
} else {
out.Ports = nil
}
if in.EnvFrom != nil {
in, out := &in.EnvFrom, &out.EnvFrom
*out = make([]EnvFromSource, len(*in))
for i := range *in {
if err := DeepCopy_api_EnvFromSource(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.EnvFrom = nil
}
if in.Env != nil {
in, out := &in.Env, &out.Env
*out = make([]EnvVar, len(*in))
......@@ -988,6 +1010,22 @@ func DeepCopy_api_EndpointsList(in interface{}, out interface{}, c *conversion.C
}
}
func DeepCopy_api_EnvFromSource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*EnvFromSource)
out := out.(*EnvFromSource)
out.Prefix = in.Prefix
if in.ConfigMapRef != nil {
in, out := &in.ConfigMapRef, &out.ConfigMapRef
*out = new(ConfigMapEnvSource)
**out = **in
} else {
out.ConfigMapRef = nil
}
return nil
}
}
func DeepCopy_api_EnvVar(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*EnvVar)
......
......@@ -797,6 +797,15 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Dependencies: []string{
"v1.ObjectMeta"},
},
"v1.ConfigMapEnvSource": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "ConfigMapEnvSource selects a ConfigMap to populate the environment variables with.\n\nThe contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.",
Properties: map[string]spec.Schema{},
},
},
Dependencies: []string{},
},
"v1.ConfigMapKeySelector": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
......@@ -944,6 +953,19 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
},
},
},
"envFrom": {
SchemaProps: spec.SchemaProps{
Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. An invalid key will prevent the container from starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: spec.MustCreateRef("#/definitions/v1.EnvFromSource"),
},
},
},
},
},
"env": {
SchemaProps: spec.SchemaProps{
Description: "List of environment variables to set in the container. Cannot be updated.",
......@@ -1040,7 +1062,7 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
},
},
Dependencies: []string{
"v1.ContainerPort", "v1.EnvVar", "v1.Lifecycle", "v1.Probe", "v1.ResourceRequirements", "v1.SecurityContext", "v1.VolumeMount"},
"v1.ContainerPort", "v1.EnvFromSource", "v1.EnvVar", "v1.Lifecycle", "v1.Probe", "v1.ResourceRequirements", "v1.SecurityContext", "v1.VolumeMount"},
},
"v1.ContainerImage": {
Schema: spec.Schema{
......@@ -1682,6 +1704,30 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Dependencies: []string{
"v1.Endpoints", "v1.ListMeta"},
},
"v1.EnvFromSource": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "EnvFromSource represents the source of a set of ConfigMaps",
Properties: map[string]spec.Schema{
"prefix": {
SchemaProps: spec.SchemaProps{
Description: "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.",
Type: []string{"string"},
Format: "",
},
},
"configMapRef": {
SchemaProps: spec.SchemaProps{
Description: "The ConfigMap to select from",
Ref: spec.MustCreateRef("#/definitions/v1.ConfigMapEnvSource"),
},
},
},
},
},
Dependencies: []string{
"v1.ConfigMapEnvSource"},
},
"v1.EnvVar": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
......
......@@ -890,6 +890,7 @@ func describeContainers(label string, containers []api.Container, containerStatu
}
describeContainerProbe(container, w)
describeContainerVolumes(container, w)
describeContainerEnvFrom(container, resolverFn, w)
describeContainerEnvVars(container, resolverFn, w)
}
}
......@@ -1012,6 +1013,7 @@ func describeContainerEnvVars(container api.Container, resolverFn EnvVarResolver
none = "\t<none>"
}
w.Write(LEVEL_2, "Environment Variables:%s\n", none)
for _, e := range container.Env {
if e.ValueFrom == nil {
w.Write(LEVEL_3, "%s:\t%s\n", e.Name, e.Value)
......@@ -1043,6 +1045,22 @@ func describeContainerEnvVars(container api.Container, resolverFn EnvVarResolver
}
}
func describeContainerEnvFrom(container api.Container, resolverFn EnvVarResolverFunc, w *PrefixWriter) {
none := ""
if len(container.EnvFrom) == 0 {
none = "\t<none>"
}
w.Write(LEVEL_2, "Environment Variables from:%s\n", none)
for _, e := range container.EnvFrom {
if len(e.Prefix) == 0 {
w.Write(LEVEL_3, "%s\tConfigMap\n", e.ConfigMapRef.Name)
} else {
w.Write(LEVEL_3, "%s\tConfigMap with prefix '%s'\n", e.ConfigMapRef.Name, e.Prefix)
}
}
}
// DescribeProbe is exported for consumers in other API groups that have probes
func DescribeProbe(probe *api.Probe) string {
attrs := fmt.Sprintf("delay=%ds timeout=%ds period=%ds #success=%d #failure=%d", probe.InitialDelaySeconds, probe.TimeoutSeconds, probe.PeriodSeconds, probe.SuccessThreshold, probe.FailureThreshold)
......
......@@ -288,13 +288,22 @@ func TestDescribeContainers(t *testing.T) {
},
// Env
{
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}},
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{ConfigMapRef: &api.ConfigMapEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
status: api.ContainerStatus{
Name: "test",
Ready: true,
RestartCount: 7,
},
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz"},
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap"},
},
{
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{Prefix: "p_", ConfigMapRef: &api.ConfigMapEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
status: api.ContainerStatus{
Name: "test",
Ready: true,
RestartCount: 7,
},
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap with prefix 'p_'"},
},
// Command
{
......
......@@ -414,6 +414,47 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
return result, err
}
var (
configMaps = make(map[string]*v1.ConfigMap)
tmpEnv = make(map[string]string)
)
// Env will override EnvFrom variables.
// Process EnvFrom first then allow Env to replace existing values.
for _, envFrom := range container.EnvFrom {
if envFrom.ConfigMapRef != nil {
name := envFrom.ConfigMapRef.Name
configMap, ok := configMaps[name]
if !ok {
if kl.kubeClient == nil {
return result, fmt.Errorf("Couldn't get configMap %v/%v, no kubeClient defined", pod.Namespace, name)
}
configMap, err = kl.kubeClient.Core().ConfigMaps(pod.Namespace).Get(name, metav1.GetOptions{})
if err != nil {
return result, err
}
configMaps[name] = configMap
}
for k, v := range configMap.Data {
if errMsgs := utilvalidation.IsCIdentifier(k); len(errMsgs) != 0 {
return result, fmt.Errorf("Invalid environment variable name, %v, from configmap %v/%v: %s", k, pod.Namespace, name, errMsgs[0])
}
if len(envFrom.Prefix) > 0 {
k = envFrom.Prefix + k
}
// Accesses apiserver+Pods.
// So, the master may set service env vars, or kubelet may. In case both are doing
// it, we delete the key from the kubelet-generated ones so we don't have duplicate
// env vars.
// TODO: remove this next line once all platforms use apiserver+Pods.
delete(serviceEnv, k)
tmpEnv[k] = v
}
}
}
// Determine the final values of variables:
//
// 1. Determine the final value of each variable:
......@@ -424,8 +465,6 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
// 2. Create the container's environment in the order variables are declared
// 3. Add remaining service environment vars
var (
tmpEnv = make(map[string]string)
configMaps = make(map[string]*v1.ConfigMap)
secrets = make(map[string]*v1.Secret)
mappingFunc = expansion.MappingFuncFor(tmpEnv, serviceEnv)
)
......@@ -434,7 +473,7 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
// So, the master may set service env vars, or kubelet may. In case both are doing
// it, we delete the key from the kubelet-generated ones so we don't have duplicate
// env vars.
// TODO: remove this net line once all platforms use apiserver+Pods.
// TODO: remove this next line once all platforms use apiserver+Pods.
delete(serviceEnv, envVar.Name)
runtimeVal := envVar.Value
......@@ -499,7 +538,11 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
}
tmpEnv[envVar.Name] = runtimeVal
result = append(result, kubecontainer.EnvVar{Name: envVar.Name, Value: tmpEnv[envVar.Name]})
}
// Append the env vars
for k, v := range tmpEnv {
result = append(result, kubecontainer.EnvVar{Name: k, Value: v})
}
// Append remaining service env vars.
......
......@@ -268,7 +268,9 @@ func TestMakeEnvironmentVariables(t *testing.T) {
container *v1.Container // the container to use
masterServiceNs string // the namespace to read master service info from
nilLister bool // whether the lister should be nil
configMap *v1.ConfigMap // an optional ConfigMap to pull from
expectedEnvs []kubecontainer.EnvVar // a set of expected environment vars
expectedError bool // does the test fail
}{
{
name: "api server = Y, kubelet = Y",
......@@ -605,6 +607,132 @@ func TestMakeEnvironmentVariables(t *testing.T) {
},
},
},
{
name: "configmap",
ns: "test1",
container: &v1.Container{
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}},
},
{
Prefix: "p_",
ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}},
},
},
Env: []v1.EnvVar{
{
Name: "TEST_LITERAL",
Value: "test-test-test",
},
{
Name: "EXPANSION_TEST",
Value: "$(REPLACE_ME)",
},
{
Name: "DUPE_TEST",
Value: "ENV_VAR",
},
},
},
masterServiceNs: "nothing",
nilLister: false,
configMap: &v1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Namespace: "test1",
Name: "test-configmap",
},
Data: map[string]string{
"REPLACE_ME": "FROM_CONFIG_MAP",
"DUPE_TEST": "CONFIG_MAP",
},
},
expectedEnvs: []kubecontainer.EnvVar{
{
Name: "TEST_LITERAL",
Value: "test-test-test",
},
{
Name: "TEST_SERVICE_HOST",
Value: "1.2.3.3",
},
{
Name: "TEST_SERVICE_PORT",
Value: "8083",
},
{
Name: "TEST_PORT",
Value: "tcp://1.2.3.3:8083",
},
{
Name: "TEST_PORT_8083_TCP",
Value: "tcp://1.2.3.3:8083",
},
{
Name: "TEST_PORT_8083_TCP_PROTO",
Value: "tcp",
},
{
Name: "TEST_PORT_8083_TCP_PORT",
Value: "8083",
},
{
Name: "TEST_PORT_8083_TCP_ADDR",
Value: "1.2.3.3",
},
{
Name: "REPLACE_ME",
Value: "FROM_CONFIG_MAP",
},
{
Name: "EXPANSION_TEST",
Value: "FROM_CONFIG_MAP",
},
{
Name: "DUPE_TEST",
Value: "ENV_VAR",
},
{
Name: "p_REPLACE_ME",
Value: "FROM_CONFIG_MAP",
},
{
Name: "p_DUPE_TEST",
Value: "CONFIG_MAP",
},
},
},
{
name: "configmap_missing",
ns: "test1",
container: &v1.Container{
EnvFrom: []v1.EnvFromSource{
{ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}}},
},
},
masterServiceNs: "nothing",
expectedError: true,
},
{
name: "configmap_invalid_keys",
ns: "test1",
container: &v1.Container{
EnvFrom: []v1.EnvFromSource{
{ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"}}},
},
},
masterServiceNs: "nothing",
configMap: &v1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Namespace: "test1",
Name: "test-configmap",
},
Data: map[string]string{
"-1234": "abc",
},
},
expectedError: true,
},
}
for _, tc := range testCases {
......@@ -617,6 +745,14 @@ func TestMakeEnvironmentVariables(t *testing.T) {
kl.serviceLister = testServiceLister{services}
}
testKubelet.fakeKubeClient.AddReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) {
var err error
if tc.configMap == nil {
err = errors.New("no configmap defined")
}
return true, tc.configMap, err
})
testPod := &v1.Pod{
ObjectMeta: v1.ObjectMeta{
Namespace: tc.ns,
......@@ -630,12 +766,16 @@ func TestMakeEnvironmentVariables(t *testing.T) {
podIP := "1.2.3.4"
result, err := kl.makeEnvironmentVariables(testPod, tc.container, podIP)
if tc.expectedError {
assert.Error(t, err, tc.name)
} else {
assert.NoError(t, err, "[%s]", tc.name)
sort.Sort(envs(result))
sort.Sort(envs(tc.expectedEnvs))
assert.Equal(t, tc.expectedEnvs, result, "[%s] env entries", tc.name)
}
}
}
func waitingState(cName string) v1.ContainerStatus {
......
......@@ -196,6 +196,46 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
})
})
It("should be consumable via the environment [Conformance]", func() {
name := "configmap-test-" + string(uuid.NewUUID())
configMap := newEnvFromConfigMap(f, name)
By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
var err error
if configMap, err = f.ClientSet.Core().ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
framework.Failf("unable to create test configMap %s: %v", configMap.Name, err)
}
pod := &v1.Pod{
ObjectMeta: v1.ObjectMeta{
Name: "pod-configmaps-" + string(uuid.NewUUID()),
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "env-test",
Image: "gcr.io/google_containers/busybox:1.24",
Command: []string{"sh", "-c", "env"},
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}},
},
{
Prefix: "p_",
ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}},
},
},
},
},
RestartPolicy: v1.RestartPolicyNever,
},
}
f.TestContainerOutput("consume configMaps", pod, 0, []string{
"data_1=value-1", "data_2=value-2", "data_3=value-3",
"p_data_1=value-1", "p_data_2=value-2", "p_data_3=value-3",
})
})
It("should be consumable in multiple volumes in the same pod [Conformance]", func() {
var (
name = "configmap-test-volume-" + string(uuid.NewUUID())
......@@ -283,6 +323,20 @@ func newConfigMap(f *framework.Framework, name string) *v1.ConfigMap {
}
}
func newEnvFromConfigMap(f *framework.Framework, name string) *v1.ConfigMap {
return &v1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Namespace: f.Namespace.Name,
Name: name,
},
Data: map[string]string{
"data_1": "value-1",
"data_2": "value-2",
"data_3": "value-3",
},
}
}
func doConfigMapE2EWithoutMappings(f *framework.Framework, uid, fsGroup int64, defaultMode *int32) {
var (
name = "configmap-test-volume-" + string(uuid.NewUUID())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment