func waitForPodEnd(pw *k8s.PodWatcher, ns, podName string, interval, timeout time.Duration) error {
	condition := func(pod *api.Pod) (bool, error) {
		if pod.Status.Phase == api.PodSucceeded {
			return true, nil
		}
		if pod.Status.Phase == api.PodFailed {
			return true, nil
		}
		return false, nil
	}
	return waitForPodCondition(pw, ns, podName, condition, interval, timeout)
}
waitForPodEnd waits for a pod in state succeeded or failed
package gitreceive
import (
	"encoding/json"
	"fmt"
	"time"
	"github.com/deis/builder/pkg/k8s"
	"github.com/pborman/uuid"
	"k8s.io/kubernetes/pkg/api"
	apierrors "k8s.io/kubernetes/pkg/api/errors"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/pkg/util/wait"
)
const (
	slugBuilderName   = "deis-slugbuilder"
	dockerBuilderName = "deis-dockerbuilder"
	tarPath          = "TAR_PATH"
	putPath          = "PUT_PATH"
	cachePath        = "CACHE_PATH"
	debugKey         = "DEIS_DEBUG"
	sourceVersion    = "SOURCE_VERSION"
	objectStore      = "objectstorage-keyfile"
	dockerSocketName = "docker-socket"
	dockerSocketPath = "/var/run/docker.sock"
	builderStorage   = "BUILDER_STORAGE"
	objectStorePath  = "/var/run/secrets/deis/objectstore/creds"
	envRoot          = "/tmp/env"
)
func dockerBuilderPodName(appName, shortSha string) string {
	uid := uuid.New()[:8]
	if len(appName) > 33 {
		appName = appName[:33]
	}
	return fmt.Sprintf("dockerbuild-%s-%s-%s", appName, shortSha, uid)
}
func slugBuilderPodName(appName, shortSha string) string {
	uid := uuid.New()[:8]
	if len(appName) > 35 {
		appName = appName[:35]
	}
	return fmt.Sprintf("slugbuild-%s-%s-%s", appName, shortSha, uid)
}
func dockerBuilderPod(
	debug bool,
	name,
	namespace string,
	env map[string]interface{},
	tarKey,
	gitShortHash string,
	imageName,
	storageType,
	image,
	registryHost,
	registryPort string,
	registryEnv map[string]string,
	pullPolicy api.PullPolicy,
	nodeSelector map[string]string,
) *api.Pod {
	pod := buildPod(debug, name, namespace, pullPolicy, nodeSelector, env)
	if _, ok := env["DEIS_DOCKER_BUILD_ARGS_ENABLED"]; ok {
		dockerBuildArgs, _ := json.Marshal(env)
		addEnvToPod(pod, "DOCKER_BUILD_ARGS", string(dockerBuildArgs))
	}
	pod.Spec.Containers[0].Name = dockerBuilderName
	pod.Spec.Containers[0].Image = image
	addEnvToPod(pod, tarPath, tarKey)
	addEnvToPod(pod, sourceVersion, gitShortHash)
	addEnvToPod(pod, "IMG_NAME", imageName)
	addEnvToPod(pod, builderStorage, storageType)
	addEnvToPod(pod, "DEIS_REGISTRY_SERVICE_HOST", registryHost)
	addEnvToPod(pod, "DEIS_REGISTRY_SERVICE_PORT", registryPort)
	for key, value := range registryEnv {
		addEnvToPod(pod, key, value)
	}
	pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, api.VolumeMount{
		Name:      dockerSocketName,
		MountPath: dockerSocketPath,
	})
	pod.Spec.Volumes = append(pod.Spec.Volumes, api.Volume{
		Name: dockerSocketName,
		VolumeSource: api.VolumeSource{
			HostPath: &api.HostPathVolumeSource{
				Path: dockerSocketPath,
			},
		},
	})
	return &pod
}
func slugbuilderPod(
	debug bool,
	name,
	namespace string,
	envSecretName string,
	tarKey,
	putKey,
	cacheKey,
	gitShortHash string,
	buildpackURL,
	storageType,
	image string,
	pullPolicy api.PullPolicy,
	nodeSelector map[string]string,
) *api.Pod {
	pod := buildPod(debug, name, namespace, pullPolicy, nodeSelector, nil)
	pod.Spec.Volumes = append(pod.Spec.Volumes, api.Volume{
		Name: envSecretName,
		VolumeSource: api.VolumeSource{
			Secret: &api.SecretVolumeSource{
				SecretName: envSecretName,
			},
		},
	})
	pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, api.VolumeMount{
		Name:      envSecretName,
		MountPath: envRoot,
		ReadOnly:  true,
	})
	pod.Spec.Containers[0].Name = slugBuilderName
	pod.Spec.Containers[0].Image = image
	if cacheKey != "" {
		addEnvToPod(pod, cachePath, cacheKey)
	}
	addEnvToPod(pod, tarPath, tarKey)
	addEnvToPod(pod, putPath, putKey)
	addEnvToPod(pod, sourceVersion, gitShortHash)
	addEnvToPod(pod, builderStorage, storageType)
	if buildpackURL != "" {
		addEnvToPod(pod, "BUILDPACK_URL", buildpackURL)
	}
	return &pod
}
func buildPod(
	debug bool,
	name,
	namespace string,
	pullPolicy api.PullPolicy,
	nodeSelector map[string]string,
	env map[string]interface{}) api.Pod {
	pod := api.Pod{
		Spec: api.PodSpec{
			RestartPolicy: api.RestartPolicyNever,
			Containers: []api.Container{
				{
					ImagePullPolicy: pullPolicy,
				},
			},
			Volumes: []api.Volume{},
		},
		ObjectMeta: api.ObjectMeta{
			Name:      name,
			Namespace: namespace,
			Labels: map[string]string{
				"heritage": name,
			},
		},
	}
	pod.Spec.Volumes = append(pod.Spec.Volumes, api.Volume{
		Name: objectStore,
		VolumeSource: api.VolumeSource{
			Secret: &api.SecretVolumeSource{
				SecretName: objectStore,
			},
		},
	})
	pod.Spec.Containers[0].VolumeMounts = []api.VolumeMount{
		{
			Name:      objectStore,
			MountPath: objectStorePath,
			ReadOnly:  true,
		},
	}
	if len(pod.Spec.Containers) > 0 {
		for k, v := range env {
			pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, api.EnvVar{
				Name:  k,
				Value: fmt.Sprintf("%v", v),
			})
		}
	}
	if len(nodeSelector) > 0 {
		pod.Spec.NodeSelector = nodeSelector
	}
	if debug {
		addEnvToPod(pod, debugKey, "1")
	}
	return pod
}
func addEnvToPod(pod api.Pod, key, value string) {
	if len(pod.Spec.Containers) > 0 {
		pod.Spec.Containers[0].Env = append(pod.Spec.Containers[0].Env, api.EnvVar{
			Name:  key,
			Value: value,
		})
	}
}
func waitForPod(pw *k8s.PodWatcher, ns, podName string, ticker, interval, timeout time.Duration) error {
	condition := func(pod *api.Pod) (bool, error) {
		if pod.Status.Phase == api.PodRunning {
			return true, nil
		}
		if pod.Status.Phase == api.PodSucceeded {
			return true, nil
		}
		if pod.Status.Phase == api.PodFailed {
			return true, fmt.Errorf("Giving up; pod went into failed status: \n[%s]:%s", pod.Status.Reason, pod.Status.Message)
		}
		return false, nil
	}
	quit := progress("...", ticker)
	err := waitForPodCondition(pw, ns, podName, condition, interval, timeout)
	quit <- true
	<-quit
	return err
}