mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 10:18:13 +00:00 
			
		
		
		
	Merge pull request #39446 from fraenkel/env_secrets
Automatic merge from submit-queue (batch tested with PRs 39446, 40023, 36853) Create environment variables from secrets Allow environment variables to be populated from entire secrets. **Release note**: ```release-note Populate environment variables from a secrets. ```
This commit is contained in:
		| @@ -35499,6 +35499,10 @@ | ||||
|      "prefix": { | ||||
|       "description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.", | ||||
|       "type": "string" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "description": "The Secret to select from", | ||||
|       "$ref": "#/definitions/v1.SecretEnvSource" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
| @@ -38203,6 +38207,15 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretEnvSource": { | ||||
|     "description": "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.", | ||||
|     "properties": { | ||||
|      "name": { | ||||
|       "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", | ||||
|       "type": "string" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretKeySelector": { | ||||
|     "description": "SecretKeySelector selects a key of a Secret.", | ||||
|     "required": [ | ||||
|   | ||||
| @@ -2257,6 +2257,10 @@ | ||||
|      "configMapRef": { | ||||
|       "$ref": "v1.ConfigMapEnvSource", | ||||
|       "description": "The ConfigMap to select from" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "$ref": "v1.SecretEnvSource", | ||||
|       "description": "The Secret to select from" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
| @@ -2270,6 +2274,16 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretEnvSource": { | ||||
|     "id": "v1.SecretEnvSource", | ||||
|     "description": "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.", | ||||
|     "properties": { | ||||
|      "name": { | ||||
|       "type": "string", | ||||
|       "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.EnvVar": { | ||||
|     "id": "v1.EnvVar", | ||||
|     "description": "EnvVar represents an environment variable present in a Container.", | ||||
|   | ||||
| @@ -2262,6 +2262,10 @@ | ||||
|      "configMapRef": { | ||||
|       "$ref": "v1.ConfigMapEnvSource", | ||||
|       "description": "The ConfigMap to select from" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "$ref": "v1.SecretEnvSource", | ||||
|       "description": "The Secret to select from" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
| @@ -2275,6 +2279,16 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretEnvSource": { | ||||
|     "id": "v1.SecretEnvSource", | ||||
|     "description": "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.", | ||||
|     "properties": { | ||||
|      "name": { | ||||
|       "type": "string", | ||||
|       "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.EnvVar": { | ||||
|     "id": "v1.EnvVar", | ||||
|     "description": "EnvVar represents an environment variable present in a Container.", | ||||
|   | ||||
| @@ -8634,6 +8634,10 @@ | ||||
|      "configMapRef": { | ||||
|       "$ref": "v1.ConfigMapEnvSource", | ||||
|       "description": "The ConfigMap to select from" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "$ref": "v1.SecretEnvSource", | ||||
|       "description": "The Secret to select from" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
| @@ -8647,6 +8651,16 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretEnvSource": { | ||||
|     "id": "v1.SecretEnvSource", | ||||
|     "description": "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.", | ||||
|     "properties": { | ||||
|      "name": { | ||||
|       "type": "string", | ||||
|       "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.EnvVar": { | ||||
|     "id": "v1.EnvVar", | ||||
|     "description": "EnvVar represents an environment variable present in a Container.", | ||||
|   | ||||
| @@ -18726,6 +18726,10 @@ | ||||
|      "configMapRef": { | ||||
|       "$ref": "v1.ConfigMapEnvSource", | ||||
|       "description": "The ConfigMap to select from" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "$ref": "v1.SecretEnvSource", | ||||
|       "description": "The Secret to select from" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
| @@ -18739,6 +18743,16 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretEnvSource": { | ||||
|     "id": "v1.SecretEnvSource", | ||||
|     "description": "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.", | ||||
|     "properties": { | ||||
|      "name": { | ||||
|       "type": "string", | ||||
|       "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.EnvVar": { | ||||
|     "id": "v1.EnvVar", | ||||
|     "description": "EnvVar represents an environment variable present in a Container.", | ||||
|   | ||||
| @@ -1512,6 +1512,43 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_secretenvsource">v1.SecretEnvSource</h3> | ||||
| <div class="paragraph"> | ||||
| <p>SecretEnvSource selects a Secret to populate the environment variables with.</p> | ||||
| </div> | ||||
| <div class="paragraph"> | ||||
| <p>The contents of the target Secret’s Data field will represent the key-value pairs as environment variables.</p> | ||||
| </div> | ||||
| <table class="tableblock frame-all grid-all" style="width:100%; "> | ||||
| <colgroup> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;">  | ||||
| </colgroup> | ||||
| <thead> | ||||
| <tr> | ||||
| <th class="tableblock halign-left valign-top">Name</th> | ||||
| <th class="tableblock halign-left valign-top">Description</th> | ||||
| <th class="tableblock halign-left valign-top">Required</th> | ||||
| <th class="tableblock halign-left valign-top">Schema</th> | ||||
| <th class="tableblock halign-left valign-top">Default</th> | ||||
| </tr> | ||||
| </thead> | ||||
| <tbody> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Name of the referent. More info: <a href="http://kubernetes.io/docs/user-guide/identifiers#names">http://kubernetes.io/docs/user-guide/identifiers#names</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_statusdetails">v1.StatusDetails</h3> | ||||
| @@ -2555,6 +2592,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"><a href="#_v1_configmapenvsource">v1.ConfigMapEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">secretRef</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">The Secret to select from</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_secretenvsource">v1.SecretEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| @@ -4967,7 +5011,7 @@ Examples:<br> | ||||
| </div> | ||||
| <div id="footer"> | ||||
| <div id="footer-text"> | ||||
| Last updated 2017-01-18 15:32:06 UTC | ||||
| Last updated 2017-01-19 19:02:01 UTC | ||||
| </div> | ||||
| </div> | ||||
| </body> | ||||
|   | ||||
| @@ -1416,6 +1416,43 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_secretenvsource">v1.SecretEnvSource</h3> | ||||
| <div class="paragraph"> | ||||
| <p>SecretEnvSource selects a Secret to populate the environment variables with.</p> | ||||
| </div> | ||||
| <div class="paragraph"> | ||||
| <p>The contents of the target Secret’s Data field will represent the key-value pairs as environment variables.</p> | ||||
| </div> | ||||
| <table class="tableblock frame-all grid-all" style="width:100%; "> | ||||
| <colgroup> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;">  | ||||
| </colgroup> | ||||
| <thead> | ||||
| <tr> | ||||
| <th class="tableblock halign-left valign-top">Name</th> | ||||
| <th class="tableblock halign-left valign-top">Description</th> | ||||
| <th class="tableblock halign-left valign-top">Required</th> | ||||
| <th class="tableblock halign-left valign-top">Schema</th> | ||||
| <th class="tableblock halign-left valign-top">Default</th> | ||||
| </tr> | ||||
| </thead> | ||||
| <tbody> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Name of the referent. More info: <a href="http://kubernetes.io/docs/user-guide/identifiers#names">http://kubernetes.io/docs/user-guide/identifiers#names</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_statusdetails">v1.StatusDetails</h3> | ||||
| @@ -2466,6 +2503,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"><a href="#_v1_configmapenvsource">v1.ConfigMapEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">secretRef</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">The Secret to select from</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_secretenvsource">v1.SecretEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| @@ -4899,7 +4943,7 @@ Examples:<br> | ||||
| </div> | ||||
| <div id="footer"> | ||||
| <div id="footer-text"> | ||||
| Last updated 2017-01-18 15:32:28 UTC | ||||
| Last updated 2017-01-19 19:02:17 UTC | ||||
| </div> | ||||
| </div> | ||||
| </body> | ||||
|   | ||||
| @@ -1663,6 +1663,43 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_secretenvsource">v1.SecretEnvSource</h3> | ||||
| <div class="paragraph"> | ||||
| <p>SecretEnvSource selects a Secret to populate the environment variables with.</p> | ||||
| </div> | ||||
| <div class="paragraph"> | ||||
| <p>The contents of the target Secret’s Data field will represent the key-value pairs as environment variables.</p> | ||||
| </div> | ||||
| <table class="tableblock frame-all grid-all" style="width:100%; "> | ||||
| <colgroup> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;">  | ||||
| </colgroup> | ||||
| <thead> | ||||
| <tr> | ||||
| <th class="tableblock halign-left valign-top">Name</th> | ||||
| <th class="tableblock halign-left valign-top">Description</th> | ||||
| <th class="tableblock halign-left valign-top">Required</th> | ||||
| <th class="tableblock halign-left valign-top">Schema</th> | ||||
| <th class="tableblock halign-left valign-top">Default</th> | ||||
| </tr> | ||||
| </thead> | ||||
| <tbody> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Name of the referent. More info: <a href="http://kubernetes.io/docs/user-guide/identifiers#names">http://kubernetes.io/docs/user-guide/identifiers#names</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_capabilities">v1.Capabilities</h3> | ||||
| @@ -2406,6 +2443,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"><a href="#_v1_configmapenvsource">v1.ConfigMapEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">secretRef</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">The Secret to select from</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_secretenvsource">v1.SecretEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| @@ -7516,7 +7560,7 @@ Both these may change in the future. Incoming requests are matched against the h | ||||
| </div> | ||||
| <div id="footer"> | ||||
| <div id="footer-text"> | ||||
| Last updated 2017-01-18 15:32:45 UTC | ||||
| Last updated 2017-01-19 19:02:29 UTC | ||||
| </div> | ||||
| </div> | ||||
| </body> | ||||
|   | ||||
| @@ -1704,6 +1704,43 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_secretenvsource">v1.SecretEnvSource</h3> | ||||
| <div class="paragraph"> | ||||
| <p>SecretEnvSource selects a Secret to populate the environment variables with.</p> | ||||
| </div> | ||||
| <div class="paragraph"> | ||||
| <p>The contents of the target Secret’s Data field will represent the key-value pairs as environment variables.</p> | ||||
| </div> | ||||
| <table class="tableblock frame-all grid-all" style="width:100%; "> | ||||
| <colgroup> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;">  | ||||
| </colgroup> | ||||
| <thead> | ||||
| <tr> | ||||
| <th class="tableblock halign-left valign-top">Name</th> | ||||
| <th class="tableblock halign-left valign-top">Description</th> | ||||
| <th class="tableblock halign-left valign-top">Required</th> | ||||
| <th class="tableblock halign-left valign-top">Schema</th> | ||||
| <th class="tableblock halign-left valign-top">Default</th> | ||||
| </tr> | ||||
| </thead> | ||||
| <tbody> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Name of the referent. More info: <a href="http://kubernetes.io/docs/user-guide/identifiers#names">http://kubernetes.io/docs/user-guide/identifiers#names</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_scalestatus">v1.ScaleStatus</h3> | ||||
| @@ -2550,6 +2587,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"><a href="#_v1_configmapenvsource">v1.ConfigMapEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">secretRef</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">The Secret to select from</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_secretenvsource">v1.SecretEnvSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| @@ -9143,7 +9187,7 @@ Examples:<br> | ||||
| </div> | ||||
| <div id="footer"> | ||||
| <div id="footer-text"> | ||||
| Last updated 2017-01-18 15:31:58 UTC | ||||
| Last updated 2017-01-19 19:01:55 UTC | ||||
| </div> | ||||
| </div> | ||||
| </body> | ||||
|   | ||||
| @@ -10101,6 +10101,10 @@ | ||||
|      "prefix": { | ||||
|       "description": "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.", | ||||
|       "type": "string" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "description": "The Secret to select from", | ||||
|       "$ref": "#/definitions/v1.SecretEnvSource" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
| @@ -11598,6 +11602,15 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretEnvSource": { | ||||
|     "description": "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.", | ||||
|     "properties": { | ||||
|      "name": { | ||||
|       "description": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", | ||||
|       "type": "string" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.SecretKeySelector": { | ||||
|     "description": "SecretKeySelector selects a key of a Secret.", | ||||
|     "required": [ | ||||
|   | ||||
| @@ -386,11 +386,16 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz | ||||
| 			} | ||||
| 			if c.RandBool() { | ||||
| 				c.Fuzz(&ev.ConfigMapRef) | ||||
| 			} else { | ||||
| 				c.Fuzz(&ev.SecretRef) | ||||
| 			} | ||||
| 		}, | ||||
| 		func(cm *api.ConfigMapEnvSource, c fuzz.Continue) { | ||||
| 			c.FuzzNoCustom(cm) // fuzz self without calling this function again | ||||
| 		}, | ||||
| 		func(s *api.SecretEnvSource, c fuzz.Continue) { | ||||
| 			c.FuzzNoCustom(s) // fuzz self without calling this function again | ||||
| 		}, | ||||
| 		func(sc *api.SecurityContext, c fuzz.Continue) { | ||||
| 			c.FuzzNoCustom(sc) // fuzz self without calling this function again | ||||
| 			if c.RandBool() { | ||||
|   | ||||
| @@ -1142,6 +1142,9 @@ type EnvFromSource struct { | ||||
| 	// The ConfigMap to select from. | ||||
| 	//+optional | ||||
| 	ConfigMapRef *ConfigMapEnvSource | ||||
| 	// The Secret to select from. | ||||
| 	//+optional | ||||
| 	SecretRef *SecretEnvSource | ||||
| } | ||||
|  | ||||
| // ConfigMapEnvSource selects a ConfigMap to populate the environment | ||||
| @@ -1154,6 +1157,16 @@ type ConfigMapEnvSource struct { | ||||
| 	LocalObjectReference | ||||
| } | ||||
|  | ||||
| // SecretEnvSource selects a Secret to populate the environment | ||||
| // variables with. | ||||
| // | ||||
| // The contents of the target Secret's Data field will represent the | ||||
| // key-value pairs as environment variables. | ||||
| type SecretEnvSource struct { | ||||
| 	// The Secret to select from. | ||||
| 	LocalObjectReference | ||||
| } | ||||
|  | ||||
| // HTTPHeader describes a custom header to be used in HTTP probes | ||||
| type HTTPHeader struct { | ||||
| 	// The header field name | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -799,6 +799,10 @@ message EnvFromSource { | ||||
|   // The ConfigMap to select from | ||||
|   // +optional | ||||
|   optional ConfigMapEnvSource configMapRef = 2; | ||||
| 
 | ||||
|   // The Secret to select from | ||||
|   // +optional | ||||
|   optional SecretEnvSource secretRef = 3; | ||||
| } | ||||
| 
 | ||||
| // EnvVar represents an environment variable present in a Container. | ||||
| @@ -3067,6 +3071,16 @@ message Secret { | ||||
|   optional string type = 3; | ||||
| } | ||||
| 
 | ||||
| // SecretEnvSource selects a Secret to populate the environment | ||||
| // variables with. | ||||
| //  | ||||
| // The contents of the target Secret's Data field will represent the | ||||
| // key-value pairs as environment variables. | ||||
| message SecretEnvSource { | ||||
|   // The Secret to select from. | ||||
|   optional LocalObjectReference localObjectReference = 1; | ||||
| } | ||||
| 
 | ||||
| // SecretKeySelector selects a key of a Secret. | ||||
| message SecretKeySelector { | ||||
|   // The name of the secret in the pod's namespace to select from. | ||||
|   | ||||
| @@ -19828,14 +19828,15 @@ func (x *EnvFromSource) CodecEncodeSelf(e *codec1978.Encoder) { | ||||
| 		} else { | ||||
| 			yysep2 := !z.EncBinary() | ||||
| 			yy2arr2 := z.EncBasicHandle().StructToArray | ||||
| 			var yyq2 [2]bool | ||||
| 			var yyq2 [3]bool | ||||
| 			_, _, _ = yysep2, yyq2, yy2arr2 | ||||
| 			const yyr2 bool = false | ||||
| 			yyq2[0] = x.Prefix != "" | ||||
| 			yyq2[1] = x.ConfigMapRef != nil | ||||
| 			yyq2[2] = x.SecretRef != nil | ||||
| 			var yynn2 int | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				r.EncodeArrayStart(2) | ||||
| 				r.EncodeArrayStart(3) | ||||
| 			} else { | ||||
| 				yynn2 = 0 | ||||
| 				for _, b := range yyq2 { | ||||
| @@ -19894,6 +19895,29 @@ func (x *EnvFromSource) CodecEncodeSelf(e *codec1978.Encoder) { | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[2] { | ||||
| 					if x.SecretRef == nil { | ||||
| 						r.EncodeNil() | ||||
| 					} else { | ||||
| 						x.SecretRef.CodecEncodeSelf(e) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeNil() | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[2] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("secretRef")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					if x.SecretRef == nil { | ||||
| 						r.EncodeNil() | ||||
| 					} else { | ||||
| 						x.SecretRef.CodecEncodeSelf(e) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 			} else { | ||||
| @@ -19978,6 +20002,17 @@ func (x *EnvFromSource) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { | ||||
| 				} | ||||
| 				x.ConfigMapRef.CodecDecodeSelf(d) | ||||
| 			} | ||||
| 		case "secretRef": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				if x.SecretRef != nil { | ||||
| 					x.SecretRef = nil | ||||
| 				} | ||||
| 			} else { | ||||
| 				if x.SecretRef == nil { | ||||
| 					x.SecretRef = new(SecretEnvSource) | ||||
| 				} | ||||
| 				x.SecretRef.CodecDecodeSelf(d) | ||||
| 			} | ||||
| 		default: | ||||
| 			z.DecStructFieldNotFound(-1, yys3) | ||||
| 		} // end switch yys3 | ||||
| @@ -19989,16 +20024,16 @@ func (x *EnvFromSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	var yyj7 int | ||||
| 	var yyb7 bool | ||||
| 	var yyhl7 bool = l >= 0 | ||||
| 	yyj7++ | ||||
| 	if yyhl7 { | ||||
| 		yyb7 = yyj7 > l | ||||
| 	var yyj8 int | ||||
| 	var yyb8 bool | ||||
| 	var yyhl8 bool = l >= 0 | ||||
| 	yyj8++ | ||||
| 	if yyhl8 { | ||||
| 		yyb8 = yyj8 > l | ||||
| 	} else { | ||||
| 		yyb7 = r.CheckBreak() | ||||
| 		yyb8 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb7 { | ||||
| 	if yyb8 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| @@ -20006,21 +20041,21 @@ func (x *EnvFromSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.Prefix = "" | ||||
| 	} else { | ||||
| 		yyv8 := &x.Prefix | ||||
| 		yym9 := z.DecBinary() | ||||
| 		_ = yym9 | ||||
| 		yyv9 := &x.Prefix | ||||
| 		yym10 := z.DecBinary() | ||||
| 		_ = yym10 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*string)(yyv8)) = r.DecodeString() | ||||
| 			*((*string)(yyv9)) = r.DecodeString() | ||||
| 		} | ||||
| 	} | ||||
| 	yyj7++ | ||||
| 	if yyhl7 { | ||||
| 		yyb7 = yyj7 > l | ||||
| 	yyj8++ | ||||
| 	if yyhl8 { | ||||
| 		yyb8 = yyj8 > l | ||||
| 	} else { | ||||
| 		yyb7 = r.CheckBreak() | ||||
| 		yyb8 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb7 { | ||||
| 	if yyb8 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| @@ -20035,18 +20070,39 @@ func (x *EnvFromSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { | ||||
| 		} | ||||
| 		x.ConfigMapRef.CodecDecodeSelf(d) | ||||
| 	} | ||||
| 	for { | ||||
| 		yyj7++ | ||||
| 		if yyhl7 { | ||||
| 			yyb7 = yyj7 > l | ||||
| 		} else { | ||||
| 			yyb7 = r.CheckBreak() | ||||
| 	yyj8++ | ||||
| 	if yyhl8 { | ||||
| 		yyb8 = yyj8 > l | ||||
| 	} else { | ||||
| 		yyb8 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb8 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		if x.SecretRef != nil { | ||||
| 			x.SecretRef = nil | ||||
| 		} | ||||
| 		if yyb7 { | ||||
| 	} else { | ||||
| 		if x.SecretRef == nil { | ||||
| 			x.SecretRef = new(SecretEnvSource) | ||||
| 		} | ||||
| 		x.SecretRef.CodecDecodeSelf(d) | ||||
| 	} | ||||
| 	for { | ||||
| 		yyj8++ | ||||
| 		if yyhl8 { | ||||
| 			yyb8 = yyj8 > l | ||||
| 		} else { | ||||
| 			yyb8 = r.CheckBreak() | ||||
| 		} | ||||
| 		if yyb8 { | ||||
| 			break | ||||
| 		} | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 		z.DecStructFieldNotFound(yyj7-1, "") | ||||
| 		z.DecStructFieldNotFound(yyj8-1, "") | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| } | ||||
| @@ -20232,6 +20288,187 @@ func (x *ConfigMapEnvSource) codecDecodeSelfFromArray(l int, d *codec1978.Decode | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *SecretEnvSource) CodecEncodeSelf(e *codec1978.Encoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperEncoder(e) | ||||
| 	_, _, _ = h, z, r | ||||
| 	if x == nil { | ||||
| 		r.EncodeNil() | ||||
| 	} else { | ||||
| 		yym1 := z.EncBinary() | ||||
| 		_ = yym1 | ||||
| 		if false { | ||||
| 		} else if z.HasExtensions() && z.EncExt(x) { | ||||
| 		} else { | ||||
| 			yysep2 := !z.EncBinary() | ||||
| 			yy2arr2 := z.EncBasicHandle().StructToArray | ||||
| 			var yyq2 [1]bool | ||||
| 			_, _, _ = yysep2, yyq2, yy2arr2 | ||||
| 			const yyr2 bool = false | ||||
| 			yyq2[0] = x.Name != "" | ||||
| 			var yynn2 int | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				r.EncodeArrayStart(1) | ||||
| 			} else { | ||||
| 				yynn2 = 0 | ||||
| 				for _, b := range yyq2 { | ||||
| 					if b { | ||||
| 						yynn2++ | ||||
| 					} | ||||
| 				} | ||||
| 				r.EncodeMapStart(yynn2) | ||||
| 				yynn2 = 0 | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[0] { | ||||
| 					yym4 := z.EncBinary() | ||||
| 					_ = yym4 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Name)) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeString(codecSelferC_UTF81234, "") | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[0] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("name")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					yym5 := z.EncBinary() | ||||
| 					_ = yym5 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Name)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 			} else { | ||||
| 				z.EncSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (x *SecretEnvSource) CodecDecodeSelf(d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	yym1 := z.DecBinary() | ||||
| 	_ = yym1 | ||||
| 	if false { | ||||
| 	} else if z.HasExtensions() && z.DecExt(x) { | ||||
| 	} else { | ||||
| 		yyct2 := r.ContainerType() | ||||
| 		if yyct2 == codecSelferValueTypeMap1234 { | ||||
| 			yyl2 := r.ReadMapStart() | ||||
| 			if yyl2 == 0 { | ||||
| 				z.DecSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| 			} else { | ||||
| 				x.codecDecodeSelfFromMap(yyl2, d) | ||||
| 			} | ||||
| 		} else if yyct2 == codecSelferValueTypeArray1234 { | ||||
| 			yyl2 := r.ReadArrayStart() | ||||
| 			if yyl2 == 0 { | ||||
| 				z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 			} else { | ||||
| 				x.codecDecodeSelfFromArray(yyl2, d) | ||||
| 			} | ||||
| 		} else { | ||||
| 			panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (x *SecretEnvSource) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	var yys3Slc = z.DecScratchBuffer() // default slice to decode into | ||||
| 	_ = yys3Slc | ||||
| 	var yyhl3 bool = l >= 0 | ||||
| 	for yyj3 := 0; ; yyj3++ { | ||||
| 		if yyhl3 { | ||||
| 			if yyj3 >= l { | ||||
| 				break | ||||
| 			} | ||||
| 		} else { | ||||
| 			if r.CheckBreak() { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		z.DecSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 		yys3Slc = r.DecodeBytes(yys3Slc, true, true) | ||||
| 		yys3 := string(yys3Slc) | ||||
| 		z.DecSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 		switch yys3 { | ||||
| 		case "name": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.Name = "" | ||||
| 			} else { | ||||
| 				yyv4 := &x.Name | ||||
| 				yym5 := z.DecBinary() | ||||
| 				_ = yym5 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					*((*string)(yyv4)) = r.DecodeString() | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			z.DecStructFieldNotFound(-1, yys3) | ||||
| 		} // end switch yys3 | ||||
| 	} // end for yyj3 | ||||
| 	z.DecSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *SecretEnvSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	var yyj6 int | ||||
| 	var yyb6 bool | ||||
| 	var yyhl6 bool = l >= 0 | ||||
| 	yyj6++ | ||||
| 	if yyhl6 { | ||||
| 		yyb6 = yyj6 > l | ||||
| 	} else { | ||||
| 		yyb6 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb6 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.Name = "" | ||||
| 	} else { | ||||
| 		yyv7 := &x.Name | ||||
| 		yym8 := z.DecBinary() | ||||
| 		_ = yym8 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*string)(yyv7)) = r.DecodeString() | ||||
| 		} | ||||
| 	} | ||||
| 	for { | ||||
| 		yyj6++ | ||||
| 		if yyhl6 { | ||||
| 			yyb6 = yyj6 > l | ||||
| 		} else { | ||||
| 			yyb6 = r.CheckBreak() | ||||
| 		} | ||||
| 		if yyb6 { | ||||
| 			break | ||||
| 		} | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 		z.DecStructFieldNotFound(yyj6-1, "") | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *HTTPHeader) CodecEncodeSelf(e *codec1978.Encoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperEncoder(e) | ||||
| @@ -62738,7 +62975,7 @@ func (x codecSelfer1234) decSliceEnvFromSource(v *[]EnvFromSource, d *codec1978. | ||||
| 
 | ||||
| 			yyrg1 := len(yyv1) > 0 | ||||
| 			yyv21 := yyv1 | ||||
| 			yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 24) | ||||
| 			yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 32) | ||||
| 			if yyrt1 { | ||||
| 				if yyrl1 <= cap(yyv1) { | ||||
| 					yyv1 = yyv1[:yyrl1] | ||||
|   | ||||
| @@ -1243,6 +1243,9 @@ type EnvFromSource struct { | ||||
| 	// The ConfigMap to select from | ||||
| 	// +optional | ||||
| 	ConfigMapRef *ConfigMapEnvSource `json:"configMapRef,omitempty" protobuf:"bytes,2,opt,name=configMapRef"` | ||||
| 	// The Secret to select from | ||||
| 	// +optional | ||||
| 	SecretRef *SecretEnvSource `json:"secretRef,omitempty" protobuf:"bytes,3,opt,name=secretRef"` | ||||
| } | ||||
|  | ||||
| // ConfigMapEnvSource selects a ConfigMap to populate the environment | ||||
| @@ -1255,6 +1258,16 @@ type ConfigMapEnvSource struct { | ||||
| 	LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"` | ||||
| } | ||||
|  | ||||
| // SecretEnvSource selects a Secret to populate the environment | ||||
| // variables with. | ||||
| // | ||||
| // The contents of the target Secret's Data field will represent the | ||||
| // key-value pairs as environment variables. | ||||
| type SecretEnvSource struct { | ||||
| 	// The Secret to select from. | ||||
| 	LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"` | ||||
| } | ||||
|  | ||||
| // HTTPHeader describes a custom header to be used in HTTP probes | ||||
| type HTTPHeader struct { | ||||
| 	// The header field name | ||||
|   | ||||
| @@ -437,6 +437,7 @@ var map_EnvFromSource = map[string]string{ | ||||
| 	"":             "EnvFromSource represents the source of a set of ConfigMaps", | ||||
| 	"prefix":       "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.", | ||||
| 	"configMapRef": "The ConfigMap to select from", | ||||
| 	"secretRef":    "The Secret to select from", | ||||
| } | ||||
| 
 | ||||
| func (EnvFromSource) SwaggerDoc() map[string]string { | ||||
| @@ -1588,6 +1589,14 @@ func (Secret) SwaggerDoc() map[string]string { | ||||
| 	return map_Secret | ||||
| } | ||||
| 
 | ||||
| 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.", | ||||
| } | ||||
| 
 | ||||
| func (SecretEnvSource) SwaggerDoc() map[string]string { | ||||
| 	return map_SecretEnvSource | ||||
| } | ||||
| 
 | ||||
| var map_SecretKeySelector = map[string]string{ | ||||
| 	"":    "SecretKeySelector selects a key of a Secret.", | ||||
| 	"key": "The key of the secret to select from.  Must be a valid secret key.", | ||||
|   | ||||
| @@ -309,6 +309,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { | ||||
| 		Convert_api_SELinuxOptions_To_v1_SELinuxOptions, | ||||
| 		Convert_v1_Secret_To_api_Secret, | ||||
| 		Convert_api_Secret_To_v1_Secret, | ||||
| 		Convert_v1_SecretEnvSource_To_api_SecretEnvSource, | ||||
| 		Convert_api_SecretEnvSource_To_v1_SecretEnvSource, | ||||
| 		Convert_v1_SecretKeySelector_To_api_SecretKeySelector, | ||||
| 		Convert_api_SecretKeySelector_To_v1_SecretKeySelector, | ||||
| 		Convert_v1_SecretList_To_api_SecretList, | ||||
| @@ -1205,6 +1207,7 @@ func Convert_api_EndpointsList_To_v1_EndpointsList(in *api.EndpointsList, out *E | ||||
| func autoConvert_v1_EnvFromSource_To_api_EnvFromSource(in *EnvFromSource, out *api.EnvFromSource, s conversion.Scope) error { | ||||
| 	out.Prefix = in.Prefix | ||||
| 	out.ConfigMapRef = (*api.ConfigMapEnvSource)(unsafe.Pointer(in.ConfigMapRef)) | ||||
| 	out.SecretRef = (*api.SecretEnvSource)(unsafe.Pointer(in.SecretRef)) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -1215,6 +1218,7 @@ func Convert_v1_EnvFromSource_To_api_EnvFromSource(in *EnvFromSource, out *api.E | ||||
| func autoConvert_api_EnvFromSource_To_v1_EnvFromSource(in *api.EnvFromSource, out *EnvFromSource, s conversion.Scope) error { | ||||
| 	out.Prefix = in.Prefix | ||||
| 	out.ConfigMapRef = (*ConfigMapEnvSource)(unsafe.Pointer(in.ConfigMapRef)) | ||||
| 	out.SecretRef = (*SecretEnvSource)(unsafe.Pointer(in.SecretRef)) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -3760,6 +3764,28 @@ func Convert_api_Secret_To_v1_Secret(in *api.Secret, out *Secret, s conversion.S | ||||
| 	return autoConvert_api_Secret_To_v1_Secret(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_v1_SecretEnvSource_To_api_SecretEnvSource(in *SecretEnvSource, out *api.SecretEnvSource, s conversion.Scope) error { | ||||
| 	if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func Convert_v1_SecretEnvSource_To_api_SecretEnvSource(in *SecretEnvSource, out *api.SecretEnvSource, s conversion.Scope) error { | ||||
| 	return autoConvert_v1_SecretEnvSource_To_api_SecretEnvSource(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_api_SecretEnvSource_To_v1_SecretEnvSource(in *api.SecretEnvSource, out *SecretEnvSource, s conversion.Scope) error { | ||||
| 	if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func Convert_api_SecretEnvSource_To_v1_SecretEnvSource(in *api.SecretEnvSource, out *SecretEnvSource, s conversion.Scope) error { | ||||
| 	return autoConvert_api_SecretEnvSource_To_v1_SecretEnvSource(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_v1_SecretKeySelector_To_api_SecretKeySelector(in *SecretKeySelector, out *api.SecretKeySelector, s conversion.Scope) error { | ||||
| 	if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil { | ||||
| 		return err | ||||
|   | ||||
| @@ -172,6 +172,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Secret, InType: reflect.TypeOf(&Secret{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretList, InType: reflect.TypeOf(&SecretList{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_SecretVolumeSource, InType: reflect.TypeOf(&SecretVolumeSource{})}, | ||||
| @@ -873,6 +874,11 @@ func DeepCopy_v1_EnvFromSource(in interface{}, out interface{}, c *conversion.Cl | ||||
| 			*out = new(ConfigMapEnvSource) | ||||
| 			**out = **in | ||||
| 		} | ||||
| 		if in.SecretRef != nil { | ||||
| 			in, out := &in.SecretRef, &out.SecretRef | ||||
| 			*out = new(SecretEnvSource) | ||||
| 			**out = **in | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| @@ -2767,6 +2773,15 @@ func DeepCopy_v1_Secret(in interface{}, out interface{}, c *conversion.Cloner) e | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func DeepCopy_v1_SecretEnvSource(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 	{ | ||||
| 		in := in.(*SecretEnvSource) | ||||
| 		out := out.(*SecretEnvSource) | ||||
| 		*out = *in | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func DeepCopy_v1_SecretKeySelector(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 	{ | ||||
| 		in := in.(*SecretKeySelector) | ||||
|   | ||||
| @@ -1260,9 +1260,22 @@ func validateEnvFrom(vars []api.EnvFromSource, fldPath *field.Path) field.ErrorL | ||||
| 				allErrs = append(allErrs, field.Invalid(idxPath.Child("prefix"), ev.Prefix, msg)) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		numSources := 0 | ||||
| 		if ev.ConfigMapRef != nil { | ||||
| 			numSources++ | ||||
| 			allErrs = append(allErrs, validateConfigMapEnvSource(ev.ConfigMapRef, idxPath.Child("configMapRef"))...) | ||||
| 		} | ||||
| 		if ev.SecretRef != nil { | ||||
| 			numSources++ | ||||
| 			allErrs = append(allErrs, validateSecretEnvSource(ev.SecretRef, idxPath.Child("secretRef"))...) | ||||
| 		} | ||||
|  | ||||
| 		if numSources == 0 { | ||||
| 			allErrs = append(allErrs, field.Invalid(fldPath, "", "must specify one of: `configMapRef` or `secretRef`")) | ||||
| 		} else if numSources > 1 { | ||||
| 			allErrs = append(allErrs, field.Invalid(fldPath, "", "may not have more than one field specified at a time")) | ||||
| 		} | ||||
| 	} | ||||
| 	return allErrs | ||||
| } | ||||
| @@ -1275,6 +1288,14 @@ func validateConfigMapEnvSource(configMapSource *api.ConfigMapEnvSource, fldPath | ||||
| 	return allErrs | ||||
| } | ||||
|  | ||||
| func validateSecretEnvSource(secretSource *api.SecretEnvSource, fldPath *field.Path) field.ErrorList { | ||||
| 	allErrs := field.ErrorList{} | ||||
| 	if len(secretSource.Name) == 0 { | ||||
| 		allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) | ||||
| 	} | ||||
| 	return allErrs | ||||
| } | ||||
|  | ||||
| var validContainerResourceDivisorForCPU = sets.NewString("1m", "1") | ||||
| var validContainerResourceDivisorForMemory = sets.NewString("1", "1k", "1M", "1G", "1T", "1P", "1E", "1Ki", "1Mi", "1Gi", "1Ti", "1Pi", "1Ei") | ||||
|  | ||||
|   | ||||
| @@ -2285,6 +2285,17 @@ func TestValidateEnvFrom(t *testing.T) { | ||||
| 				LocalObjectReference: api.LocalObjectReference{Name: "abc"}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			SecretRef: &api.SecretEnvSource{ | ||||
| 				LocalObjectReference: api.LocalObjectReference{Name: "abc"}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Prefix: "pre_", | ||||
| 			SecretRef: &api.SecretEnvSource{ | ||||
| 				LocalObjectReference: api.LocalObjectReference{Name: "abc"}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	if errs := validateEnvFrom(successCase, field.NewPath("field")); len(errs) != 0 { | ||||
| 		t.Errorf("expected success: %v", errs) | ||||
| @@ -2316,6 +2327,46 @@ func TestValidateEnvFrom(t *testing.T) { | ||||
| 			}, | ||||
| 			expectedError: `field[0].prefix: Invalid value: "a.b": ` + idErrMsg, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "zero-length name", | ||||
| 			envs: []api.EnvFromSource{ | ||||
| 				{ | ||||
| 					SecretRef: &api.SecretEnvSource{ | ||||
| 						LocalObjectReference: api.LocalObjectReference{Name: ""}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedError: "field[0].secretRef.name: Required value", | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "invalid prefix", | ||||
| 			envs: []api.EnvFromSource{ | ||||
| 				{ | ||||
| 					Prefix: "a.b", | ||||
| 					SecretRef: &api.SecretEnvSource{ | ||||
| 						LocalObjectReference: api.LocalObjectReference{Name: "abc"}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedError: `field[0].prefix: Invalid value: "a.b": ` + idErrMsg, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "no refs", | ||||
| 			envs: []api.EnvFromSource{ | ||||
| 				{}, | ||||
| 			}, | ||||
| 			expectedError: "field: Invalid value: \"\": must specify one of: `configMapRef` or `secretRef`", | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "multiple refs", | ||||
| 			envs: []api.EnvFromSource{ | ||||
| 				{ | ||||
| 					SecretRef: &api.SecretEnvSource{ | ||||
| 						LocalObjectReference: api.LocalObjectReference{Name: "abc"}}, | ||||
| 					ConfigMapRef: &api.ConfigMapEnvSource{ | ||||
| 						LocalObjectReference: api.LocalObjectReference{Name: "abc"}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedError: "field: Invalid value: \"\": may not have more than one field specified at a time", | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range errorCases { | ||||
| 		if errs := validateEnvFrom(tc.envs, field.NewPath("field")); len(errs) == 0 { | ||||
|   | ||||
| @@ -175,6 +175,7 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ResourceRequirements, InType: reflect.TypeOf(&ResourceRequirements{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SELinuxOptions, InType: reflect.TypeOf(&SELinuxOptions{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_Secret, InType: reflect.TypeOf(&Secret{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretEnvSource, InType: reflect.TypeOf(&SecretEnvSource{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretKeySelector, InType: reflect.TypeOf(&SecretKeySelector{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretList, InType: reflect.TypeOf(&SecretList{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_SecretVolumeSource, InType: reflect.TypeOf(&SecretVolumeSource{})}, | ||||
| @@ -901,6 +902,11 @@ func DeepCopy_api_EnvFromSource(in interface{}, out interface{}, c *conversion.C | ||||
| 			*out = new(ConfigMapEnvSource) | ||||
| 			**out = **in | ||||
| 		} | ||||
| 		if in.SecretRef != nil { | ||||
| 			in, out := &in.SecretRef, &out.SecretRef | ||||
| 			*out = new(SecretEnvSource) | ||||
| 			**out = **in | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| @@ -2799,6 +2805,15 @@ func DeepCopy_api_Secret(in interface{}, out interface{}, c *conversion.Cloner) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func DeepCopy_api_SecretEnvSource(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 	{ | ||||
| 		in := in.(*SecretEnvSource) | ||||
| 		out := out.(*SecretEnvSource) | ||||
| 		*out = *in | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func DeepCopy_api_SecretKeySelector(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 	{ | ||||
| 		in := in.(*SecretKeySelector) | ||||
|   | ||||
| @@ -1924,11 +1924,17 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions | ||||
| 							Ref:         spec.MustCreateRef("#/definitions/v1.ConfigMapEnvSource"), | ||||
| 						}, | ||||
| 					}, | ||||
| 					"secretRef": { | ||||
| 						SchemaProps: spec.SchemaProps{ | ||||
| 							Description: "The Secret to select from", | ||||
| 							Ref:         spec.MustCreateRef("#/definitions/v1.SecretEnvSource"), | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		Dependencies: []string{ | ||||
| 			"v1.ConfigMapEnvSource"}, | ||||
| 			"v1.ConfigMapEnvSource", "v1.SecretEnvSource"}, | ||||
| 	}, | ||||
| 	"v1.EnvVar": { | ||||
| 		Schema: spec.Schema{ | ||||
| @@ -7367,6 +7373,23 @@ var OpenAPIDefinitions *openapi.OpenAPIDefinitions = &openapi.OpenAPIDefinitions | ||||
| 		Dependencies: []string{ | ||||
| 			"v1.ObjectMeta"}, | ||||
| 	}, | ||||
| 	"v1.SecretEnvSource": { | ||||
| 		Schema: spec.Schema{ | ||||
| 			SchemaProps: spec.SchemaProps{ | ||||
| 				Description: "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.", | ||||
| 				Properties: map[string]spec.Schema{ | ||||
| 					"name": { | ||||
| 						SchemaProps: spec.SchemaProps{ | ||||
| 							Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", | ||||
| 							Type:        []string{"string"}, | ||||
| 							Format:      "", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		Dependencies: []string{}, | ||||
| 	}, | ||||
| 	"v1.SecretKeySelector": { | ||||
| 		Schema: spec.Schema{ | ||||
| 			SchemaProps: spec.SchemaProps{ | ||||
|   | ||||
| @@ -1052,10 +1052,19 @@ func describeContainerEnvFrom(container api.Container, resolverFn EnvVarResolver | ||||
| 	w.Write(LEVEL_2, "Environment Variables from:%s\n", none) | ||||
|  | ||||
| 	for _, e := range container.EnvFrom { | ||||
| 		from := "" | ||||
| 		name := "" | ||||
| 		if e.ConfigMapRef != nil { | ||||
| 			from = "ConfigMap" | ||||
| 			name = e.ConfigMapRef.Name | ||||
| 		} else if e.SecretRef != nil { | ||||
| 			from = "Secret" | ||||
| 			name = e.SecretRef.Name | ||||
| 		} | ||||
| 		if len(e.Prefix) == 0 { | ||||
| 			w.Write(LEVEL_3, "%s\tConfigMap\n", e.ConfigMapRef.Name) | ||||
| 			w.Write(LEVEL_3, "%s\t%s\n", name, from) | ||||
| 		} else { | ||||
| 			w.Write(LEVEL_3, "%s\tConfigMap with prefix '%s'\n", e.ConfigMapRef.Name, e.Prefix) | ||||
| 			w.Write(LEVEL_3, "%s\t%s with prefix '%s'\n", name, from, e.Prefix) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -306,6 +306,24 @@ func TestDescribeContainers(t *testing.T) { | ||||
| 			}, | ||||
| 			expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap with prefix 'p_'"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			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"}}}}}, | ||||
| 			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"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			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"}}}}}, | ||||
| 			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 with prefix 'p_'"}, | ||||
| 		}, | ||||
| 		// Command | ||||
| 		{ | ||||
| 			container: api.Container{Name: "test", Image: "image", Command: []string{"sleep", "1000"}}, | ||||
|   | ||||
| @@ -418,13 +418,15 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container | ||||
|  | ||||
| 	var ( | ||||
| 		configMaps = make(map[string]*v1.ConfigMap) | ||||
| 		secrets    = make(map[string]*v1.Secret) | ||||
| 		tmpEnv     = make(map[string]string) | ||||
| 	) | ||||
|  | ||||
| 	// Env will override EnvFrom variables. | ||||
| 	// Process EnvFrom first then allow Env to replace existing values. | ||||
| 	for _, envFrom := range container.EnvFrom { | ||||
| 		if envFrom.ConfigMapRef != nil { | ||||
| 		switch { | ||||
| 		case envFrom.ConfigMapRef != nil: | ||||
| 			name := envFrom.ConfigMapRef.Name | ||||
| 			configMap, ok := configMaps[name] | ||||
| 			if !ok { | ||||
| @@ -432,12 +434,12 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container | ||||
| 					return result, fmt.Errorf("Couldn't get configMap %v/%v, no kubeClient defined", pod.Namespace, name) | ||||
| 				} | ||||
| 				configMap, err = kl.kubeClient.Core().ConfigMaps(pod.Namespace).Get(name, metav1.GetOptions{}) | ||||
|  | ||||
| 				if err != nil { | ||||
| 					return result, err | ||||
| 				} | ||||
| 				configMaps[name] = configMap | ||||
| 			} | ||||
|  | ||||
| 			for k, v := range configMap.Data { | ||||
| 				if len(envFrom.Prefix) > 0 { | ||||
| 					k = envFrom.Prefix + k | ||||
| @@ -445,14 +447,31 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container | ||||
| 				if errMsgs := utilvalidation.IsCIdentifier(k); len(errMsgs) != 0 { | ||||
| 					return result, fmt.Errorf("Invalid environment variable name, %v, from configmap %v/%v: %s", k, pod.Namespace, name, errMsgs[0]) | ||||
| 				} | ||||
| 				// Accesses apiserver+Pods. | ||||
| 				// So, the master may set service env vars, or kubelet may.  In case both are doing | ||||
| 				// it, we delete the key from the kubelet-generated ones so we don't have duplicate | ||||
| 				// env vars. | ||||
| 				// TODO: remove this next line once all platforms use apiserver+Pods. | ||||
| 				delete(serviceEnv, k) | ||||
| 				tmpEnv[k] = v | ||||
| 			} | ||||
| 		case envFrom.SecretRef != nil: | ||||
| 			name := envFrom.SecretRef.Name | ||||
| 			secret, ok := secrets[name] | ||||
| 			if !ok { | ||||
| 				if kl.kubeClient == nil { | ||||
| 					return result, fmt.Errorf("Couldn't get secret %v/%v, no kubeClient defined", pod.Namespace, name) | ||||
| 				} | ||||
| 				secret, err = kl.kubeClient.Core().Secrets(pod.Namespace).Get(name, metav1.GetOptions{}) | ||||
| 				if err != nil { | ||||
| 					return result, err | ||||
| 				} | ||||
| 				secrets[name] = secret | ||||
| 			} | ||||
|  | ||||
| 			for k, v := range secret.Data { | ||||
| 				if len(envFrom.Prefix) > 0 { | ||||
| 					k = envFrom.Prefix + k | ||||
| 				} | ||||
| 				if errMsgs := utilvalidation.IsCIdentifier(k); len(errMsgs) != 0 { | ||||
| 					return result, fmt.Errorf("Invalid environment variable name, %v, from secret %v/%v: %s", k, pod.Namespace, name, errMsgs[0]) | ||||
| 				} | ||||
| 				tmpEnv[k] = string(v) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -466,17 +485,9 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container | ||||
| 	// 2.  Create the container's environment in the order variables are declared | ||||
| 	// 3.  Add remaining service environment vars | ||||
| 	var ( | ||||
| 		secrets     = make(map[string]*v1.Secret) | ||||
| 		mappingFunc = expansion.MappingFuncFor(tmpEnv, serviceEnv) | ||||
| 	) | ||||
| 	for _, envVar := range container.Env { | ||||
| 		// 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) | ||||
|  | ||||
| 		runtimeVal := envVar.Value | ||||
| 		if runtimeVal != "" { | ||||
| 			// Step 1a: expand variable references | ||||
| @@ -548,7 +559,14 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container | ||||
|  | ||||
| 	// Append remaining service env vars. | ||||
| 	for k, v := range serviceEnv { | ||||
| 		result = append(result, kubecontainer.EnvVar{Name: k, Value: v}) | ||||
| 		// Accesses apiserver+Pods. | ||||
| 		// So, the master may set service env vars, or kubelet may.  In case both are doing | ||||
| 		// it, we skip 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. | ||||
| 		if _, present := tmpEnv[k]; !present { | ||||
| 			result = append(result, kubecontainer.EnvVar{Name: k, Value: v}) | ||||
| 		} | ||||
| 	} | ||||
| 	return result, nil | ||||
| } | ||||
|   | ||||
| @@ -274,6 +274,7 @@ func TestMakeEnvironmentVariables(t *testing.T) { | ||||
| 		masterServiceNs string                 // the namespace to read master service info from | ||||
| 		nilLister       bool                   // whether the lister should be nil | ||||
| 		configMap       *v1.ConfigMap          // an optional ConfigMap to pull from | ||||
| 		secret          *v1.Secret             // an optional Secret to pull from | ||||
| 		expectedEnvs    []kubecontainer.EnvVar // a set of expected environment vars | ||||
| 		expectedError   bool                   // does the test fail | ||||
| 	}{ | ||||
| @@ -766,6 +767,160 @@ func TestMakeEnvironmentVariables(t *testing.T) { | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "secret", | ||||
| 			ns:   "test1", | ||||
| 			container: &v1.Container{ | ||||
| 				EnvFrom: []v1.EnvFromSource{ | ||||
| 					{ | ||||
| 						SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Prefix:    "p_", | ||||
| 						SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				Env: []v1.EnvVar{ | ||||
| 					{ | ||||
| 						Name:  "TEST_LITERAL", | ||||
| 						Value: "test-test-test", | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:  "EXPANSION_TEST", | ||||
| 						Value: "$(REPLACE_ME)", | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:  "DUPE_TEST", | ||||
| 						Value: "ENV_VAR", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			masterServiceNs: "nothing", | ||||
| 			nilLister:       false, | ||||
| 			secret: &v1.Secret{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Namespace: "test1", | ||||
| 					Name:      "test-secret", | ||||
| 				}, | ||||
| 				Data: map[string][]byte{ | ||||
| 					"REPLACE_ME": []byte("FROM_SECRET"), | ||||
| 					"DUPE_TEST":  []byte("SECRET"), | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedEnvs: []kubecontainer.EnvVar{ | ||||
| 				{ | ||||
| 					Name:  "TEST_LITERAL", | ||||
| 					Value: "test-test-test", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "TEST_SERVICE_HOST", | ||||
| 					Value: "1.2.3.3", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "TEST_SERVICE_PORT", | ||||
| 					Value: "8083", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "TEST_PORT", | ||||
| 					Value: "tcp://1.2.3.3:8083", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "TEST_PORT_8083_TCP", | ||||
| 					Value: "tcp://1.2.3.3:8083", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "TEST_PORT_8083_TCP_PROTO", | ||||
| 					Value: "tcp", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "TEST_PORT_8083_TCP_PORT", | ||||
| 					Value: "8083", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "TEST_PORT_8083_TCP_ADDR", | ||||
| 					Value: "1.2.3.3", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "REPLACE_ME", | ||||
| 					Value: "FROM_SECRET", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "EXPANSION_TEST", | ||||
| 					Value: "FROM_SECRET", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "DUPE_TEST", | ||||
| 					Value: "ENV_VAR", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "p_REPLACE_ME", | ||||
| 					Value: "FROM_SECRET", | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:  "p_DUPE_TEST", | ||||
| 					Value: "SECRET", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "secret_missing", | ||||
| 			ns:   "test1", | ||||
| 			container: &v1.Container{ | ||||
| 				EnvFrom: []v1.EnvFromSource{ | ||||
| 					{SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			masterServiceNs: "nothing", | ||||
| 			expectedError:   true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "secret_invalid_keys", | ||||
| 			ns:   "test1", | ||||
| 			container: &v1.Container{ | ||||
| 				EnvFrom: []v1.EnvFromSource{ | ||||
| 					{SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			masterServiceNs: "nothing", | ||||
| 			secret: &v1.Secret{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Namespace: "test1", | ||||
| 					Name:      "test-secret", | ||||
| 				}, | ||||
| 				Data: map[string][]byte{ | ||||
| 					"1234": []byte("abc"), | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedError: true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "secret_invalid_keys_valid", | ||||
| 			ns:   "test", | ||||
| 			container: &v1.Container{ | ||||
| 				EnvFrom: []v1.EnvFromSource{ | ||||
| 					{ | ||||
| 						Prefix:    "p_", | ||||
| 						SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: "test-secret"}}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			masterServiceNs: "", | ||||
| 			secret: &v1.Secret{ | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Namespace: "test1", | ||||
| 					Name:      "test-secret", | ||||
| 				}, | ||||
| 				Data: map[string][]byte{ | ||||
| 					"1234": []byte("abc"), | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedEnvs: []kubecontainer.EnvVar{ | ||||
| 				{ | ||||
| 					Name:  "p_1234", | ||||
| 					Value: "abc", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range testCases { | ||||
| @@ -786,6 +941,14 @@ func TestMakeEnvironmentVariables(t *testing.T) { | ||||
| 			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 = errors.New("no secret defined") | ||||
| 			} | ||||
| 			return true, tc.secret, err | ||||
| 		}) | ||||
|  | ||||
| 		testPod := &v1.Pod{ | ||||
| 			ObjectMeta: metav1.ObjectMeta{ | ||||
| 				Namespace: tc.ns, | ||||
|   | ||||
| @@ -193,8 +193,62 @@ var _ = framework.KubeDescribe("Secrets", func() { | ||||
| 			"SECRET_DATA=value-1", | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
| 	It("should be consumable via the environment [Conformance]", func() { | ||||
| 		name := "secret-test-" + string(uuid.NewUUID()) | ||||
| 		secret := newEnvFromSecret(f.Namespace.Name, name) | ||||
| 		By(fmt.Sprintf("creating secret %v/%v", f.Namespace.Name, secret.Name)) | ||||
| 		var err error | ||||
| 		if secret, err = f.ClientSet.Core().Secrets(f.Namespace.Name).Create(secret); err != nil { | ||||
| 			framework.Failf("unable to create test secret %s: %v", secret.Name, err) | ||||
| 		} | ||||
|  | ||||
| 		pod := &v1.Pod{ | ||||
| 			ObjectMeta: metav1.ObjectMeta{ | ||||
| 				Name: "pod-configmaps-" + string(uuid.NewUUID()), | ||||
| 			}, | ||||
| 			Spec: v1.PodSpec{ | ||||
| 				Containers: []v1.Container{ | ||||
| 					{ | ||||
| 						Name:    "env-test", | ||||
| 						Image:   "gcr.io/google_containers/busybox:1.24", | ||||
| 						Command: []string{"sh", "-c", "env"}, | ||||
| 						EnvFrom: []v1.EnvFromSource{ | ||||
| 							{ | ||||
| 								SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, | ||||
| 							}, | ||||
| 							{ | ||||
| 								Prefix:    "p_", | ||||
| 								SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				RestartPolicy: v1.RestartPolicyNever, | ||||
| 			}, | ||||
| 		} | ||||
|  | ||||
| 		f.TestContainerOutput("consume secrets", pod, 0, []string{ | ||||
| 			"data_1=value-1", "data_2=value-2", "data_3=value-3", | ||||
| 			"p_data_1=value-1", "p_data_2=value-2", "p_data_3=value-3", | ||||
| 		}) | ||||
| 	}) | ||||
| }) | ||||
|  | ||||
| func newEnvFromSecret(namespace, name string) *v1.Secret { | ||||
| 	return &v1.Secret{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Namespace: namespace, | ||||
| 			Name:      name, | ||||
| 		}, | ||||
| 		Data: map[string][]byte{ | ||||
| 			"data_1": []byte("value-1\n"), | ||||
| 			"data_2": []byte("value-2\n"), | ||||
| 			"data_3": []byte("value-3\n"), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func secretForTest(namespace, name string) *v1.Secret { | ||||
| 	return &v1.Secret{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Submit Queue
					Kubernetes Submit Queue