Commit 6e0d25dc authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #27880 from smarterclayton/serviceaccountdownward

Automatic merge from submit-queue Add spec.nodeName and spec.serviceAccountName to downward env var The serviceAccountName is occasionally useful for clients running on Kube that need to know who they are when talking to other components. The nodeName is useful for PetSet or DaemonSet pods that need to make calls back to the API to fetch info about their node. Both fields are immutable, and cannot easily be retrieved in another way. @bprashanth @pmorie as relevant consumers / reviewers. ```release-note The `valueFrom.fieldRef.name` field on environment variables in pods and objects with pod templates now allows two additional fields to be used: * `spec.nodeName` will return the name of the node this pod is running on * `spec.serviceAccountName` will return the name of the service account this pod is running under ```
parents 98c40292 abded5c6
......@@ -2169,7 +2169,7 @@
"properties": {
"fieldRef": {
"$ref": "v1.ObjectFieldSelector",
"description": "Selects a field of the pod; only name and namespace are supported."
"description": "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP."
},
"resourceFieldRef": {
"$ref": "v1.ResourceFieldSelector",
......
......@@ -2174,7 +2174,7 @@
"properties": {
"fieldRef": {
"$ref": "v1.ObjectFieldSelector",
"description": "Selects a field of the pod; only name and namespace are supported."
"description": "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP."
},
"resourceFieldRef": {
"$ref": "v1.ResourceFieldSelector",
......
......@@ -9338,7 +9338,7 @@
"properties": {
"fieldRef": {
"$ref": "v1.ObjectFieldSelector",
"description": "Selects a field of the pod; only name and namespace are supported."
"description": "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP."
},
"resourceFieldRef": {
"$ref": "v1.ResourceFieldSelector",
......
......@@ -18271,7 +18271,7 @@
"properties": {
"fieldRef": {
"$ref": "v1.ObjectFieldSelector",
"description": "Selects a field of the pod; only name and namespace are supported."
"description": "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP."
},
"resourceFieldRef": {
"$ref": "v1.ResourceFieldSelector",
......
......@@ -2838,7 +2838,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">fieldRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a field of the pod; only name and namespace are supported.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP.</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_objectfieldselector">v1.ObjectFieldSelector</a></p></td>
<td class="tableblock halign-left valign-top"></td>
......@@ -4207,7 +4207,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div>
<div id="footer">
<div id="footer-text">
Last updated 2016-08-18 14:23:21 UTC
Last updated 2016-08-19 22:24:38 UTC
</div>
</div>
</body>
......
......@@ -2547,7 +2547,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">fieldRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a field of the pod; only name and namespace are supported.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP.</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_objectfieldselector">v1.ObjectFieldSelector</a></p></td>
<td class="tableblock halign-left valign-top"></td>
......@@ -6595,7 +6595,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 2016-08-18 14:23:14 UTC
Last updated 2016-08-19 22:24:31 UTC
</div>
</div>
</body>
......
......@@ -3019,7 +3019,7 @@ The resulting set of endpoints can be viewed as:<br>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">fieldRef</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a field of the pod; only name and namespace are supported.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP.</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_objectfieldselector">v1.ObjectFieldSelector</a></p></td>
<td class="tableblock halign-left valign-top"></td>
......@@ -8285,7 +8285,7 @@ The resulting set of endpoints can be viewed as:<br>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2016-08-19 15:53:53 UTC
Last updated 2016-08-19 22:24:23 UTC
</div>
</div>
</body>
......
......@@ -878,7 +878,8 @@ type EnvVar struct {
// EnvVarSource represents a source for the value of an EnvVar.
// Only one of its fields may be set.
type EnvVarSource struct {
// Selects a field of the pod; only name and namespace are supported.
// Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations,
// spec.nodeName, spec.serviceAccountName, status.podIP.
FieldRef *ObjectFieldSelector `json:"fieldRef,omitempty"`
// Selects a resource of the container: only resources limits and requests
// (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.
......
......@@ -192,14 +192,15 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
err = scheme.AddFieldLabelConversionFunc("v1", "Pod",
func(label, value string) (string, string, error) {
switch label {
case "metadata.name",
"metadata.namespace",
case "metadata.annotations",
"metadata.labels",
"metadata.annotations",
"status.phase",
"status.podIP",
"metadata.name",
"metadata.namespace",
"spec.nodeName",
"spec.restartPolicy":
"spec.restartPolicy",
"spec.serviceAccountName",
"status.phase",
"status.podIP":
return label, value, nil
// This is for backwards compatibility with old v1 clients which send spec.host
case "spec.host":
......
......@@ -683,7 +683,8 @@ message EnvVar {
// EnvVarSource represents a source for the value of an EnvVar.
message EnvVarSource {
// Selects a field of the pod; only name and namespace are supported.
// Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations,
// spec.nodeName, spec.serviceAccountName, status.podIP.
optional ObjectFieldSelector fieldRef = 1;
// Selects a resource of the container: only resources limits and requests
......
......@@ -990,7 +990,8 @@ type EnvVar struct {
// EnvVarSource represents a source for the value of an EnvVar.
type EnvVarSource struct {
// Selects a field of the pod; only name and namespace are supported.
// Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations,
// spec.nodeName, spec.serviceAccountName, status.podIP.
FieldRef *ObjectFieldSelector `json:"fieldRef,omitempty" protobuf:"bytes,1,opt,name=fieldRef"`
// Selects a resource of the container: only resources limits and requests
// (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.
......
......@@ -424,7 +424,7 @@ func (EnvVar) SwaggerDoc() map[string]string {
var map_EnvVarSource = map[string]string{
"": "EnvVarSource represents a source for the value of an EnvVar.",
"fieldRef": "Selects a field of the pod; only name and namespace are supported.",
"fieldRef": "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP.",
"resourceFieldRef": "Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.",
"configMapKeyRef": "Selects a key of a ConfigMap.",
"secretKeyRef": "Selects a key of a secret in the pod's namespace",
......
......@@ -1208,7 +1208,7 @@ func validateEnv(vars []api.EnvVar, fldPath *field.Path) field.ErrorList {
return allErrs
}
var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "status.podIP")
var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "spec.nodeName", "spec.serviceAccountName", "status.podIP")
var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "requests.cpu", "requests.memory")
func validateEnvVarValueFrom(ev api.EnvVar, fldPath *field.Path) field.ErrorList {
......
......@@ -2215,6 +2215,24 @@ func TestValidateEnv(t *testing.T) {
},
},
{
Name: "abc",
ValueFrom: &api.EnvVarSource{
FieldRef: &api.ObjectFieldSelector{
APIVersion: testapi.Default.GroupVersion().String(),
FieldPath: "spec.nodeName",
},
},
},
{
Name: "abc",
ValueFrom: &api.EnvVarSource{
FieldRef: &api.ObjectFieldSelector{
APIVersion: testapi.Default.GroupVersion().String(),
FieldPath: "spec.serviceAccountName",
},
},
},
{
Name: "secret_value",
ValueFrom: &api.EnvVarSource{
SecretKeyRef: &api.SecretKeySelector{
......@@ -2381,7 +2399,7 @@ func TestValidateEnv(t *testing.T) {
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: metadata.name, metadata.namespace, status.podIP`,
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: metadata.name, metadata.namespace, spec.nodeName, spec.serviceAccountName, status.podIP`,
},
{
name: "invalid fieldPath annotations",
......@@ -2394,7 +2412,7 @@ func TestValidateEnv(t *testing.T) {
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: metadata.name, metadata.namespace, status.podIP`,
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: metadata.name, metadata.namespace, spec.nodeName, spec.serviceAccountName, status.podIP`,
},
{
name: "unsupported fieldPath",
......@@ -2407,7 +2425,7 @@ func TestValidateEnv(t *testing.T) {
},
},
}},
expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: metadata.name, metadata.namespace, status.podIP`,
expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: metadata.name, metadata.namespace, spec.nodeName, spec.serviceAccountName, status.podIP`,
},
}
for _, tc := range errorCases {
......
......@@ -1440,6 +1440,10 @@ func (kl *Kubelet) podFieldSelectorRuntimeValue(fs *api.ObjectFieldSelector, pod
return "", err
}
switch internalFieldPath {
case "spec.nodeName":
return pod.Spec.NodeName, nil
case "spec.serviceAccountName":
return pod.Spec.ServiceAccountName, nil
case "status.podIP":
return podIP, nil
}
......
......@@ -1380,6 +1380,24 @@ func TestMakeEnvironmentVariables(t *testing.T) {
},
},
{
Name: "POD_NODE_NAME",
ValueFrom: &api.EnvVarSource{
FieldRef: &api.ObjectFieldSelector{
APIVersion: testapi.Default.GroupVersion().String(),
FieldPath: "spec.nodeName",
},
},
},
{
Name: "POD_SERVICE_ACCOUNT_NAME",
ValueFrom: &api.EnvVarSource{
FieldRef: &api.ObjectFieldSelector{
APIVersion: testapi.Default.GroupVersion().String(),
FieldPath: "spec.serviceAccountName",
},
},
},
{
Name: "POD_IP",
ValueFrom: &api.EnvVarSource{
FieldRef: &api.ObjectFieldSelector{
......@@ -1395,6 +1413,8 @@ func TestMakeEnvironmentVariables(t *testing.T) {
expectedEnvs: []kubecontainer.EnvVar{
{Name: "POD_NAME", Value: "dapi-test-pod-name"},
{Name: "POD_NAMESPACE", Value: "downward-api"},
{Name: "POD_NODE_NAME", Value: "node-name"},
{Name: "POD_SERVICE_ACCOUNT_NAME", Value: "special"},
{Name: "POD_IP", Value: "1.2.3.4"},
},
},
......@@ -1546,6 +1566,10 @@ func TestMakeEnvironmentVariables(t *testing.T) {
Namespace: tc.ns,
Name: "dapi-test-pod-name",
},
Spec: api.PodSpec{
ServiceAccountName: "special",
NodeName: "node-name",
},
}
podIP := "1.2.3.4"
......
......@@ -215,6 +215,7 @@ func (d *downwardAPIVolume) collectData(defaultMode *int32) (map[string]volumeut
fileProjection.Mode = *defaultMode
}
if fileInfo.FieldRef != nil {
// TODO: unify with Kubelet.podFieldSelectorRuntimeValue
if values, err := fieldpath.ExtractFieldPathAsString(d.pod, fileInfo.FieldRef.FieldPath); err != nil {
glog.Errorf("Unable to extract field %s: %s", fileInfo.FieldRef.FieldPath, err.Error())
errlist = append(errlist, err)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment