Merge pull request #39981 from fraenkel/optional_configmaps_secrets

Automatic merge from submit-queue

Optional configmaps and secrets

Allow configmaps and secrets for environment variables and volume sources to be optional

Implements approved proposal c9f881b7bb

Release note:
```release-note
Volumes and environment variables populated from ConfigMap and Secret objects can now tolerate the named source object or specific keys being missing, by adding `optional: true` to the volume or environment variable source specifications.
```
This commit is contained in:
Kubernetes Submit Queue 2017-01-23 23:06:35 -08:00 committed by GitHub
commit 43286a82c6
35 changed files with 3002 additions and 878 deletions

View File

@ -34912,6 +34912,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the ConfigMap must be defined",
"type": "boolean"
} }
} }
}, },
@ -34928,6 +34932,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the ConfigMap or it's key must be defined",
"type": "boolean"
} }
} }
}, },
@ -34967,7 +34975,7 @@
"format": "int32" "format": "int32"
}, },
"items": { "items": {
"description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/v1.KeyToPath" "$ref": "#/definitions/v1.KeyToPath"
@ -34976,6 +34984,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the ConfigMap or it's keys must be defined",
"type": "boolean"
} }
} }
}, },
@ -38217,6 +38229,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the Secret must be defined",
"type": "boolean"
} }
} }
}, },
@ -38233,6 +38249,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the Secret or it's key must be defined",
"type": "boolean"
} }
} }
}, },
@ -38272,12 +38292,16 @@
"format": "int32" "format": "int32"
}, },
"items": { "items": {
"description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/v1.KeyToPath" "$ref": "#/definitions/v1.KeyToPath"
} }
}, },
"optional": {
"description": "Specify whether the Secret or it's keys must be defined",
"type": "boolean"
},
"secretName": { "secretName": {
"description": "Name of the secret in the pod's namespace to use. More info: http://kubernetes.io/docs/user-guide/volumes#secrets", "description": "Name of the secret in the pod's namespace to use. More info: http://kubernetes.io/docs/user-guide/volumes#secrets",
"type": "string" "type": "string"

View File

@ -1574,12 +1574,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's keys must be defined"
} }
} }
}, },
@ -2005,12 +2009,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's keys must be defined"
} }
} }
}, },
@ -2275,6 +2283,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap must be defined"
} }
} }
}, },
@ -2285,6 +2297,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret must be defined"
} }
} }
}, },
@ -2345,6 +2361,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key to select." "description": "The key to select."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's key must be defined"
} }
} }
}, },
@ -2362,6 +2382,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key of the secret to select from. Must be a valid secret key." "description": "The key of the secret to select from. Must be a valid secret key."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's key must be defined"
} }
} }
}, },

View File

@ -1579,12 +1579,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's keys must be defined"
} }
} }
}, },
@ -2010,12 +2014,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's keys must be defined"
} }
} }
}, },
@ -2280,6 +2288,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap must be defined"
} }
} }
}, },
@ -2290,6 +2302,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret must be defined"
} }
} }
}, },
@ -2350,6 +2366,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key to select." "description": "The key to select."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's key must be defined"
} }
} }
}, },
@ -2367,6 +2387,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key of the secret to select from. Must be a valid secret key." "description": "The key of the secret to select from. Must be a valid secret key."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's key must be defined"
} }
} }
}, },

View File

@ -7951,12 +7951,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's keys must be defined"
} }
} }
}, },
@ -8382,12 +8386,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's keys must be defined"
} }
} }
}, },
@ -8652,6 +8660,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap must be defined"
} }
} }
}, },
@ -8662,6 +8674,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret must be defined"
} }
} }
}, },
@ -8722,6 +8738,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key to select." "description": "The key to select."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's key must be defined"
} }
} }
}, },
@ -8739,6 +8759,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key of the secret to select from. Must be a valid secret key." "description": "The key of the secret to select from. Must be a valid secret key."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's key must be defined"
} }
} }
}, },

View File

@ -18428,12 +18428,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's keys must be defined"
} }
} }
}, },
@ -18572,12 +18576,16 @@
"items": { "items": {
"$ref": "v1.KeyToPath" "$ref": "v1.KeyToPath"
}, },
"description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'." "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'."
}, },
"defaultMode": { "defaultMode": {
"type": "integer", "type": "integer",
"format": "int32", "format": "int32",
"description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set." "description": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's keys must be defined"
} }
} }
}, },
@ -18744,6 +18752,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap must be defined"
} }
} }
}, },
@ -18754,6 +18766,10 @@
"name": { "name": {
"type": "string", "type": "string",
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret must be defined"
} }
} }
}, },
@ -18814,6 +18830,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key to select." "description": "The key to select."
},
"optional": {
"type": "boolean",
"description": "Specify whether the ConfigMap or it's key must be defined"
} }
} }
}, },
@ -18831,6 +18851,10 @@
"key": { "key": {
"type": "string", "type": "string",
"description": "The key of the secret to select from. Must be a valid secret key." "description": "The key of the secret to select from. Must be a valid secret key."
},
"optional": {
"type": "boolean",
"description": "Specify whether the Secret or it's key must be defined"
} }
} }
}, },

View File

@ -1387,7 +1387,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -1399,6 +1399,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -1546,6 +1553,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -3194,7 +3208,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -3206,6 +3220,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4055,6 +4076,13 @@ The StatefulSet guarantees that a given network identity will always map to the
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4268,6 +4296,13 @@ The StatefulSet guarantees that a given network identity will always map to the
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4713,6 +4748,13 @@ The StatefulSet guarantees that a given network identity will always map to the
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -5018,7 +5060,7 @@ Examples:<br>
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2017-01-20 19:58:01 UTC Last updated 2017-01-24 01:22:19 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -1291,7 +1291,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -1303,6 +1303,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -1450,6 +1457,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -3181,7 +3195,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -3193,6 +3207,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4042,6 +4063,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4255,6 +4283,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4700,6 +4735,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4950,7 +4992,7 @@ Examples:<br>
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2017-01-20 19:58:30 UTC Last updated 2017-01-24 01:22:40 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -1600,7 +1600,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -1612,6 +1612,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -1697,6 +1704,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -2828,7 +2842,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -2840,6 +2854,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -3839,6 +3860,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -7171,6 +7199,13 @@ Both these may change in the future. Incoming requests are matched against the h
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -7390,6 +7425,13 @@ Both these may change in the future. Incoming requests are matched against the h
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -7567,7 +7609,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 2017-01-20 19:59:01 UTC Last updated 2017-01-24 01:22:55 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -1524,7 +1524,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -1536,6 +1536,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -1738,6 +1745,13 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -3296,7 +3310,7 @@ The resulting set of endpoints can be viewed as:<br>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the <em>..</em> path or start with <em>..</em>.</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>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_keytopath">v1.KeyToPath</a> array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
@ -3308,6 +3322,13 @@ The resulting set of endpoints can be viewed as:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s keys must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -4387,6 +4408,13 @@ The resulting set of endpoints can be viewed as:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the Secret or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -8535,6 +8563,13 @@ Examples:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -8775,6 +8810,13 @@ Examples:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</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">optional</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Specify whether the ConfigMap or it&#8217;s key must be defined</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">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -9194,7 +9236,7 @@ Examples:<br>
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2017-01-20 19:57:54 UTC Last updated 2017-01-24 01:22:13 UTC
</div> </div>
</div> </div>
</body> </body>

View File

@ -10746,6 +10746,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the ConfigMap must be defined",
"type": "boolean"
} }
} }
}, },
@ -10762,6 +10766,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the ConfigMap or it's key must be defined",
"type": "boolean"
} }
} }
}, },
@ -10801,7 +10809,7 @@
"format": "int32" "format": "int32"
}, },
"items": { "items": {
"description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", "description": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/v1.KeyToPath" "$ref": "#/definitions/v1.KeyToPath"
@ -10810,6 +10818,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the ConfigMap or it's keys must be defined",
"type": "boolean"
} }
} }
}, },
@ -12677,6 +12689,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the Secret must be defined",
"type": "boolean"
} }
} }
}, },
@ -12693,6 +12709,10 @@
"name": { "name": {
"description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
"type": "string" "type": "string"
},
"optional": {
"description": "Specify whether the Secret or it's key must be defined",
"type": "boolean"
} }
} }
}, },
@ -12732,12 +12752,16 @@
"format": "int32" "format": "int32"
}, },
"items": { "items": {
"description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", "description": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/v1.KeyToPath" "$ref": "#/definitions/v1.KeyToPath"
} }
}, },
"optional": {
"description": "Specify whether the Secret or it's keys must be defined",
"type": "boolean"
},
"secretName": { "secretName": {
"description": "Name of the secret in the pod's namespace to use. More info: http://kubernetes.io/docs/user-guide/volumes#secrets", "description": "Name of the secret in the pod's namespace to use. More info: http://kubernetes.io/docs/user-guide/volumes#secrets",
"type": "string" "type": "string"

View File

@ -123,11 +123,17 @@ pkg/util/oom/oom_linux.go: oomScoreAdjPath := path.Join("/proc", pidStr, "oom_sc
pkg/util/oom/oom_linux.go:// Writes 'value' to /proc/<pid>/oom_score_adj for all processes in cgroup cgroupName. pkg/util/oom/oom_linux.go:// Writes 'value' to /proc/<pid>/oom_score_adj for all processes in cgroup cgroupName.
pkg/util/oom/oom_linux.go:// Writes 'value' to /proc/<pid>/oom_score_adj. PID = 0 means self pkg/util/oom/oom_linux.go:// Writes 'value' to /proc/<pid>/oom_score_adj. PID = 0 means self
test/e2e/common/configmap.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volume/data-1"}, test/e2e/common/configmap.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volume/data-1"},
test/e2e/common/configmap.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volumes/create/data-1"},
test/e2e/common/configmap.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volumes/delete/data-1"},
test/e2e/common/configmap.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volumes/update/data-3"},
test/e2e/common/downwardapi_volume.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=" + filePath}, test/e2e/common/downwardapi_volume.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=" + filePath},
test/e2e/common/host_path.go: fmt.Sprintf("--file_content_in_loop=%v", filePath), test/e2e/common/host_path.go: fmt.Sprintf("--file_content_in_loop=%v", filePath),
test/e2e/common/host_path.go: fmt.Sprintf("--file_content_in_loop=%v", filePathInReader), test/e2e/common/host_path.go: fmt.Sprintf("--file_content_in_loop=%v", filePathInReader),
test/e2e/common/host_path.go: fmt.Sprintf("--retry_time=%d", retryDuration), test/e2e/common/host_path.go: fmt.Sprintf("--retry_time=%d", retryDuration),
test/e2e/common/host_path.go: fmt.Sprintf("--retry_time=%d", retryDuration), test/e2e/common/host_path.go: fmt.Sprintf("--retry_time=%d", retryDuration),
test/e2e/common/secrets.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
test/e2e/common/secrets.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/secret-volumes/delete/data-1"},
test/e2e/common/secrets.go: Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/secret-volumes/update/data-3"},
test/e2e_node/container_manager_test.go: return fmt.Errorf("expected pid %d's oom_score_adj to be %d; found %d", pid, expectedOOMScoreAdj, oomScore) test/e2e_node/container_manager_test.go: return fmt.Errorf("expected pid %d's oom_score_adj to be %d; found %d", pid, expectedOOMScoreAdj, oomScore)
test/e2e_node/container_manager_test.go: return fmt.Errorf("expected pid %d's oom_score_adj to be < %d; found %d", pid, expectedMaxOOMScoreAdj, oomScore) test/e2e_node/container_manager_test.go: return fmt.Errorf("expected pid %d's oom_score_adj to be < %d; found %d", pid, expectedMaxOOMScoreAdj, oomScore)
test/e2e_node/container_manager_test.go: return fmt.Errorf("expected pid %d's oom_score_adj to be >= %d; found %d", pid, expectedMinOOMScoreAdj, oomScore) test/e2e_node/container_manager_test.go: return fmt.Errorf("expected pid %d's oom_score_adj to be >= %d; found %d", pid, expectedMinOOMScoreAdj, oomScore)

View File

@ -286,6 +286,10 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
func(s *api.SecretVolumeSource, c fuzz.Continue) { func(s *api.SecretVolumeSource, c fuzz.Continue) {
c.FuzzNoCustom(s) // fuzz self without calling this function again c.FuzzNoCustom(s) // fuzz self without calling this function again
if c.RandBool() {
opt := c.RandBool()
s.Optional = &opt
}
// DefaultMode should always be set, it has a default // DefaultMode should always be set, it has a default
// value and it is expected to be between 0 and 0777 // value and it is expected to be between 0 and 0777
var mode int32 var mode int32
@ -296,6 +300,10 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
func(cm *api.ConfigMapVolumeSource, c fuzz.Continue) { func(cm *api.ConfigMapVolumeSource, c fuzz.Continue) {
c.FuzzNoCustom(cm) // fuzz self without calling this function again c.FuzzNoCustom(cm) // fuzz self without calling this function again
if c.RandBool() {
opt := c.RandBool()
cm.Optional = &opt
}
// DefaultMode should always be set, it has a default // DefaultMode should always be set, it has a default
// value and it is expected to be between 0 and 0777 // value and it is expected to be between 0 and 0777
var mode int32 var mode int32
@ -401,6 +409,10 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
}, },
func(cm *api.ConfigMapEnvSource, c fuzz.Continue) { func(cm *api.ConfigMapEnvSource, c fuzz.Continue) {
c.FuzzNoCustom(cm) // fuzz self without calling this function again c.FuzzNoCustom(cm) // fuzz self without calling this function again
if c.RandBool() {
opt := c.RandBool()
cm.Optional = &opt
}
}, },
func(s *api.SecretEnvSource, c fuzz.Continue) { func(s *api.SecretEnvSource, c fuzz.Continue) {
c.FuzzNoCustom(s) // fuzz self without calling this function again c.FuzzNoCustom(s) // fuzz self without calling this function again

View File

@ -729,8 +729,8 @@ type SecretVolumeSource struct {
// key and content is the value. If specified, the listed keys will be // key and content is the value. If specified, the listed keys will be
// projected into the specified paths, and unlisted keys will not be // projected into the specified paths, and unlisted keys will not be
// present. If a key is specified which is not present in the Secret, // present. If a key is specified which is not present in the Secret,
// the volume setup will error. Paths must be relative and may not contain // the volume setup will error unless it is marked optional. Paths must be
// the '..' path or start with '..'. // relative and may not contain the '..' path or start with '..'.
// +optional // +optional
Items []KeyToPath Items []KeyToPath
// Mode bits to use on created files by default. Must be a value between // Mode bits to use on created files by default. Must be a value between
@ -740,6 +740,9 @@ type SecretVolumeSource struct {
// mode, like fsGroup, and the result can be other mode bits set. // mode, like fsGroup, and the result can be other mode bits set.
// +optional // +optional
DefaultMode *int32 DefaultMode *int32
// Specify whether the Secret or it's key must be defined
// +optional
Optional *bool
} }
// Represents an NFS mount that lasts the lifetime of a pod. // Represents an NFS mount that lasts the lifetime of a pod.
@ -992,8 +995,8 @@ type ConfigMapVolumeSource struct {
// key and content is the value. If specified, the listed keys will be // key and content is the value. If specified, the listed keys will be
// projected into the specified paths, and unlisted keys will not be // projected into the specified paths, and unlisted keys will not be
// present. If a key is specified which is not present in the ConfigMap, // present. If a key is specified which is not present in the ConfigMap,
// the volume setup will error. Paths must be relative and may not contain // the volume setup will error unless it is marked optional. Paths must be
// the '..' path or start with '..'. // relative and may not contain the '..' path or start with '..'.
// +optional // +optional
Items []KeyToPath Items []KeyToPath
// Mode bits to use on created files by default. Must be a value between // Mode bits to use on created files by default. Must be a value between
@ -1003,6 +1006,9 @@ type ConfigMapVolumeSource struct {
// mode, like fsGroup, and the result can be other mode bits set. // mode, like fsGroup, and the result can be other mode bits set.
// +optional // +optional
DefaultMode *int32 DefaultMode *int32
// Specify whether the ConfigMap or it's keys must be defined
// +optional
Optional *bool
} }
// Maps a string key to a path within a volume. // Maps a string key to a path within a volume.
@ -1124,6 +1130,9 @@ type ConfigMapKeySelector struct {
LocalObjectReference LocalObjectReference
// The key to select. // The key to select.
Key string Key string
// Specify whether the ConfigMap or it's key must be defined
// +optional
Optional *bool
} }
// SecretKeySelector selects a key of a Secret. // SecretKeySelector selects a key of a Secret.
@ -1132,6 +1141,9 @@ type SecretKeySelector struct {
LocalObjectReference LocalObjectReference
// The key of the secret to select from. Must be a valid secret key. // The key of the secret to select from. Must be a valid secret key.
Key string Key string
// Specify whether the Secret or it's key must be defined
// +optional
Optional *bool
} }
// EnvFromSource represents the source of a set of ConfigMaps // EnvFromSource represents the source of a set of ConfigMaps
@ -1155,6 +1167,9 @@ type EnvFromSource struct {
type ConfigMapEnvSource struct { type ConfigMapEnvSource struct {
// The ConfigMap to select from. // The ConfigMap to select from.
LocalObjectReference LocalObjectReference
// Specify whether the ConfigMap must be defined
// +optional
Optional *bool
} }
// SecretEnvSource selects a Secret to populate the environment // SecretEnvSource selects a Secret to populate the environment
@ -1165,6 +1180,9 @@ type ConfigMapEnvSource struct {
type SecretEnvSource struct { type SecretEnvSource struct {
// The Secret to select from. // The Secret to select from.
LocalObjectReference LocalObjectReference
// Specify whether the Secret must be defined
// +optional
Optional *bool
} }
// HTTPHeader describes a custom header to be used in HTTP probes // HTTPHeader describes a custom header to be used in HTTP probes

File diff suppressed because it is too large Load Diff

View File

@ -279,6 +279,10 @@ message ConfigMap {
message ConfigMapEnvSource { message ConfigMapEnvSource {
// The ConfigMap to select from. // The ConfigMap to select from.
optional LocalObjectReference localObjectReference = 1; optional LocalObjectReference localObjectReference = 1;
// Specify whether the ConfigMap must be defined
// +optional
optional bool optional = 2;
} }
// Selects a key from a ConfigMap. // Selects a key from a ConfigMap.
@ -288,6 +292,10 @@ message ConfigMapKeySelector {
// The key to select. // The key to select.
optional string key = 2; optional string key = 2;
// Specify whether the ConfigMap or it's key must be defined
// +optional
optional bool optional = 3;
} }
// ConfigMapList is a resource containing a list of ConfigMap objects. // ConfigMapList is a resource containing a list of ConfigMap objects.
@ -314,8 +322,8 @@ message ConfigMapVolumeSource {
// key and content is the value. If specified, the listed keys will be // key and content is the value. If specified, the listed keys will be
// projected into the specified paths, and unlisted keys will not be // projected into the specified paths, and unlisted keys will not be
// present. If a key is specified which is not present in the ConfigMap, // present. If a key is specified which is not present in the ConfigMap,
// the volume setup will error. Paths must be relative and may not contain // the volume setup will error unless it is marked optional. Paths must be
// the '..' path or start with '..'. // relative and may not contain the '..' path or start with '..'.
// +optional // +optional
repeated KeyToPath items = 2; repeated KeyToPath items = 2;
@ -326,6 +334,10 @@ message ConfigMapVolumeSource {
// mode, like fsGroup, and the result can be other mode bits set. // mode, like fsGroup, and the result can be other mode bits set.
// +optional // +optional
optional int32 defaultMode = 3; optional int32 defaultMode = 3;
// Specify whether the ConfigMap or it's keys must be defined
// +optional
optional bool optional = 4;
} }
// A single application container that you want to run within a pod. // A single application container that you want to run within a pod.
@ -3106,6 +3118,10 @@ message Secret {
message SecretEnvSource { message SecretEnvSource {
// The Secret to select from. // The Secret to select from.
optional LocalObjectReference localObjectReference = 1; optional LocalObjectReference localObjectReference = 1;
// Specify whether the Secret must be defined
// +optional
optional bool optional = 2;
} }
// SecretKeySelector selects a key of a Secret. // SecretKeySelector selects a key of a Secret.
@ -3115,6 +3131,10 @@ message SecretKeySelector {
// The key of the secret to select from. Must be a valid secret key. // The key of the secret to select from. Must be a valid secret key.
optional string key = 2; optional string key = 2;
// Specify whether the Secret or it's key must be defined
// +optional
optional bool optional = 3;
} }
// SecretList is a list of Secret. // SecretList is a list of Secret.
@ -3145,8 +3165,8 @@ message SecretVolumeSource {
// key and content is the value. If specified, the listed keys will be // key and content is the value. If specified, the listed keys will be
// projected into the specified paths, and unlisted keys will not be // projected into the specified paths, and unlisted keys will not be
// present. If a key is specified which is not present in the Secret, // present. If a key is specified which is not present in the Secret,
// the volume setup will error. Paths must be relative and may not contain // the volume setup will error unless it is marked optional. Paths must be
// the '..' path or start with '..'. // relative and may not contain the '..' path or start with '..'.
// +optional // +optional
repeated KeyToPath items = 2; repeated KeyToPath items = 2;
@ -3157,6 +3177,10 @@ message SecretVolumeSource {
// mode, like fsGroup, and the result can be other mode bits set. // mode, like fsGroup, and the result can be other mode bits set.
// +optional // +optional
optional int32 defaultMode = 3; optional int32 defaultMode = 3;
// Specify whether the Secret or it's keys must be defined
// +optional
optional bool optional = 4;
} }
// SecurityContext holds security configuration that will be applied to a container. // SecurityContext holds security configuration that will be applied to a container.

File diff suppressed because it is too large Load Diff

View File

@ -924,8 +924,8 @@ type SecretVolumeSource struct {
// key and content is the value. If specified, the listed keys will be // key and content is the value. If specified, the listed keys will be
// projected into the specified paths, and unlisted keys will not be // projected into the specified paths, and unlisted keys will not be
// present. If a key is specified which is not present in the Secret, // present. If a key is specified which is not present in the Secret,
// the volume setup will error. Paths must be relative and may not contain // the volume setup will error unless it is marked optional. Paths must be
// the '..' path or start with '..'. // relative and may not contain the '..' path or start with '..'.
// +optional // +optional
Items []KeyToPath `json:"items,omitempty" protobuf:"bytes,2,rep,name=items"` Items []KeyToPath `json:"items,omitempty" protobuf:"bytes,2,rep,name=items"`
// Optional: mode bits to use on created files by default. Must be a // Optional: mode bits to use on created files by default. Must be a
@ -935,6 +935,9 @@ type SecretVolumeSource struct {
// mode, like fsGroup, and the result can be other mode bits set. // mode, like fsGroup, and the result can be other mode bits set.
// +optional // +optional
DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"bytes,3,opt,name=defaultMode"` DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"bytes,3,opt,name=defaultMode"`
// Specify whether the Secret or it's keys must be defined
// +optional
Optional *bool `json:"optional,omitempty" protobuf:"varint,4,opt,name=optional"`
} }
const ( const (
@ -1081,8 +1084,8 @@ type ConfigMapVolumeSource struct {
// key and content is the value. If specified, the listed keys will be // key and content is the value. If specified, the listed keys will be
// projected into the specified paths, and unlisted keys will not be // projected into the specified paths, and unlisted keys will not be
// present. If a key is specified which is not present in the ConfigMap, // present. If a key is specified which is not present in the ConfigMap,
// the volume setup will error. Paths must be relative and may not contain // the volume setup will error unless it is marked optional. Paths must be
// the '..' path or start with '..'. // relative and may not contain the '..' path or start with '..'.
// +optional // +optional
Items []KeyToPath `json:"items,omitempty" protobuf:"bytes,2,rep,name=items"` Items []KeyToPath `json:"items,omitempty" protobuf:"bytes,2,rep,name=items"`
// Optional: mode bits to use on created files by default. Must be a // Optional: mode bits to use on created files by default. Must be a
@ -1092,6 +1095,9 @@ type ConfigMapVolumeSource struct {
// mode, like fsGroup, and the result can be other mode bits set. // mode, like fsGroup, and the result can be other mode bits set.
// +optional // +optional
DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"varint,3,opt,name=defaultMode"` DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"varint,3,opt,name=defaultMode"`
// Specify whether the ConfigMap or it's keys must be defined
// +optional
Optional *bool `json:"optional,omitempty" protobuf:"varint,4,opt,name=optional"`
} }
const ( const (
@ -1225,6 +1231,9 @@ type ConfigMapKeySelector struct {
LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"` LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
// The key to select. // The key to select.
Key string `json:"key" protobuf:"bytes,2,opt,name=key"` Key string `json:"key" protobuf:"bytes,2,opt,name=key"`
// Specify whether the ConfigMap or it's key must be defined
// +optional
Optional *bool `json:"optional,omitempty" protobuf:"varint,3,opt,name=optional"`
} }
// SecretKeySelector selects a key of a Secret. // SecretKeySelector selects a key of a Secret.
@ -1233,6 +1242,9 @@ type SecretKeySelector struct {
LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"` LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
// The key of the secret to select from. Must be a valid secret key. // The key of the secret to select from. Must be a valid secret key.
Key string `json:"key" protobuf:"bytes,2,opt,name=key"` Key string `json:"key" protobuf:"bytes,2,opt,name=key"`
// Specify whether the Secret or it's key must be defined
// +optional
Optional *bool `json:"optional,omitempty" protobuf:"varint,3,opt,name=optional"`
} }
// EnvFromSource represents the source of a set of ConfigMaps // EnvFromSource represents the source of a set of ConfigMaps
@ -1256,6 +1268,9 @@ type EnvFromSource struct {
type ConfigMapEnvSource struct { type ConfigMapEnvSource struct {
// The ConfigMap to select from. // The ConfigMap to select from.
LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"` LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
// Specify whether the ConfigMap must be defined
// +optional
Optional *bool `json:"optional,omitempty" protobuf:"varint,2,opt,name=optional"`
} }
// SecretEnvSource selects a Secret to populate the environment // SecretEnvSource selects a Secret to populate the environment
@ -1266,6 +1281,9 @@ type ConfigMapEnvSource struct {
type SecretEnvSource struct { type SecretEnvSource struct {
// The Secret to select from. // The Secret to select from.
LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"` LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
// Specify whether the Secret must be defined
// +optional
Optional *bool `json:"optional,omitempty" protobuf:"varint,2,opt,name=optional"`
} }
// HTTPHeader describes a custom header to be used in HTTP probes // HTTPHeader describes a custom header to be used in HTTP probes

View File

@ -181,7 +181,8 @@ func (ConfigMap) SwaggerDoc() map[string]string {
} }
var map_ConfigMapEnvSource = map[string]string{ 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.", "": "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.",
"optional": "Specify whether the ConfigMap must be defined",
} }
func (ConfigMapEnvSource) SwaggerDoc() map[string]string { func (ConfigMapEnvSource) SwaggerDoc() map[string]string {
@ -189,8 +190,9 @@ func (ConfigMapEnvSource) SwaggerDoc() map[string]string {
} }
var map_ConfigMapKeySelector = map[string]string{ var map_ConfigMapKeySelector = map[string]string{
"": "Selects a key from a ConfigMap.", "": "Selects a key from a ConfigMap.",
"key": "The key to select.", "key": "The key to select.",
"optional": "Specify whether the ConfigMap or it's key must be defined",
} }
func (ConfigMapKeySelector) SwaggerDoc() map[string]string { func (ConfigMapKeySelector) SwaggerDoc() map[string]string {
@ -209,8 +211,9 @@ func (ConfigMapList) SwaggerDoc() map[string]string {
var map_ConfigMapVolumeSource = map[string]string{ var map_ConfigMapVolumeSource = map[string]string{
"": "Adapts a ConfigMap into a volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. ConfigMap volumes support ownership management and SELinux relabeling.", "": "Adapts a ConfigMap into a volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. ConfigMap volumes support ownership management and SELinux relabeling.",
"items": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", "items": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
"defaultMode": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", "defaultMode": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.",
"optional": "Specify whether the ConfigMap or it's keys must be defined",
} }
func (ConfigMapVolumeSource) SwaggerDoc() map[string]string { func (ConfigMapVolumeSource) SwaggerDoc() map[string]string {
@ -1600,7 +1603,8 @@ func (Secret) SwaggerDoc() map[string]string {
} }
var map_SecretEnvSource = map[string]string{ var map_SecretEnvSource = map[string]string{
"": "SecretEnvSource selects a Secret to populate the environment variables with.\n\nThe contents of the target Secret's Data field will represent the key-value pairs as environment variables.", "": "SecretEnvSource selects a Secret to populate the environment variables with.\n\nThe contents of the target Secret's Data field will represent the key-value pairs as environment variables.",
"optional": "Specify whether the Secret must be defined",
} }
func (SecretEnvSource) SwaggerDoc() map[string]string { func (SecretEnvSource) SwaggerDoc() map[string]string {
@ -1608,8 +1612,9 @@ func (SecretEnvSource) SwaggerDoc() map[string]string {
} }
var map_SecretKeySelector = map[string]string{ var map_SecretKeySelector = map[string]string{
"": "SecretKeySelector selects a key of a Secret.", "": "SecretKeySelector selects a key of a Secret.",
"key": "The key of the secret to select from. Must be a valid secret key.", "key": "The key of the secret to select from. Must be a valid secret key.",
"optional": "Specify whether the Secret or it's key must be defined",
} }
func (SecretKeySelector) SwaggerDoc() map[string]string { func (SecretKeySelector) SwaggerDoc() map[string]string {
@ -1629,8 +1634,9 @@ func (SecretList) SwaggerDoc() map[string]string {
var map_SecretVolumeSource = map[string]string{ var map_SecretVolumeSource = map[string]string{
"": "Adapts a Secret into a volume.\n\nThe contents of the target Secret's Data field will be presented in a volume as files using the keys in the Data field as the file names. Secret volumes support ownership management and SELinux relabeling.", "": "Adapts a Secret into a volume.\n\nThe contents of the target Secret's Data field will be presented in a volume as files using the keys in the Data field as the file names. Secret volumes support ownership management and SELinux relabeling.",
"secretName": "Name of the secret in the pod's namespace to use. More info: http://kubernetes.io/docs/user-guide/volumes#secrets", "secretName": "Name of the secret in the pod's namespace to use. More info: http://kubernetes.io/docs/user-guide/volumes#secrets",
"items": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", "items": "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
"defaultMode": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", "defaultMode": "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.",
"optional": "Specify whether the Secret or it's keys must be defined",
} }
func (SecretVolumeSource) SwaggerDoc() map[string]string { func (SecretVolumeSource) SwaggerDoc() map[string]string {

View File

@ -674,6 +674,7 @@ func autoConvert_v1_ConfigMapEnvSource_To_api_ConfigMapEnvSource(in *ConfigMapEn
if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
return err return err
} }
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -685,6 +686,7 @@ func autoConvert_api_ConfigMapEnvSource_To_v1_ConfigMapEnvSource(in *api.ConfigM
if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
return err return err
} }
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -697,6 +699,7 @@ func autoConvert_v1_ConfigMapKeySelector_To_api_ConfigMapKeySelector(in *ConfigM
return err return err
} }
out.Key = in.Key out.Key = in.Key
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -709,6 +712,7 @@ func autoConvert_api_ConfigMapKeySelector_To_v1_ConfigMapKeySelector(in *api.Con
return err return err
} }
out.Key = in.Key out.Key = in.Key
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -742,6 +746,7 @@ func autoConvert_v1_ConfigMapVolumeSource_To_api_ConfigMapVolumeSource(in *Confi
} }
out.Items = *(*[]api.KeyToPath)(unsafe.Pointer(&in.Items)) out.Items = *(*[]api.KeyToPath)(unsafe.Pointer(&in.Items))
out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode))
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -755,6 +760,7 @@ func autoConvert_api_ConfigMapVolumeSource_To_v1_ConfigMapVolumeSource(in *api.C
} }
out.Items = *(*[]KeyToPath)(unsafe.Pointer(&in.Items)) out.Items = *(*[]KeyToPath)(unsafe.Pointer(&in.Items))
out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode))
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -3790,6 +3796,7 @@ func autoConvert_v1_SecretEnvSource_To_api_SecretEnvSource(in *SecretEnvSource,
if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
return err return err
} }
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -3801,6 +3808,7 @@ func autoConvert_api_SecretEnvSource_To_v1_SecretEnvSource(in *api.SecretEnvSour
if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
return err return err
} }
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -3813,6 +3821,7 @@ func autoConvert_v1_SecretKeySelector_To_api_SecretKeySelector(in *SecretKeySele
return err return err
} }
out.Key = in.Key out.Key = in.Key
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -3825,6 +3834,7 @@ func autoConvert_api_SecretKeySelector_To_v1_SecretKeySelector(in *api.SecretKey
return err return err
} }
out.Key = in.Key out.Key = in.Key
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -3876,6 +3886,7 @@ func autoConvert_v1_SecretVolumeSource_To_api_SecretVolumeSource(in *SecretVolum
out.SecretName = in.SecretName out.SecretName = in.SecretName
out.Items = *(*[]api.KeyToPath)(unsafe.Pointer(&in.Items)) out.Items = *(*[]api.KeyToPath)(unsafe.Pointer(&in.Items))
out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode))
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }
@ -3887,6 +3898,7 @@ func autoConvert_api_SecretVolumeSource_To_v1_SecretVolumeSource(in *api.SecretV
out.SecretName = in.SecretName out.SecretName = in.SecretName
out.Items = *(*[]KeyToPath)(unsafe.Pointer(&in.Items)) out.Items = *(*[]KeyToPath)(unsafe.Pointer(&in.Items))
out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode)) out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode))
out.Optional = (*bool)(unsafe.Pointer(in.Optional))
return nil return nil
} }

View File

@ -431,6 +431,11 @@ func DeepCopy_v1_ConfigMapEnvSource(in interface{}, out interface{}, c *conversi
in := in.(*ConfigMapEnvSource) in := in.(*ConfigMapEnvSource)
out := out.(*ConfigMapEnvSource) out := out.(*ConfigMapEnvSource)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -440,6 +445,11 @@ func DeepCopy_v1_ConfigMapKeySelector(in interface{}, out interface{}, c *conver
in := in.(*ConfigMapKeySelector) in := in.(*ConfigMapKeySelector)
out := out.(*ConfigMapKeySelector) out := out.(*ConfigMapKeySelector)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -481,6 +491,11 @@ func DeepCopy_v1_ConfigMapVolumeSource(in interface{}, out interface{}, c *conve
*out = new(int32) *out = new(int32)
**out = **in **out = **in
} }
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -861,12 +876,16 @@ func DeepCopy_v1_EnvFromSource(in interface{}, out interface{}, c *conversion.Cl
if in.ConfigMapRef != nil { if in.ConfigMapRef != nil {
in, out := &in.ConfigMapRef, &out.ConfigMapRef in, out := &in.ConfigMapRef, &out.ConfigMapRef
*out = new(ConfigMapEnvSource) *out = new(ConfigMapEnvSource)
**out = **in if err := DeepCopy_v1_ConfigMapEnvSource(*in, *out, c); err != nil {
return err
}
} }
if in.SecretRef != nil { if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef in, out := &in.SecretRef, &out.SecretRef
*out = new(SecretEnvSource) *out = new(SecretEnvSource)
**out = **in if err := DeepCopy_v1_SecretEnvSource(*in, *out, c); err != nil {
return err
}
} }
return nil return nil
} }
@ -908,12 +927,16 @@ func DeepCopy_v1_EnvVarSource(in interface{}, out interface{}, c *conversion.Clo
if in.ConfigMapKeyRef != nil { if in.ConfigMapKeyRef != nil {
in, out := &in.ConfigMapKeyRef, &out.ConfigMapKeyRef in, out := &in.ConfigMapKeyRef, &out.ConfigMapKeyRef
*out = new(ConfigMapKeySelector) *out = new(ConfigMapKeySelector)
**out = **in if err := DeepCopy_v1_ConfigMapKeySelector(*in, *out, c); err != nil {
return err
}
} }
if in.SecretKeyRef != nil { if in.SecretKeyRef != nil {
in, out := &in.SecretKeyRef, &out.SecretKeyRef in, out := &in.SecretKeyRef, &out.SecretKeyRef
*out = new(SecretKeySelector) *out = new(SecretKeySelector)
**out = **in if err := DeepCopy_v1_SecretKeySelector(*in, *out, c); err != nil {
return err
}
} }
return nil return nil
} }
@ -2759,6 +2782,11 @@ func DeepCopy_v1_SecretEnvSource(in interface{}, out interface{}, c *conversion.
in := in.(*SecretEnvSource) in := in.(*SecretEnvSource)
out := out.(*SecretEnvSource) out := out.(*SecretEnvSource)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -2768,6 +2796,11 @@ func DeepCopy_v1_SecretKeySelector(in interface{}, out interface{}, c *conversio
in := in.(*SecretKeySelector) in := in.(*SecretKeySelector)
out := out.(*SecretKeySelector) out := out.(*SecretKeySelector)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -2809,6 +2842,11 @@ func DeepCopy_v1_SecretVolumeSource(in interface{}, out interface{}, c *conversi
*out = new(int32) *out = new(int32)
**out = **in **out = **in
} }
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }

View File

@ -434,6 +434,11 @@ func DeepCopy_api_ConfigMapEnvSource(in interface{}, out interface{}, c *convers
in := in.(*ConfigMapEnvSource) in := in.(*ConfigMapEnvSource)
out := out.(*ConfigMapEnvSource) out := out.(*ConfigMapEnvSource)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -443,6 +448,11 @@ func DeepCopy_api_ConfigMapKeySelector(in interface{}, out interface{}, c *conve
in := in.(*ConfigMapKeySelector) in := in.(*ConfigMapKeySelector)
out := out.(*ConfigMapKeySelector) out := out.(*ConfigMapKeySelector)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -484,6 +494,11 @@ func DeepCopy_api_ConfigMapVolumeSource(in interface{}, out interface{}, c *conv
*out = new(int32) *out = new(int32)
**out = **in **out = **in
} }
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -889,12 +904,16 @@ func DeepCopy_api_EnvFromSource(in interface{}, out interface{}, c *conversion.C
if in.ConfigMapRef != nil { if in.ConfigMapRef != nil {
in, out := &in.ConfigMapRef, &out.ConfigMapRef in, out := &in.ConfigMapRef, &out.ConfigMapRef
*out = new(ConfigMapEnvSource) *out = new(ConfigMapEnvSource)
**out = **in if err := DeepCopy_api_ConfigMapEnvSource(*in, *out, c); err != nil {
return err
}
} }
if in.SecretRef != nil { if in.SecretRef != nil {
in, out := &in.SecretRef, &out.SecretRef in, out := &in.SecretRef, &out.SecretRef
*out = new(SecretEnvSource) *out = new(SecretEnvSource)
**out = **in if err := DeepCopy_api_SecretEnvSource(*in, *out, c); err != nil {
return err
}
} }
return nil return nil
} }
@ -936,12 +955,16 @@ func DeepCopy_api_EnvVarSource(in interface{}, out interface{}, c *conversion.Cl
if in.ConfigMapKeyRef != nil { if in.ConfigMapKeyRef != nil {
in, out := &in.ConfigMapKeyRef, &out.ConfigMapKeyRef in, out := &in.ConfigMapKeyRef, &out.ConfigMapKeyRef
*out = new(ConfigMapKeySelector) *out = new(ConfigMapKeySelector)
**out = **in if err := DeepCopy_api_ConfigMapKeySelector(*in, *out, c); err != nil {
return err
}
} }
if in.SecretKeyRef != nil { if in.SecretKeyRef != nil {
in, out := &in.SecretKeyRef, &out.SecretKeyRef in, out := &in.SecretKeyRef, &out.SecretKeyRef
*out = new(SecretKeySelector) *out = new(SecretKeySelector)
**out = **in if err := DeepCopy_api_SecretKeySelector(*in, *out, c); err != nil {
return err
}
} }
return nil return nil
} }
@ -2791,6 +2814,11 @@ func DeepCopy_api_SecretEnvSource(in interface{}, out interface{}, c *conversion
in := in.(*SecretEnvSource) in := in.(*SecretEnvSource)
out := out.(*SecretEnvSource) out := out.(*SecretEnvSource)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -2800,6 +2828,11 @@ func DeepCopy_api_SecretKeySelector(in interface{}, out interface{}, c *conversi
in := in.(*SecretKeySelector) in := in.(*SecretKeySelector)
out := out.(*SecretKeySelector) out := out.(*SecretKeySelector)
*out = *in *out = *in
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }
@ -2841,6 +2874,11 @@ func DeepCopy_api_SecretVolumeSource(in interface{}, out interface{}, c *convers
*out = new(int32) *out = new(int32)
**out = **in **out = **in
} }
if in.Optional != nil {
in, out := &in.Optional, &out.Optional
*out = new(bool)
**out = **in
}
return nil return nil
} }
} }

View File

@ -933,6 +933,13 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
Format: "", Format: "",
}, },
}, },
"optional": {
SchemaProps: spec.SchemaProps{
Description: "Specify whether the ConfigMap must be defined",
Type: []string{"boolean"},
Format: "",
},
},
}, },
}, },
}, },
@ -957,6 +964,13 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
Format: "", Format: "",
}, },
}, },
"optional": {
SchemaProps: spec.SchemaProps{
Description: "Specify whether the ConfigMap or it's key must be defined",
Type: []string{"boolean"},
Format: "",
},
},
}, },
Required: []string{"key"}, Required: []string{"key"},
}, },
@ -1022,7 +1036,7 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
}, },
"items": { "items": {
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Description: "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", Description: "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
Type: []string{"array"}, Type: []string{"array"},
Items: &spec.SchemaOrArray{ Items: &spec.SchemaOrArray{
Schema: &spec.Schema{ Schema: &spec.Schema{
@ -1040,6 +1054,13 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
Format: "int32", Format: "int32",
}, },
}, },
"optional": {
SchemaProps: spec.SchemaProps{
Description: "Specify whether the ConfigMap or it's keys must be defined",
Type: []string{"boolean"},
Format: "",
},
},
}, },
}, },
}, },
@ -7430,6 +7451,13 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
Format: "", Format: "",
}, },
}, },
"optional": {
SchemaProps: spec.SchemaProps{
Description: "Specify whether the Secret must be defined",
Type: []string{"boolean"},
Format: "",
},
},
}, },
}, },
}, },
@ -7454,6 +7482,13 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
Format: "", Format: "",
}, },
}, },
"optional": {
SchemaProps: spec.SchemaProps{
Description: "Specify whether the Secret or it's key must be defined",
Type: []string{"boolean"},
Format: "",
},
},
}, },
Required: []string{"key"}, Required: []string{"key"},
}, },
@ -7519,7 +7554,7 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
}, },
"items": { "items": {
SchemaProps: spec.SchemaProps{ SchemaProps: spec.SchemaProps{
Description: "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.", Description: "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
Type: []string{"array"}, Type: []string{"array"},
Items: &spec.SchemaOrArray{ Items: &spec.SchemaOrArray{
Schema: &spec.Schema{ Schema: &spec.Schema{
@ -7537,6 +7572,13 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions
Format: "int32", Format: "int32",
}, },
}, },
"optional": {
SchemaProps: spec.SchemaProps{
Description: "Specify whether the Secret or it's keys must be defined",
Type: []string{"boolean"},
Format: "",
},
},
}, },
}, },
}, },

View File

@ -650,13 +650,19 @@ func printGitRepoVolumeSource(git *api.GitRepoVolumeSource, w *PrefixWriter) {
} }
func printSecretVolumeSource(secret *api.SecretVolumeSource, w *PrefixWriter) { func printSecretVolumeSource(secret *api.SecretVolumeSource, w *PrefixWriter) {
optional := secret.Optional != nil && *secret.Optional
w.Write(LEVEL_2, "Type:\tSecret (a volume populated by a Secret)\n"+ w.Write(LEVEL_2, "Type:\tSecret (a volume populated by a Secret)\n"+
" SecretName:\t%v\n", secret.SecretName) " SecretName:\t%v\n",
" Optional:\t%v\n",
secret.SecretName, optional)
} }
func printConfigMapVolumeSource(configMap *api.ConfigMapVolumeSource, w *PrefixWriter) { func printConfigMapVolumeSource(configMap *api.ConfigMapVolumeSource, w *PrefixWriter) {
optional := configMap.Optional != nil && *configMap.Optional
w.Write(LEVEL_2, "Type:\tConfigMap (a volume populated by a ConfigMap)\n"+ w.Write(LEVEL_2, "Type:\tConfigMap (a volume populated by a ConfigMap)\n"+
" Name:\t%v\n", configMap.Name) " Name:\t%v\n"+
" Optional:\t%v\n",
configMap.Name, optional)
} }
func printNFSVolumeSource(nfs *api.NFSVolumeSource, w *PrefixWriter) { func printNFSVolumeSource(nfs *api.NFSVolumeSource, w *PrefixWriter) {
@ -1037,9 +1043,11 @@ func describeContainerEnvVars(container api.Container, resolverFn EnvVarResolver
} }
w.Write(LEVEL_3, "%s:\t%s (%s)\n", e.Name, valueFrom, resource) w.Write(LEVEL_3, "%s:\t%s (%s)\n", e.Name, valueFrom, resource)
case e.ValueFrom.SecretKeyRef != nil: case e.ValueFrom.SecretKeyRef != nil:
w.Write(LEVEL_3, "%s:\t<set to the key '%s' in secret '%s'>\n", e.Name, e.ValueFrom.SecretKeyRef.Key, e.ValueFrom.SecretKeyRef.Name) optional := e.ValueFrom.SecretKeyRef.Optional != nil && *e.ValueFrom.SecretKeyRef.Optional
w.Write(LEVEL_3, "%s:\t<set to the key '%s' in secret '%s'>\tOptional: %t\n", e.Name, e.ValueFrom.SecretKeyRef.Key, e.ValueFrom.SecretKeyRef.Name, optional)
case e.ValueFrom.ConfigMapKeyRef != nil: case e.ValueFrom.ConfigMapKeyRef != nil:
w.Write(LEVEL_3, "%s:\t<set to the key '%s' of config map '%s'>\n", e.Name, e.ValueFrom.ConfigMapKeyRef.Key, e.ValueFrom.ConfigMapKeyRef.Name) optional := e.ValueFrom.ConfigMapKeyRef.Optional != nil && *e.ValueFrom.ConfigMapKeyRef.Optional
w.Write(LEVEL_3, "%s:\t<set to the key '%s' of config map '%s'>\tOptional: %t\n", e.Name, e.ValueFrom.ConfigMapKeyRef.Key, e.ValueFrom.ConfigMapKeyRef.Name, optional)
} }
} }
} }
@ -1054,17 +1062,20 @@ func describeContainerEnvFrom(container api.Container, resolverFn EnvVarResolver
for _, e := range container.EnvFrom { for _, e := range container.EnvFrom {
from := "" from := ""
name := "" name := ""
optional := false
if e.ConfigMapRef != nil { if e.ConfigMapRef != nil {
from = "ConfigMap" from = "ConfigMap"
name = e.ConfigMapRef.Name name = e.ConfigMapRef.Name
optional = e.ConfigMapRef.Optional != nil && *e.ConfigMapRef.Optional
} else if e.SecretRef != nil { } else if e.SecretRef != nil {
from = "Secret" from = "Secret"
name = e.SecretRef.Name name = e.SecretRef.Name
optional = e.SecretRef.Optional != nil && *e.SecretRef.Optional
} }
if len(e.Prefix) == 0 { if len(e.Prefix) == 0 {
w.Write(LEVEL_3, "%s\t%s\n", name, from) w.Write(LEVEL_3, "%s\t%s\tOptional: %t\n", name, from, optional)
} else { } else {
w.Write(LEVEL_3, "%s\t%s with prefix '%s'\n", name, from, e.Prefix) w.Write(LEVEL_3, "%s\t%s with prefix '%s'\tOptional: %t\n", name, from, e.Prefix, optional)
} }
} }
} }

View File

@ -201,6 +201,7 @@ func VerifyDatesInOrder(
} }
func TestDescribeContainers(t *testing.T) { func TestDescribeContainers(t *testing.T) {
trueVal := true
testCases := []struct { testCases := []struct {
container api.Container container api.Container
status api.ContainerStatus status api.ContainerStatus
@ -295,7 +296,7 @@ func TestDescribeContainers(t *testing.T) {
Ready: true, Ready: true,
RestartCount: 7, RestartCount: 7,
}, },
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap"}, expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap\tOptional: false"},
}, },
{ {
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"}}}}}, 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"}}}}},
@ -304,16 +305,25 @@ func TestDescribeContainers(t *testing.T) {
Ready: true, Ready: true,
RestartCount: 7, RestartCount: 7,
}, },
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap with prefix 'p_'"}, expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap with prefix 'p_'\tOptional: false"},
}, },
{ {
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}}, container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{ConfigMapRef: &api.ConfigMapEnvSource{Optional: &trueVal, LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
status: api.ContainerStatus{ status: api.ContainerStatus{
Name: "test", Name: "test",
Ready: true, Ready: true,
RestartCount: 7, RestartCount: 7,
}, },
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tSecret"}, expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap\tOptional: true"},
},
{
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}, Optional: &trueVal}}}},
status: api.ContainerStatus{
Name: "test",
Ready: true,
RestartCount: 7,
},
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tSecret\tOptional: true"},
}, },
{ {
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{Prefix: "p_", SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}}, container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{Prefix: "p_", SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
@ -322,7 +332,7 @@ func TestDescribeContainers(t *testing.T) {
Ready: true, Ready: true,
RestartCount: 7, RestartCount: 7,
}, },
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tSecret with prefix 'p_'"}, expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tSecret with prefix 'p_'\tOptional: false"},
}, },
// Command // Command
{ {

View File

@ -33,6 +33,7 @@ import (
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
@ -427,14 +428,20 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
for _, envFrom := range container.EnvFrom { for _, envFrom := range container.EnvFrom {
switch { switch {
case envFrom.ConfigMapRef != nil: case envFrom.ConfigMapRef != nil:
name := envFrom.ConfigMapRef.Name cm := envFrom.ConfigMapRef
name := cm.Name
configMap, ok := configMaps[name] configMap, ok := configMaps[name]
if !ok { if !ok {
if kl.kubeClient == nil { if kl.kubeClient == nil {
return result, fmt.Errorf("Couldn't get configMap %v/%v, no kubeClient defined", pod.Namespace, name) return result, fmt.Errorf("Couldn't get configMap %v/%v, no kubeClient defined", pod.Namespace, name)
} }
optional := cm.Optional != nil && *cm.Optional
configMap, err = kl.kubeClient.Core().ConfigMaps(pod.Namespace).Get(name, metav1.GetOptions{}) configMap, err = kl.kubeClient.Core().ConfigMaps(pod.Namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
if errors.IsNotFound(err) && optional {
// ignore error when marked optional
continue
}
return result, err return result, err
} }
configMaps[name] = configMap configMaps[name] = configMap
@ -450,14 +457,20 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
tmpEnv[k] = v tmpEnv[k] = v
} }
case envFrom.SecretRef != nil: case envFrom.SecretRef != nil:
name := envFrom.SecretRef.Name s := envFrom.SecretRef
name := s.Name
secret, ok := secrets[name] secret, ok := secrets[name]
if !ok { if !ok {
if kl.kubeClient == nil { if kl.kubeClient == nil {
return result, fmt.Errorf("Couldn't get secret %v/%v, no kubeClient defined", pod.Namespace, name) return result, fmt.Errorf("Couldn't get secret %v/%v, no kubeClient defined", pod.Namespace, name)
} }
optional := s.Optional != nil && *s.Optional
secret, err = kl.kubeClient.Core().Secrets(pod.Namespace).Get(name, metav1.GetOptions{}) secret, err = kl.kubeClient.Core().Secrets(pod.Namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
if errors.IsNotFound(err) && optional {
// ignore error when marked optional
continue
}
return result, err return result, err
} }
secrets[name] = secret secrets[name] = secret
@ -510,8 +523,10 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
return result, err return result, err
} }
case envVar.ValueFrom.ConfigMapKeyRef != nil: case envVar.ValueFrom.ConfigMapKeyRef != nil:
name := envVar.ValueFrom.ConfigMapKeyRef.Name cm := envVar.ValueFrom.ConfigMapKeyRef
key := envVar.ValueFrom.ConfigMapKeyRef.Key name := cm.Name
key := cm.Key
optional := cm.Optional != nil && *cm.Optional
configMap, ok := configMaps[name] configMap, ok := configMaps[name]
if !ok { if !ok {
if kl.kubeClient == nil { if kl.kubeClient == nil {
@ -519,17 +534,26 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
} }
configMap, err = kl.kubeClient.Core().ConfigMaps(pod.Namespace).Get(name, metav1.GetOptions{}) configMap, err = kl.kubeClient.Core().ConfigMaps(pod.Namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
if errors.IsNotFound(err) && optional {
// ignore error when marked optional
continue
}
return result, err return result, err
} }
configMaps[name] = configMap configMaps[name] = configMap
} }
runtimeVal, ok = configMap.Data[key] runtimeVal, ok = configMap.Data[key]
if !ok { if !ok {
if optional {
continue
}
return result, fmt.Errorf("Couldn't find key %v in ConfigMap %v/%v", key, pod.Namespace, name) return result, fmt.Errorf("Couldn't find key %v in ConfigMap %v/%v", key, pod.Namespace, name)
} }
case envVar.ValueFrom.SecretKeyRef != nil: case envVar.ValueFrom.SecretKeyRef != nil:
name := envVar.ValueFrom.SecretKeyRef.Name s := envVar.ValueFrom.SecretKeyRef
key := envVar.ValueFrom.SecretKeyRef.Key name := s.Name
key := s.Key
optional := s.Optional != nil && *s.Optional
secret, ok := secrets[name] secret, ok := secrets[name]
if !ok { if !ok {
if kl.kubeClient == nil { if kl.kubeClient == nil {
@ -537,17 +561,30 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
} }
secret, err = kl.secretManager.GetSecret(pod.Namespace, name) secret, err = kl.secretManager.GetSecret(pod.Namespace, name)
if err != nil { if err != nil {
if errors.IsNotFound(err) && optional {
// ignore error when marked optional
continue
}
return result, err return result, err
} }
secrets[name] = secret secrets[name] = secret
} }
runtimeValBytes, ok := secret.Data[key] runtimeValBytes, ok := secret.Data[key]
if !ok { if !ok {
if optional {
continue
}
return result, fmt.Errorf("Couldn't find key %v in Secret %v/%v", key, pod.Namespace, name) return result, fmt.Errorf("Couldn't find key %v in Secret %v/%v", key, pod.Namespace, name)
} }
runtimeVal = string(runtimeValBytes) runtimeVal = string(runtimeValBytes)
} }
} }
// 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, envVar.Name)
tmpEnv[envVar.Name] = runtimeVal tmpEnv[envVar.Name] = runtimeVal
} }

View File

@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -257,6 +258,7 @@ func buildService(name, namespace, clusterIP, protocol string, port int) *v1.Ser
} }
func TestMakeEnvironmentVariables(t *testing.T) { func TestMakeEnvironmentVariables(t *testing.T) {
trueVal := true
services := []*v1.Service{ services := []*v1.Service{
buildService("kubernetes", metav1.NamespaceDefault, "1.2.3.1", "TCP", 8081), buildService("kubernetes", metav1.NamespaceDefault, "1.2.3.1", "TCP", 8081),
buildService("test", "test1", "1.2.3.3", "TCP", 8083), buildService("test", "test1", "1.2.3.3", "TCP", 8083),
@ -616,6 +618,106 @@ func TestMakeEnvironmentVariables(t *testing.T) {
}, },
}, },
}, },
{
name: "configmapkeyref_missing_optional",
ns: "test",
container: &v1.Container{
Env: []v1.EnvVar{
{
Name: "POD_NAME",
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{Name: "missing-config-map"},
Key: "key",
Optional: &trueVal,
},
},
},
},
},
masterServiceNs: "nothing",
expectedEnvs: nil,
},
{
name: "configmapkeyref_missing_key_optional",
ns: "test",
container: &v1.Container{
Env: []v1.EnvVar{
{
Name: "POD_NAME",
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{Name: "test-config-map"},
Key: "key",
Optional: &trueVal,
},
},
},
},
},
masterServiceNs: "nothing",
nilLister: true,
configMap: &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: "test1",
Name: "test-configmap",
},
Data: map[string]string{
"a": "b",
},
},
expectedEnvs: nil,
},
{
name: "secretkeyref_missing_optional",
ns: "test",
container: &v1.Container{
Env: []v1.EnvVar{
{
Name: "POD_NAME",
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{Name: "missing-secret"},
Key: "key",
Optional: &trueVal,
},
},
},
},
},
masterServiceNs: "nothing",
expectedEnvs: nil,
},
{
name: "secretkeyref_missing_key_optional",
ns: "test",
container: &v1.Container{
Env: []v1.EnvVar{
{
Name: "POD_NAME",
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"},
Key: "key",
Optional: &trueVal,
},
},
},
},
},
masterServiceNs: "nothing",
nilLister: true,
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: "test1",
Name: "test-secret",
},
Data: map[string][]byte{
"a": []byte("b"),
},
},
expectedEnvs: nil,
},
{ {
name: "configmap", name: "configmap",
ns: "test1", ns: "test1",
@ -722,6 +824,19 @@ func TestMakeEnvironmentVariables(t *testing.T) {
masterServiceNs: "nothing", masterServiceNs: "nothing",
expectedError: true, expectedError: true,
}, },
{
name: "configmap_missing_optional",
ns: "test",
container: &v1.Container{
EnvFrom: []v1.EnvFromSource{
{ConfigMapRef: &v1.ConfigMapEnvSource{
Optional: &trueVal,
LocalObjectReference: v1.LocalObjectReference{Name: "missing-config-map"}}},
},
},
masterServiceNs: "nothing",
expectedEnvs: nil,
},
{ {
name: "configmap_invalid_keys", name: "configmap_invalid_keys",
ns: "test1", ns: "test1",
@ -876,6 +991,19 @@ func TestMakeEnvironmentVariables(t *testing.T) {
masterServiceNs: "nothing", masterServiceNs: "nothing",
expectedError: true, expectedError: true,
}, },
{
name: "secret_missing_optional",
ns: "test",
container: &v1.Container{
EnvFrom: []v1.EnvFromSource{
{SecretRef: &v1.SecretEnvSource{
LocalObjectReference: v1.LocalObjectReference{Name: "missing-secret"},
Optional: &trueVal}},
},
},
masterServiceNs: "nothing",
expectedEnvs: nil,
},
{ {
name: "secret_invalid_keys", name: "secret_invalid_keys",
ns: "test1", ns: "test1",
@ -940,10 +1068,17 @@ func TestMakeEnvironmentVariables(t *testing.T) {
testKubelet.fakeKubeClient.AddReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) { testKubelet.fakeKubeClient.AddReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) {
var err error var err error
if tc.configMap == nil { if tc.configMap == nil {
err = errors.New("no configmap defined") err = apierrors.NewNotFound(action.GetResource().GroupResource(), "configmap-name")
} }
return true, tc.configMap, err return true, tc.configMap, err
}) })
testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
var err error
if tc.secret == nil {
err = apierrors.NewNotFound(action.GetResource().GroupResource(), "secret-name")
}
return true, tc.secret, err
})
testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) { testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
var err error var err error

View File

@ -173,8 +173,12 @@ func newTestKubeletWithImageList(
kubelet.cadvisor = mockCadvisor kubelet.cadvisor = mockCadvisor
fakeMirrorClient := podtest.NewFakeMirrorClient() fakeMirrorClient := podtest.NewFakeMirrorClient()
fakeSecretManager := secret.NewFakeManager() secretManager, err := secret.NewSimpleSecretManager(kubelet.kubeClient)
kubelet.podManager = kubepod.NewBasicPodManager(fakeMirrorClient, fakeSecretManager) if err != nil {
t.Fatalf("can't create a secret manager: %v", err)
}
kubelet.secretManager = secretManager
kubelet.podManager = kubepod.NewBasicPodManager(fakeMirrorClient, kubelet.secretManager)
kubelet.statusManager = status.NewManager(fakeKubeClient, kubelet.podManager) kubelet.statusManager = status.NewManager(fakeKubeClient, kubelet.podManager)
kubelet.containerRefManager = kubecontainer.NewRefManager() kubelet.containerRefManager = kubecontainer.NewRefManager()
diskSpaceManager, err := newDiskSpaceManager(mockCadvisor, DiskSpacePolicy{}) diskSpaceManager, err := newDiskSpaceManager(mockCadvisor, DiskSpacePolicy{})
@ -249,7 +253,7 @@ func newTestKubeletWithImageList(
plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil} plug := &volumetest.FakeVolumePlugin{PluginName: "fake", Host: nil}
kubelet.volumePluginMgr, err = kubelet.volumePluginMgr, err =
NewInitializedVolumePluginMgr(kubelet, fakeSecretManager, []volume.VolumePlugin{plug}) NewInitializedVolumePluginMgr(kubelet, kubelet.secretManager, []volume.VolumePlugin{plug})
require.NoError(t, err, "Failed to initialize VolumePluginMgr") require.NoError(t, err, "Failed to initialize VolumePluginMgr")
kubelet.mounter = &mount.FakeMounter{} kubelet.mounter = &mount.FakeMounter{}

View File

@ -23,6 +23,7 @@ go_library(
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/types", "//vendor:k8s.io/apimachinery/pkg/types",
], ],

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
@ -170,10 +171,19 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
return fmt.Errorf("Cannot setup configMap volume %v because kube client is not configured", b.volName) return fmt.Errorf("Cannot setup configMap volume %v because kube client is not configured", b.volName)
} }
optional := b.source.Optional != nil && *b.source.Optional
configMap, err := kubeClient.Core().ConfigMaps(b.pod.Namespace).Get(b.source.Name, metav1.GetOptions{}) configMap, err := kubeClient.Core().ConfigMaps(b.pod.Namespace).Get(b.source.Name, metav1.GetOptions{})
if err != nil { if err != nil {
glog.Errorf("Couldn't get configMap %v/%v: %v", b.pod.Namespace, b.source.Name, err) if !(errors.IsNotFound(err) && optional) {
return err glog.Errorf("Couldn't get configMap %v/%v: %v", b.pod.Namespace, b.source.Name, err)
return err
}
configMap = &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: b.pod.Namespace,
Name: b.source.Name,
},
}
} }
totalBytes := totalBytes(configMap) totalBytes := totalBytes(configMap)
@ -183,7 +193,7 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
len(configMap.Data), len(configMap.Data),
totalBytes) totalBytes)
payload, err := makePayload(b.source.Items, configMap, b.source.DefaultMode) payload, err := makePayload(b.source.Items, configMap, b.source.DefaultMode, optional)
if err != nil { if err != nil {
return err return err
} }
@ -210,7 +220,7 @@ func (b *configMapVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
return nil return nil
} }
func makePayload(mappings []v1.KeyToPath, configMap *v1.ConfigMap, defaultMode *int32) (map[string]volumeutil.FileProjection, error) { func makePayload(mappings []v1.KeyToPath, configMap *v1.ConfigMap, defaultMode *int32, optional bool) (map[string]volumeutil.FileProjection, error) {
if defaultMode == nil { if defaultMode == nil {
return nil, fmt.Errorf("No defaultMode used, not even the default value for it") return nil, fmt.Errorf("No defaultMode used, not even the default value for it")
} }
@ -228,6 +238,9 @@ func makePayload(mappings []v1.KeyToPath, configMap *v1.ConfigMap, defaultMode *
for _, ktp := range mappings { for _, ktp := range mappings {
content, ok := configMap.Data[ktp.Key] content, ok := configMap.Data[ktp.Key]
if !ok { if !ok {
if optional {
continue
}
err_msg := "references non-existent config key" err_msg := "references non-existent config key"
glog.Errorf(err_msg) glog.Errorf(err_msg)
return nil, fmt.Errorf(err_msg) return nil, fmt.Errorf(err_msg)

View File

@ -43,6 +43,7 @@ func TestMakePayload(t *testing.T) {
mappings []v1.KeyToPath mappings []v1.KeyToPath
configMap *v1.ConfigMap configMap *v1.ConfigMap
mode int32 mode int32
optional bool
payload map[string]util.FileProjection payload map[string]util.FileProjection
success bool success bool
}{ }{
@ -215,10 +216,29 @@ func TestMakePayload(t *testing.T) {
}, },
success: true, success: true,
}, },
{
name: "optional non existent key",
mappings: []v1.KeyToPath{
{
Key: "zab",
Path: "path/to/foo.txt",
},
},
configMap: &v1.ConfigMap{
Data: map[string]string{
"foo": "foo",
"bar": "bar",
},
},
mode: 0644,
optional: true,
payload: map[string]util.FileProjection{},
success: true,
},
} }
for _, tc := range cases { for _, tc := range cases {
actualPayload, err := makePayload(tc.mappings, tc.configMap, &tc.mode) actualPayload, err := makePayload(tc.mappings, tc.configMap, &tc.mode, tc.optional)
if err != nil && tc.success { if err != nil && tc.success {
t.Errorf("%v: unexpected failure making payload: %v", tc.name, err) t.Errorf("%v: unexpected failure making payload: %v", tc.name, err)
continue continue
@ -388,6 +408,143 @@ func TestPluginReboot(t *testing.T) {
doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
} }
func TestPluginOptional(t *testing.T) {
var (
testPodUID = types.UID("test_pod_uid")
testVolumeName = "test_volume_name"
testNamespace = "test_configmap_namespace"
testName = "test_configmap_name"
trueVal = true
volumeSpec = volumeSpec(testVolumeName, testName, 0644)
client = fake.NewSimpleClientset()
pluginMgr = volume.VolumePluginMgr{}
tempDir, host = newTestHost(t, client)
)
volumeSpec.VolumeSource.ConfigMap.Optional = &trueVal
defer os.RemoveAll(tempDir)
pluginMgr.InitPlugins(ProbeVolumePlugins(), host)
plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
if err != nil {
t.Errorf("Can't find the plugin by name")
}
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
if err != nil {
t.Errorf("Failed to make a new Mounter: %v", err)
}
if mounter == nil {
t.Errorf("Got a nil Mounter")
}
vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec))
if err != nil {
t.Errorf("Failed to GetVolumeName: %v", err)
}
if vName != "test_volume_name/test_configmap_name" {
t.Errorf("Got unexpect VolumeName %v", vName)
}
volumePath := mounter.GetPath()
if !strings.HasSuffix(volumePath, fmt.Sprintf("pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name")) {
t.Errorf("Got unexpected path: %s", volumePath)
}
fsGroup := int64(1001)
err = mounter.SetUp(&fsGroup)
if err != nil {
t.Errorf("Failed to setup volume: %v", err)
}
if _, err := os.Stat(volumePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
} else {
t.Errorf("SetUp() failed: %v", err)
}
}
infos, err := ioutil.ReadDir(volumePath)
if err != nil {
t.Fatalf("couldn't find volume path, %s", volumePath)
}
if len(infos) != 0 {
t.Errorf("empty directory, %s, not found", volumePath)
}
doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
}
func TestPluginKeysOptional(t *testing.T) {
var (
testPodUID = types.UID("test_pod_uid")
testVolumeName = "test_volume_name"
testNamespace = "test_configmap_namespace"
testName = "test_configmap_name"
trueVal = true
volumeSpec = volumeSpec(testVolumeName, testName, 0644)
configMap = configMap(testNamespace, testName)
client = fake.NewSimpleClientset(&configMap)
pluginMgr = volume.VolumePluginMgr{}
tempDir, host = newTestHost(t, client)
)
volumeSpec.VolumeSource.ConfigMap.Items = []v1.KeyToPath{
{Key: "data-1", Path: "data-1"},
{Key: "data-2", Path: "data-2"},
{Key: "data-3", Path: "data-3"},
{Key: "missing", Path: "missing"},
}
volumeSpec.VolumeSource.ConfigMap.Optional = &trueVal
defer os.RemoveAll(tempDir)
pluginMgr.InitPlugins(ProbeVolumePlugins(), host)
plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
if err != nil {
t.Errorf("Can't find the plugin by name")
}
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
if err != nil {
t.Errorf("Failed to make a new Mounter: %v", err)
}
if mounter == nil {
t.Errorf("Got a nil Mounter")
}
vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec))
if err != nil {
t.Errorf("Failed to GetVolumeName: %v", err)
}
if vName != "test_volume_name/test_configmap_name" {
t.Errorf("Got unexpect VolumeName %v", vName)
}
volumePath := mounter.GetPath()
if !strings.HasSuffix(volumePath, fmt.Sprintf("pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name")) {
t.Errorf("Got unexpected path: %s", volumePath)
}
fsGroup := int64(1001)
err = mounter.SetUp(&fsGroup)
if err != nil {
t.Errorf("Failed to setup volume: %v", err)
}
if _, err := os.Stat(volumePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
} else {
t.Errorf("SetUp() failed: %v", err)
}
}
doTestConfigMapDataInVolume(volumePath, configMap, t)
doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
}
func volumeSpec(volumeName, configMapName string, defaultMode int32) *v1.Volume { func volumeSpec(volumeName, configMapName string, defaultMode int32) *v1.Volume {
return &v1.Volume{ return &v1.Volume{
Name: volumeName, Name: volumeName,

View File

@ -23,6 +23,8 @@ go_library(
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/types", "//vendor:k8s.io/apimachinery/pkg/types",
], ],
) )

View File

@ -22,6 +22,8 @@ import (
"runtime" "runtime"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
ioutil "k8s.io/kubernetes/pkg/util/io" ioutil "k8s.io/kubernetes/pkg/util/io"
@ -191,10 +193,19 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
return err return err
} }
optional := b.source.Optional != nil && *b.source.Optional
secret, err := b.getSecret(b.pod.Namespace, b.source.SecretName) secret, err := b.getSecret(b.pod.Namespace, b.source.SecretName)
if err != nil { if err != nil {
glog.Errorf("Couldn't get secret %v/%v", b.pod.Namespace, b.source.SecretName) if !(errors.IsNotFound(err) && optional) {
return err glog.Errorf("Couldn't get secret %v/%v", b.pod.Namespace, b.source.SecretName)
return err
}
secret = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: b.pod.Namespace,
Name: b.source.SecretName,
},
}
} }
totalBytes := totalSecretBytes(secret) totalBytes := totalSecretBytes(secret)
@ -204,7 +215,7 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
len(secret.Data), len(secret.Data),
totalBytes) totalBytes)
payload, err := makePayload(b.source.Items, secret, b.source.DefaultMode) payload, err := makePayload(b.source.Items, secret, b.source.DefaultMode, optional)
if err != nil { if err != nil {
return err return err
} }
@ -231,7 +242,7 @@ func (b *secretVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
return nil return nil
} }
func makePayload(mappings []v1.KeyToPath, secret *v1.Secret, defaultMode *int32) (map[string]volumeutil.FileProjection, error) { func makePayload(mappings []v1.KeyToPath, secret *v1.Secret, defaultMode *int32, optional bool) (map[string]volumeutil.FileProjection, error) {
if defaultMode == nil { if defaultMode == nil {
return nil, fmt.Errorf("No defaultMode used, not even the default value for it") return nil, fmt.Errorf("No defaultMode used, not even the default value for it")
} }
@ -249,6 +260,9 @@ func makePayload(mappings []v1.KeyToPath, secret *v1.Secret, defaultMode *int32)
for _, ktp := range mappings { for _, ktp := range mappings {
content, ok := secret.Data[ktp.Key] content, ok := secret.Data[ktp.Key]
if !ok { if !ok {
if optional {
continue
}
err_msg := "references non-existent secret key" err_msg := "references non-existent secret key"
glog.Errorf(err_msg) glog.Errorf(err_msg)
return nil, fmt.Errorf(err_msg) return nil, fmt.Errorf(err_msg)

View File

@ -46,6 +46,7 @@ func TestMakePayload(t *testing.T) {
mappings []v1.KeyToPath mappings []v1.KeyToPath
secret *v1.Secret secret *v1.Secret
mode int32 mode int32
optional bool
payload map[string]util.FileProjection payload map[string]util.FileProjection
success bool success bool
}{ }{
@ -218,10 +219,29 @@ func TestMakePayload(t *testing.T) {
}, },
success: true, success: true,
}, },
{
name: "optional non existent key",
mappings: []v1.KeyToPath{
{
Key: "zab",
Path: "path/to/foo.txt",
},
},
secret: &v1.Secret{
Data: map[string][]byte{
"foo": []byte("foo"),
"bar": []byte("bar"),
},
},
mode: 0644,
optional: true,
payload: map[string]util.FileProjection{},
success: true,
},
} }
for _, tc := range cases { for _, tc := range cases {
actualPayload, err := makePayload(tc.mappings, tc.secret, &tc.mode) actualPayload, err := makePayload(tc.mappings, tc.secret, &tc.mode, tc.optional)
if err != nil && tc.success { if err != nil && tc.success {
t.Errorf("%v: unexpected failure making payload: %v", tc.name, err) t.Errorf("%v: unexpected failure making payload: %v", tc.name, err)
continue continue
@ -398,6 +418,154 @@ func TestPluginReboot(t *testing.T) {
doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
} }
func TestPluginOptional(t *testing.T) {
var (
testPodUID = types.UID("test_pod_uid")
testVolumeName = "test_volume_name"
testNamespace = "test_secret_namespace"
testName = "test_secret_name"
trueVal = true
volumeSpec = volumeSpec(testVolumeName, testName, 0644)
client = fake.NewSimpleClientset()
pluginMgr = volume.VolumePluginMgr{}
rootDir, host = newTestHost(t, client)
)
volumeSpec.Secret.Optional = &trueVal
defer os.RemoveAll(rootDir)
pluginMgr.InitPlugins(ProbeVolumePlugins(), host)
plugin, err := pluginMgr.FindPluginByName(secretPluginName)
if err != nil {
t.Errorf("Can't find the plugin by name")
}
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
if err != nil {
t.Errorf("Failed to make a new Mounter: %v", err)
}
if mounter == nil {
t.Errorf("Got a nil Mounter")
}
volumePath := mounter.GetPath()
if !strings.HasSuffix(volumePath, fmt.Sprintf("pods/test_pod_uid/volumes/kubernetes.io~secret/test_volume_name")) {
t.Errorf("Got unexpected path: %s", volumePath)
}
err = mounter.SetUp(nil)
if err != nil {
t.Errorf("Failed to setup volume: %v", err)
}
if _, err := os.Stat(volumePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
} else {
t.Errorf("SetUp() failed: %v", err)
}
}
// secret volume should create its own empty wrapper path
podWrapperMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid/plugins/kubernetes.io~empty-dir/wrapped_test_volume_name", rootDir)
if _, err := os.Stat(podWrapperMetadataDir); err != nil {
if os.IsNotExist(err) {
t.Errorf("SetUp() failed, empty-dir wrapper path is not created: %s", podWrapperMetadataDir)
} else {
t.Errorf("SetUp() failed: %v", err)
}
}
infos, err := ioutil.ReadDir(volumePath)
if err != nil {
t.Fatalf("couldn't find volume path, %s", volumePath)
}
if len(infos) != 0 {
t.Errorf("empty directory, %s, not found", volumePath)
}
defer doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
}
func TestPluginOptionalKeys(t *testing.T) {
var (
testPodUID = types.UID("test_pod_uid")
testVolumeName = "test_volume_name"
testNamespace = "test_secret_namespace"
testName = "test_secret_name"
trueVal = true
volumeSpec = volumeSpec(testVolumeName, testName, 0644)
secret = secret(testNamespace, testName)
client = fake.NewSimpleClientset(&secret)
pluginMgr = volume.VolumePluginMgr{}
rootDir, host = newTestHost(t, client)
)
volumeSpec.VolumeSource.Secret.Items = []v1.KeyToPath{
{Key: "data-1", Path: "data-1"},
{Key: "data-2", Path: "data-2"},
{Key: "data-3", Path: "data-3"},
{Key: "missing", Path: "missing"},
}
volumeSpec.Secret.Optional = &trueVal
defer os.RemoveAll(rootDir)
pluginMgr.InitPlugins(ProbeVolumePlugins(), host)
plugin, err := pluginMgr.FindPluginByName(secretPluginName)
if err != nil {
t.Errorf("Can't find the plugin by name")
}
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
if err != nil {
t.Errorf("Failed to make a new Mounter: %v", err)
}
if mounter == nil {
t.Errorf("Got a nil Mounter")
}
volumePath := mounter.GetPath()
if !strings.HasSuffix(volumePath, fmt.Sprintf("pods/test_pod_uid/volumes/kubernetes.io~secret/test_volume_name")) {
t.Errorf("Got unexpected path: %s", volumePath)
}
err = mounter.SetUp(nil)
if err != nil {
t.Errorf("Failed to setup volume: %v", err)
}
if _, err := os.Stat(volumePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
} else {
t.Errorf("SetUp() failed: %v", err)
}
}
// secret volume should create its own empty wrapper path
podWrapperMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid/plugins/kubernetes.io~empty-dir/wrapped_test_volume_name", rootDir)
if _, err := os.Stat(podWrapperMetadataDir); err != nil {
if os.IsNotExist(err) {
t.Errorf("SetUp() failed, empty-dir wrapper path is not created: %s", podWrapperMetadataDir)
} else {
t.Errorf("SetUp() failed: %v", err)
}
}
doTestSecretDataInVolume(volumePath, secret, t)
defer doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
// Metrics only supported on linux
metrics, err := mounter.GetMetrics()
if runtime.GOOS == "linux" {
assert.NotEmpty(t, metrics)
assert.NoError(t, err)
} else {
t.Skipf("Volume metrics not supported on %s", runtime.GOOS)
}
}
func volumeSpec(volumeName, secretName string, defaultMode int32) *v1.Volume { func volumeSpec(volumeName, secretName string, defaultMode int32) *v1.Volume {
return &v1.Volume{ return &v1.Volume{
Name: volumeName, Name: volumeName,

View File

@ -19,6 +19,7 @@ package common
import ( import (
"fmt" "fmt"
"os" "os"
"path"
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -154,6 +155,189 @@ var _ = framework.KubeDescribe("ConfigMap", func() {
Eventually(pollLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-2")) Eventually(pollLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-2"))
}) })
It("optional updates should be reflected in volume [Conformance] [Volume]", func() {
// We may have to wait or a full sync period to elapse before the
// Kubelet projects the update into the volume and the container picks
// it up. This timeout is based on the default Kubelet sync period (1
// minute) plus additional time for fudge factor.
const podLogTimeout = 300 * time.Second
trueVal := true
volumeMountPath := "/etc/configmap-volumes"
deleteName := "cm-test-opt-del-" + string(uuid.NewUUID())
deleteContainerName := "delcm-volume-test"
deleteVolumeName := "deletecm-volume"
deleteConfigMap := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: f.Namespace.Name,
Name: deleteName,
},
Data: map[string]string{
"data-1": "value-1",
},
}
updateName := "cm-test-opt-upd-" + string(uuid.NewUUID())
updateContainerName := "updcm-volume-test"
updateVolumeName := "updatecm-volume"
updateConfigMap := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: f.Namespace.Name,
Name: updateName,
},
Data: map[string]string{
"data-1": "value-1",
},
}
createName := "cm-test-opt-create-" + string(uuid.NewUUID())
createContainerName := "createcm-volume-test"
createVolumeName := "createcm-volume"
createConfigMap := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: f.Namespace.Name,
Name: createName,
},
Data: map[string]string{
"data-1": "value-1",
},
}
By(fmt.Sprintf("Creating configMap with name %s", deleteConfigMap.Name))
var err error
if deleteConfigMap, err = f.ClientSet.Core().ConfigMaps(f.Namespace.Name).Create(deleteConfigMap); err != nil {
framework.Failf("unable to create test configMap %s: %v", deleteConfigMap.Name, err)
}
By(fmt.Sprintf("Creating configMap with name %s", updateConfigMap.Name))
if updateConfigMap, err = f.ClientSet.Core().ConfigMaps(f.Namespace.Name).Create(updateConfigMap); err != nil {
framework.Failf("unable to create test configMap %s: %v", updateConfigMap.Name, err)
}
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-configmaps-" + string(uuid.NewUUID()),
},
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: deleteVolumeName,
VolumeSource: v1.VolumeSource{
ConfigMap: &v1.ConfigMapVolumeSource{
LocalObjectReference: v1.LocalObjectReference{
Name: deleteName,
},
Optional: &trueVal,
},
},
},
{
Name: updateVolumeName,
VolumeSource: v1.VolumeSource{
ConfigMap: &v1.ConfigMapVolumeSource{
LocalObjectReference: v1.LocalObjectReference{
Name: updateName,
},
Optional: &trueVal,
},
},
},
{
Name: createVolumeName,
VolumeSource: v1.VolumeSource{
ConfigMap: &v1.ConfigMapVolumeSource{
LocalObjectReference: v1.LocalObjectReference{
Name: createName,
},
Optional: &trueVal,
},
},
},
},
Containers: []v1.Container{
{
Name: deleteContainerName,
Image: "gcr.io/google_containers/mounttest:0.7",
Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volumes/delete/data-1"},
VolumeMounts: []v1.VolumeMount{
{
Name: deleteVolumeName,
MountPath: path.Join(volumeMountPath, "delete"),
ReadOnly: true,
},
},
},
{
Name: updateContainerName,
Image: "gcr.io/google_containers/mounttest:0.7",
Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volumes/update/data-3"},
VolumeMounts: []v1.VolumeMount{
{
Name: updateVolumeName,
MountPath: path.Join(volumeMountPath, "update"),
ReadOnly: true,
},
},
},
{
Name: createContainerName,
Image: "gcr.io/google_containers/mounttest:0.7",
Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/configmap-volumes/create/data-1"},
VolumeMounts: []v1.VolumeMount{
{
Name: createVolumeName,
MountPath: path.Join(volumeMountPath, "create"),
ReadOnly: true,
},
},
},
},
RestartPolicy: v1.RestartPolicyNever,
},
}
By("Creating the pod")
f.PodClient().CreateSync(pod)
pollCreateLogs := func() (string, error) {
return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, createContainerName)
}
Eventually(pollCreateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/configmap-volumes/create/data-1"))
pollUpdateLogs := func() (string, error) {
return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, updateContainerName)
}
Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/configmap-volumes/update/data-3"))
pollDeleteLogs := func() (string, error) {
return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, deleteContainerName)
}
Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-1"))
By(fmt.Sprintf("Deleting configmap %v", deleteConfigMap.Name))
err = f.ClientSet.Core().ConfigMaps(f.Namespace.Name).Delete(deleteConfigMap.Name, &v1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred(), "Failed to delete configmap %q in namespace %q", deleteConfigMap.Name, f.Namespace.Name)
By(fmt.Sprintf("Updating configmap %v", updateConfigMap.Name))
updateConfigMap.ResourceVersion = "" // to force update
delete(updateConfigMap.Data, "data-1")
updateConfigMap.Data["data-3"] = "value-3"
_, err = f.ClientSet.Core().ConfigMaps(f.Namespace.Name).Update(updateConfigMap)
Expect(err).NotTo(HaveOccurred(), "Failed to update configmap %q in namespace %q", updateConfigMap.Name, f.Namespace.Name)
By(fmt.Sprintf("Creating configMap with name %s", createConfigMap.Name))
if createConfigMap, err = f.ClientSet.Core().ConfigMaps(f.Namespace.Name).Create(createConfigMap); err != nil {
framework.Failf("unable to create test configMap %s: %v", createConfigMap.Name, err)
}
By("waiting to observe update in volume")
Eventually(pollCreateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-1"))
Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-3"))
Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/configmap-volumes/delete/data-1"))
})
It("should be consumable via environment variable [Conformance]", func() { It("should be consumable via environment variable [Conformance]", func() {
name := "configmap-test-" + string(uuid.NewUUID()) name := "configmap-test-" + string(uuid.NewUUID())
configMap := newConfigMap(f, name) configMap := newConfigMap(f, name)

View File

@ -19,6 +19,8 @@ package common
import ( import (
"fmt" "fmt"
"os" "os"
"path"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
@ -26,6 +28,7 @@ import (
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
) )
var _ = framework.KubeDescribe("Secrets", func() { var _ = framework.KubeDescribe("Secrets", func() {
@ -150,6 +153,183 @@ var _ = framework.KubeDescribe("Secrets", func() {
}) })
}) })
It("optional updates should be reflected in volume [Conformance] [Volume]", func() {
// We may have to wait or a full sync period to elapse before the
// Kubelet projects the update into the volume and the container picks
// it up. This timeout is based on the default Kubelet sync period (1
// minute) plus additional time for fudge factor.
const podLogTimeout = 300 * time.Second
trueVal := true
volumeMountPath := "/etc/secret-volumes"
deleteName := "s-test-opt-del-" + string(uuid.NewUUID())
deleteContainerName := "dels-volume-test"
deleteVolumeName := "deletes-volume"
deleteSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: f.Namespace.Name,
Name: deleteName,
},
Data: map[string][]byte{
"data-1": []byte("value-1"),
},
}
updateName := "s-test-opt-upd-" + string(uuid.NewUUID())
updateContainerName := "upds-volume-test"
updateVolumeName := "updates-volume"
updateSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: f.Namespace.Name,
Name: updateName,
},
Data: map[string][]byte{
"data-1": []byte("value-1"),
},
}
createName := "s-test-opt-create-" + string(uuid.NewUUID())
createContainerName := "creates-volume-test"
createVolumeName := "creates-volume"
createSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: f.Namespace.Name,
Name: createName,
},
Data: map[string][]byte{
"data-1": []byte("value-1"),
},
}
By(fmt.Sprintf("Creating secret with name %s", deleteSecret.Name))
var err error
if deleteSecret, err = f.ClientSet.Core().Secrets(f.Namespace.Name).Create(deleteSecret); err != nil {
framework.Failf("unable to create test secret %s: %v", deleteSecret.Name, err)
}
By(fmt.Sprintf("Creating secret with name %s", updateSecret.Name))
if updateSecret, err = f.ClientSet.Core().Secrets(f.Namespace.Name).Create(updateSecret); err != nil {
framework.Failf("unable to create test secret %s: %v", updateSecret.Name, err)
}
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-secrets-" + string(uuid.NewUUID()),
},
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: deleteVolumeName,
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: deleteName,
Optional: &trueVal,
},
},
},
{
Name: updateVolumeName,
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: updateName,
Optional: &trueVal,
},
},
},
{
Name: createVolumeName,
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: createName,
Optional: &trueVal,
},
},
},
},
Containers: []v1.Container{
{
Name: deleteContainerName,
Image: "gcr.io/google_containers/mounttest:0.7",
Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/secret-volumes/delete/data-1"},
VolumeMounts: []v1.VolumeMount{
{
Name: deleteVolumeName,
MountPath: path.Join(volumeMountPath, "delete"),
ReadOnly: true,
},
},
},
{
Name: updateContainerName,
Image: "gcr.io/google_containers/mounttest:0.7",
Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/secret-volumes/update/data-3"},
VolumeMounts: []v1.VolumeMount{
{
Name: updateVolumeName,
MountPath: path.Join(volumeMountPath, "update"),
ReadOnly: true,
},
},
},
{
Name: createContainerName,
Image: "gcr.io/google_containers/mounttest:0.7",
Command: []string{"/mt", "--break_on_expected_content=false", "--retry_time=120", "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
VolumeMounts: []v1.VolumeMount{
{
Name: createVolumeName,
MountPath: path.Join(volumeMountPath, "create"),
ReadOnly: true,
},
},
},
},
RestartPolicy: v1.RestartPolicyNever,
},
}
By("Creating the pod")
f.PodClient().CreateSync(pod)
pollCreateLogs := func() (string, error) {
return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, createContainerName)
}
Eventually(pollCreateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/secret-volumes/create/data-1"))
pollUpdateLogs := func() (string, error) {
return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, updateContainerName)
}
Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/secret-volumes/update/data-3"))
pollDeleteLogs := func() (string, error) {
return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, deleteContainerName)
}
Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-1"))
By(fmt.Sprintf("Deleting secret %v", deleteSecret.Name))
err = f.ClientSet.Core().Secrets(f.Namespace.Name).Delete(deleteSecret.Name, &v1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred(), "Failed to delete secret %q in namespace %q", deleteSecret.Name, f.Namespace.Name)
By(fmt.Sprintf("Updating secret %v", updateSecret.Name))
updateSecret.ResourceVersion = "" // to force update
delete(updateSecret.Data, "data-1")
updateSecret.Data["data-3"] = []byte("value-3")
_, err = f.ClientSet.Core().Secrets(f.Namespace.Name).Update(updateSecret)
Expect(err).NotTo(HaveOccurred(), "Failed to update secret %q in namespace %q", updateSecret.Name, f.Namespace.Name)
By(fmt.Sprintf("Creating secret with name %s", createSecret.Name))
if createSecret, err = f.ClientSet.Core().Secrets(f.Namespace.Name).Create(createSecret); err != nil {
framework.Failf("unable to create test secret %s: %v", createSecret.Name, err)
}
By("waiting to observe update in volume")
Eventually(pollCreateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-1"))
Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-3"))
Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/secret-volumes/delete/data-1"))
})
It("should be consumable from pods in env vars [Conformance]", func() { It("should be consumable from pods in env vars [Conformance]", func() {
name := "secret-test-" + string(uuid.NewUUID()) name := "secret-test-" + string(uuid.NewUUID())
secret := secretForTest(f.Namespace.Name, name) secret := secretForTest(f.Namespace.Name, name)