mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Change EnvVarSource.FieldPath -> FieldRef and add example
This commit is contained in:
		
							
								
								
									
										33
									
								
								examples/downward-api/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								examples/downward-api/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
# Downward API example
 | 
			
		||||
 | 
			
		||||
Following this example, you will create a pod with a containers that consumes the pod's name and
 | 
			
		||||
namespace using the downward API.
 | 
			
		||||
 | 
			
		||||
## Step Zero: Prerequisites
 | 
			
		||||
 | 
			
		||||
This example assumes you have a Kubernetes cluster installed and running, and that you have
 | 
			
		||||
installed the ```kubectl``` command line tool somewhere in your path. Please see the [getting
 | 
			
		||||
started](../../docs/getting-started-guides) for installation instructions for your platform.
 | 
			
		||||
 | 
			
		||||
## Step One: Create the pod
 | 
			
		||||
 | 
			
		||||
Containers consume the downward API using environment variables.  The downward API allows
 | 
			
		||||
containers to be injected with the name and namespace of the pod the container is in.
 | 
			
		||||
 | 
			
		||||
Use the `examples/secrets/secret-pod.yaml` file to create a Pod with a container that consumes the
 | 
			
		||||
downward API.
 | 
			
		||||
 | 
			
		||||
```shell
 | 
			
		||||
$ kubectl create -f examples/downward-api/dapi-pod.yaml
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Examine the logs
 | 
			
		||||
 | 
			
		||||
This pod runs the `env` command in a container that consumes the downward API.  You can grep
 | 
			
		||||
through the pod logs to see that the pod was injected with the correct values:
 | 
			
		||||
 | 
			
		||||
```shell
 | 
			
		||||
$ kubectl log dapi-test-pod | grep POD_
 | 
			
		||||
2015-04-30T20:22:18.568024817Z POD_NAME=dapi-test-pod
 | 
			
		||||
2015-04-30T20:22:18.568087688Z POD_NAMESPACE=default
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										19
									
								
								examples/downward-api/dapi-pod.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								examples/downward-api/dapi-pod.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
apiVersion: v1beta3
 | 
			
		||||
kind: Pod
 | 
			
		||||
metadata:
 | 
			
		||||
  name: dapi-test-pod
 | 
			
		||||
spec:
 | 
			
		||||
  containers:
 | 
			
		||||
    - name: test-container
 | 
			
		||||
      image: gcr.io/google_containers/busybox
 | 
			
		||||
      command: [ "/bin/sh", "-c", "env" ]
 | 
			
		||||
      env:
 | 
			
		||||
        - name: POD_NAME
 | 
			
		||||
          valueFrom:
 | 
			
		||||
            fieldRef:
 | 
			
		||||
              fieldPath: metadata.name
 | 
			
		||||
        - name: POD_NAMESPACE
 | 
			
		||||
          valueFrom:
 | 
			
		||||
            fieldRef:
 | 
			
		||||
              fieldPath: metadata.namespace
 | 
			
		||||
  restartPolicy: Never
 | 
			
		||||
@@ -196,12 +196,12 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
 | 
			
		||||
				ev.Value = c.RandString()
 | 
			
		||||
			} else {
 | 
			
		||||
				ev.ValueFrom = &api.EnvVarSource{}
 | 
			
		||||
				ev.ValueFrom.FieldPath = &api.ObjectFieldSelector{}
 | 
			
		||||
				ev.ValueFrom.FieldRef = &api.ObjectFieldSelector{}
 | 
			
		||||
 | 
			
		||||
				versions := []string{"v1beta1", "v1beta2", "v1beta3"}
 | 
			
		||||
 | 
			
		||||
				ev.ValueFrom.FieldPath.APIVersion = versions[c.Rand.Intn(len(versions))]
 | 
			
		||||
				ev.ValueFrom.FieldPath.FieldPath = c.RandString()
 | 
			
		||||
				ev.ValueFrom.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))]
 | 
			
		||||
				ev.ValueFrom.FieldRef.FieldPath = c.RandString()
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		func(e *api.Event, c fuzz.Continue) {
 | 
			
		||||
 
 | 
			
		||||
@@ -518,7 +518,7 @@ type EnvVar struct {
 | 
			
		||||
// EnvVarSource represents a source for the value of an EnvVar.
 | 
			
		||||
type EnvVarSource struct {
 | 
			
		||||
	// Required: Selects a field of the pod; only name and namespace are supported.
 | 
			
		||||
	FieldPath *ObjectFieldSelector `json:"fieldPath"`
 | 
			
		||||
	FieldRef *ObjectFieldSelector `json:"fieldRef"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ObjectFieldSelector selects an APIVersioned field of an object.
 | 
			
		||||
 
 | 
			
		||||
@@ -330,7 +330,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
				Env: []current.EnvVar{
 | 
			
		||||
					{
 | 
			
		||||
						ValueFrom: ¤t.EnvVarSource{
 | 
			
		||||
							FieldPath: ¤t.ObjectFieldSelector{},
 | 
			
		||||
							FieldRef: ¤t.ObjectFieldSelector{},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
@@ -344,7 +344,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
	pod2 := obj2.(*current.Pod)
 | 
			
		||||
	s2 := pod2.Spec
 | 
			
		||||
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldPath.APIVersion
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldRef.APIVersion
 | 
			
		||||
	if apiVersion != "v1" {
 | 
			
		||||
		t.Errorf("Expected default APIVersion v1, got: %v", apiVersion)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -529,7 +529,7 @@ type EnvVar struct {
 | 
			
		||||
// EnvVarSource represents a source for the value of an EnvVar.
 | 
			
		||||
type EnvVarSource struct {
 | 
			
		||||
	// Required: Selects a field of the pod; only name and namespace are supported.
 | 
			
		||||
	FieldPath *ObjectFieldSelector `json:"fieldPath" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
	FieldRef *ObjectFieldSelector `json:"fieldRef" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ObjectFieldSelector selects an APIVersioned field of an object.
 | 
			
		||||
 
 | 
			
		||||
@@ -322,7 +322,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
				Env: []current.EnvVar{
 | 
			
		||||
					{
 | 
			
		||||
						ValueFrom: ¤t.EnvVarSource{
 | 
			
		||||
							FieldPath: ¤t.ObjectFieldSelector{},
 | 
			
		||||
							FieldRef: ¤t.ObjectFieldSelector{},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
@@ -335,7 +335,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
	sList2 := obj2.(*current.ContainerManifestList)
 | 
			
		||||
	s2 := sList2.Items[0]
 | 
			
		||||
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldPath.APIVersion
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldRef.APIVersion
 | 
			
		||||
	if apiVersion != "v1beta1" {
 | 
			
		||||
		t.Errorf("Expected default APIVersion v1beta1, got: %v", apiVersion)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -414,7 +414,7 @@ type EnvVar struct {
 | 
			
		||||
// EnvVarSource represents a source for the value of an EnvVar.
 | 
			
		||||
type EnvVarSource struct {
 | 
			
		||||
	// Required: Selects a field of the pod; only name and namespace are supported.
 | 
			
		||||
	FieldPath *ObjectFieldSelector `json:"fieldPath" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
	FieldRef *ObjectFieldSelector `json:"fieldRef" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ObjectFieldSelector selects an APIVersioned field of an object.
 | 
			
		||||
 
 | 
			
		||||
@@ -321,7 +321,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
				Env: []current.EnvVar{
 | 
			
		||||
					{
 | 
			
		||||
						ValueFrom: ¤t.EnvVarSource{
 | 
			
		||||
							FieldPath: ¤t.ObjectFieldSelector{},
 | 
			
		||||
							FieldRef: ¤t.ObjectFieldSelector{},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
@@ -334,7 +334,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
	sList2 := obj2.(*current.ContainerManifestList)
 | 
			
		||||
	s2 := sList2.Items[0]
 | 
			
		||||
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldPath.APIVersion
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldRef.APIVersion
 | 
			
		||||
	if apiVersion != "v1beta2" {
 | 
			
		||||
		t.Errorf("Expected default APIVersion v1beta2, got: %v", apiVersion)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -391,7 +391,7 @@ type EnvVar struct {
 | 
			
		||||
// EnvVarSource represents a source for the value of an EnvVar.
 | 
			
		||||
type EnvVarSource struct {
 | 
			
		||||
	// Required: Selects a field of the pod; only name and namespace are supported.
 | 
			
		||||
	FieldPath *ObjectFieldSelector `json:"fieldPath" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
	FieldRef *ObjectFieldSelector `json:"fieldRef" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ObjectFieldSelector selects an APIVersioned field of an object.
 | 
			
		||||
 
 | 
			
		||||
@@ -632,14 +632,14 @@ func convert_api_EnvVar_To_v1beta3_EnvVar(in *newer.EnvVar, out *EnvVar, s conve
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convert_v1beta3_EnvVarSource_To_api_EnvVarSource(in *EnvVarSource, out *newer.EnvVarSource, s conversion.Scope) error {
 | 
			
		||||
	if err := s.Convert(&in.FieldPath, &out.FieldPath, 0); err != nil {
 | 
			
		||||
	if err := s.Convert(&in.FieldRef, &out.FieldRef, 0); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convert_api_EnvVarSource_To_v1beta3_EnvVarSource(in *newer.EnvVarSource, out *EnvVarSource, s conversion.Scope) error {
 | 
			
		||||
	if err := s.Convert(&in.FieldPath, &out.FieldPath, 0); err != nil {
 | 
			
		||||
	if err := s.Convert(&in.FieldRef, &out.FieldRef, 0); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
 
 | 
			
		||||
@@ -330,7 +330,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
				Env: []current.EnvVar{
 | 
			
		||||
					{
 | 
			
		||||
						ValueFrom: ¤t.EnvVarSource{
 | 
			
		||||
							FieldPath: ¤t.ObjectFieldSelector{},
 | 
			
		||||
							FieldRef: ¤t.ObjectFieldSelector{},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
@@ -344,7 +344,7 @@ func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
 | 
			
		||||
	pod2 := obj2.(*current.Pod)
 | 
			
		||||
	s2 := pod2.Spec
 | 
			
		||||
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldPath.APIVersion
 | 
			
		||||
	apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldRef.APIVersion
 | 
			
		||||
	if apiVersion != "v1beta3" {
 | 
			
		||||
		t.Errorf("Expected default APIVersion v1beta3, got: %v", apiVersion)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -529,7 +529,7 @@ type EnvVar struct {
 | 
			
		||||
// EnvVarSource represents a source for the value of an EnvVar.
 | 
			
		||||
type EnvVarSource struct {
 | 
			
		||||
	// Required: Selects a field of the pod; only name and namespace are supported.
 | 
			
		||||
	FieldPath *ObjectFieldSelector `json:"fieldPath" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
	FieldRef *ObjectFieldSelector `json:"fieldRef" description:"selects a field of the pod; only name and namespace are supported"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ObjectFieldSelector selects an APIVersioned field of an object.
 | 
			
		||||
 
 | 
			
		||||
@@ -591,9 +591,9 @@ func validateEnvVarValueFrom(ev api.EnvVar) errs.ValidationErrorList {
 | 
			
		||||
	numSources := 0
 | 
			
		||||
 | 
			
		||||
	switch {
 | 
			
		||||
	case ev.ValueFrom.FieldPath != nil:
 | 
			
		||||
	case ev.ValueFrom.FieldRef != nil:
 | 
			
		||||
		numSources++
 | 
			
		||||
		allErrs = append(allErrs, validateObjectFieldSelector(ev.ValueFrom.FieldPath).Prefix("fieldPath")...)
 | 
			
		||||
		allErrs = append(allErrs, validateObjectFieldSelector(ev.ValueFrom.FieldRef).Prefix("fieldRef")...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ev.Value != "" && numSources != 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -636,7 +636,7 @@ func TestValidateEnv(t *testing.T) {
 | 
			
		||||
		{
 | 
			
		||||
			Name: "abc",
 | 
			
		||||
			ValueFrom: &api.EnvVarSource{
 | 
			
		||||
				FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
				FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
					APIVersion: "v1beta3",
 | 
			
		||||
					FieldPath:  "metadata.name",
 | 
			
		||||
				},
 | 
			
		||||
@@ -668,7 +668,7 @@ func TestValidateEnv(t *testing.T) {
 | 
			
		||||
				Name:  "abc",
 | 
			
		||||
				Value: "foo",
 | 
			
		||||
				ValueFrom: &api.EnvVarSource{
 | 
			
		||||
					FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
					FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
						APIVersion: "v1beta3",
 | 
			
		||||
						FieldPath:  "metadata.name",
 | 
			
		||||
					},
 | 
			
		||||
@@ -681,50 +681,50 @@ func TestValidateEnv(t *testing.T) {
 | 
			
		||||
			envs: []api.EnvVar{{
 | 
			
		||||
				Name: "abc",
 | 
			
		||||
				ValueFrom: &api.EnvVarSource{
 | 
			
		||||
					FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
					FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
						APIVersion: "v1beta3",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldPath.fieldPath: required value",
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldRef.fieldPath: required value",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "missing APIVersion on ObjectFieldSelector",
 | 
			
		||||
			envs: []api.EnvVar{{
 | 
			
		||||
				Name: "abc",
 | 
			
		||||
				ValueFrom: &api.EnvVarSource{
 | 
			
		||||
					FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
					FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
						FieldPath: "metadata.name",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldPath.apiVersion: required value",
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldRef.apiVersion: required value",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid fieldPath",
 | 
			
		||||
			envs: []api.EnvVar{{
 | 
			
		||||
				Name: "abc",
 | 
			
		||||
				ValueFrom: &api.EnvVarSource{
 | 
			
		||||
					FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
					FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
						FieldPath:  "metadata.whoops",
 | 
			
		||||
						APIVersion: "v1beta3",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldPath.fieldPath: invalid value 'metadata.whoops': error converting fieldPath",
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldRef.fieldPath: invalid value 'metadata.whoops': error converting fieldPath",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "unsupported fieldPath",
 | 
			
		||||
			envs: []api.EnvVar{{
 | 
			
		||||
				Name: "abc",
 | 
			
		||||
				ValueFrom: &api.EnvVarSource{
 | 
			
		||||
					FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
					FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
						FieldPath:  "status.phase",
 | 
			
		||||
						APIVersion: "v1beta3",
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			}},
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldPath.fieldPath: unsupported value 'status.phase'",
 | 
			
		||||
			expectedError: "[0].valueFrom.fieldRef.fieldPath: unsupported value 'status.phase'",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range errorCases {
 | 
			
		||||
 
 | 
			
		||||
@@ -795,8 +795,8 @@ func (kl *Kubelet) runtimeEnvVarValue(envVar api.EnvVar, pod *api.Pod) (string,
 | 
			
		||||
		return runtimeVal, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if envVar.ValueFrom != nil && envVar.ValueFrom.FieldPath != nil {
 | 
			
		||||
		return kl.podFieldSelectorRuntimeValue(envVar.ValueFrom.FieldPath, pod)
 | 
			
		||||
	if envVar.ValueFrom != nil && envVar.ValueFrom.FieldRef != nil {
 | 
			
		||||
		return kl.podFieldSelectorRuntimeValue(envVar.ValueFrom.FieldRef, pod)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return runtimeVal, nil
 | 
			
		||||
 
 | 
			
		||||
@@ -2181,7 +2181,7 @@ func TestMakeEnvironmentVariables(t *testing.T) {
 | 
			
		||||
					{
 | 
			
		||||
						Name: "POD_NAME",
 | 
			
		||||
						ValueFrom: &api.EnvVarSource{
 | 
			
		||||
							FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
							FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
								APIVersion: "v1beta3",
 | 
			
		||||
								FieldPath:  "metadata.name",
 | 
			
		||||
							},
 | 
			
		||||
@@ -2190,7 +2190,7 @@ func TestMakeEnvironmentVariables(t *testing.T) {
 | 
			
		||||
					{
 | 
			
		||||
						Name: "POD_NAMESPACE",
 | 
			
		||||
						ValueFrom: &api.EnvVarSource{
 | 
			
		||||
							FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
							FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
								APIVersion: "v1beta3",
 | 
			
		||||
								FieldPath:  "metadata.namespace",
 | 
			
		||||
							},
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ var _ = Describe("Downward API", func() {
 | 
			
		||||
							{
 | 
			
		||||
								Name: "POD_NAME",
 | 
			
		||||
								ValueFrom: &api.EnvVarSource{
 | 
			
		||||
									FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
									FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
										APIVersion: "v1beta3",
 | 
			
		||||
										FieldPath:  "metadata.name",
 | 
			
		||||
									},
 | 
			
		||||
@@ -75,7 +75,7 @@ var _ = Describe("Downward API", func() {
 | 
			
		||||
							{
 | 
			
		||||
								Name: "POD_NAMESPACE",
 | 
			
		||||
								ValueFrom: &api.EnvVarSource{
 | 
			
		||||
									FieldPath: &api.ObjectFieldSelector{
 | 
			
		||||
									FieldRef: &api.ObjectFieldSelector{
 | 
			
		||||
										APIVersion: "v1beta3",
 | 
			
		||||
										FieldPath:  "metadata.namespace",
 | 
			
		||||
									},
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user