Merge pull request #6739 from pmorie/downward-api

Env var sources / downward API
This commit is contained in:
Brian Grant
2015-04-27 12:46:00 -07:00
21 changed files with 674 additions and 17 deletions

View File

@@ -36,6 +36,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record"
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fieldpath"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
kubecontainer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/container"
@@ -702,7 +703,7 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Cont
return nil, fmt.Errorf("impossible: cannot find the mounted volumes for pod %q", kubecontainer.GetPodFullName(pod))
}
opts.Binds = makeBinds(container, vol)
opts.Envs, err = kl.makeEnvironmentVariables(pod.Namespace, container)
opts.Envs, err = kl.makeEnvironmentVariables(pod, container)
if err != nil {
return nil, err
}
@@ -780,7 +781,7 @@ func (kl *Kubelet) getServiceEnvVarMap(ns string) (map[string]string, error) {
}
// Make the service environment variables for a pod in the given namespace.
func (kl *Kubelet) makeEnvironmentVariables(ns string, container *api.Container) ([]string, error) {
func (kl *Kubelet) makeEnvironmentVariables(pod *api.Pod, container *api.Container) ([]string, error) {
var result []string
// Note: These are added to the docker.Config, but are not included in the checksum computed
// by dockertools.BuildDockerName(...). That way, we can still determine whether an
@@ -791,7 +792,7 @@ func (kl *Kubelet) makeEnvironmentVariables(ns string, container *api.Container)
// To avoid this users can: (1) wait between starting a service and starting; or (2) detect
// missing service env var and exit and be restarted; or (3) use DNS instead of env vars
// and keep trying to resolve the DNS name of the service (recommended).
serviceEnv, err := kl.getServiceEnvVarMap(ns)
serviceEnv, err := kl.getServiceEnvVarMap(pod.Namespace)
if err != nil {
return result, err
}
@@ -803,7 +804,13 @@ func (kl *Kubelet) makeEnvironmentVariables(ns string, container *api.Container)
// env vars.
// TODO: remove this net line once all platforms use apiserver+Pods.
delete(serviceEnv, value.Name)
result = append(result, fmt.Sprintf("%s=%s", value.Name, value.Value))
runtimeValue, err := kl.runtimeEnvVarValue(value, pod)
if err != nil {
return result, err
}
result = append(result, fmt.Sprintf("%s=%s", value.Name, runtimeValue))
}
// Append remaining service env vars.
@@ -813,6 +820,33 @@ func (kl *Kubelet) makeEnvironmentVariables(ns string, container *api.Container)
return result, nil
}
// runtimeEnvVarValue determines the value that an env var should take when a container
// is started. If the value of the env var is the empty string, the source of the env var
// is resolved, if one is specified.
//
// TODO: preliminary factoring; make better
func (kl *Kubelet) runtimeEnvVarValue(envVar api.EnvVar, pod *api.Pod) (string, error) {
runtimeVal := envVar.Value
if runtimeVal != "" {
return runtimeVal, nil
}
if envVar.ValueFrom != nil && envVar.ValueFrom.FieldPath != nil {
return kl.podFieldSelectorRuntimeValue(envVar.ValueFrom.FieldPath, pod)
}
return runtimeVal, nil
}
func (kl *Kubelet) podFieldSelectorRuntimeValue(fs *api.ObjectFieldSelector, pod *api.Pod) (string, error) {
internalFieldPath, _, err := api.Scheme.ConvertFieldLabel(fs.APIVersion, "Pod", fs.FieldPath, "")
if err != nil {
return "", err
}
return fieldpath.ExtractFieldPathAsString(pod, internalFieldPath)
}
// getClusterDNS returns a list of the DNS servers and a list of the DNS search
// domains of the cluster.
func (kl *Kubelet) getClusterDNS(pod *api.Pod) ([]string, []string, error) {

View File

@@ -68,6 +68,8 @@ type TestKubelet struct {
fakeMirrorClient *fakeMirrorClient
}
const testKubeletHostname = "testnode"
func newTestKubelet(t *testing.T) *TestKubelet {
fakeDocker := &dockertools.FakeDockerClient{Errors: make(map[string]error), RemovedImages: util.StringSet{}}
fakeRecorder := &record.FakeRecorder{}
@@ -2378,6 +2380,39 @@ func TestMakeEnvironmentVariables(t *testing.T) {
"KUBERNETES_RO_PORT_8087_TCP_ADDR=1.2.3.7"),
21,
},
{
"downward api pod",
"downward-api",
&api.Container{
Env: []api.EnvVar{
{
Name: "POD_NAME",
ValueFrom: &api.EnvVarSource{
FieldPath: &api.ObjectFieldSelector{
APIVersion: "v1beta3",
FieldPath: "metadata.name",
},
},
},
{
Name: "POD_NAMESPACE",
ValueFrom: &api.EnvVarSource{
FieldPath: &api.ObjectFieldSelector{
APIVersion: "v1beta3",
FieldPath: "metadata.namespace",
},
},
},
},
},
"nothing",
true,
util.NewStringSet(
"POD_NAME=dapi-test-pod-name",
"POD_NAMESPACE=downward-api",
),
2,
},
}
for _, tc := range testCases {
@@ -2390,7 +2425,14 @@ func TestMakeEnvironmentVariables(t *testing.T) {
kl.serviceLister = testServiceLister{services}
}
result, err := kl.makeEnvironmentVariables(tc.ns, tc.container)
testPod := &api.Pod{
ObjectMeta: api.ObjectMeta{
Namespace: tc.ns,
Name: "dapi-test-pod-name",
},
}
result, err := kl.makeEnvironmentVariables(testPod, tc.container)
if err != nil {
t.Errorf("[%v] Unexpected error: %v", tc.name, err)
}