diff --git a/pkg/api/types.go b/pkg/api/types.go index 3c01ca773be..62606aef6c2 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -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. diff --git a/pkg/api/v1/conversion.go b/pkg/api/v1/conversion.go index d2cb2dc7acb..7e5a7cff6bf 100644 --- a/pkg/api/v1/conversion.go +++ b/pkg/api/v1/conversion.go @@ -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": diff --git a/pkg/api/v1/types.go b/pkg/api/v1/types.go index b7721211b84..6d5de4c5f74 100644 --- a/pkg/api/v1/types.go +++ b/pkg/api/v1/types.go @@ -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. diff --git a/pkg/api/v1/types_swagger_doc_generated.go b/pkg/api/v1/types_swagger_doc_generated.go index d1023eb4acc..6b4db441fce 100644 --- a/pkg/api/v1/types_swagger_doc_generated.go +++ b/pkg/api/v1/types_swagger_doc_generated.go @@ -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", diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index f44b67dd229..13722e09a4d 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -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 { diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index b55447fc8d2..bf9cfd2bebd 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -2214,6 +2214,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{ @@ -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 { diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 470e67413a0..3ac93a5dfb7 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -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 } diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 4e95769045b..12392b91dae 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -1379,6 +1379,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{ @@ -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" diff --git a/pkg/volume/downwardapi/downwardapi.go b/pkg/volume/downwardapi/downwardapi.go index 679c73114c3..4a640fdcc6a 100644 --- a/pkg/volume/downwardapi/downwardapi.go +++ b/pkg/volume/downwardapi/downwardapi.go @@ -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)