diff --git a/cmd/helm/init.go b/cmd/helm/init.go index 425c10074..4be54e675 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -274,7 +274,7 @@ func (i *initCmd) run() error { if err := installer.Upgrade(i.kubeClient, &i.opts); err != nil { return fmt.Errorf("error when upgrading: %s", err) } - if err := i.ping(); err != nil { + if err := i.ping(i.opts.SelectImage()); err != nil { return err } fmt.Fprintln(i.out, "\nTiller (the Helm server-side component) has been upgraded to the current version.") @@ -290,7 +290,7 @@ func (i *initCmd) run() error { "For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation") } } - if err := i.ping(); err != nil { + if err := i.ping(i.opts.SelectImage()); err != nil { return err } } else { @@ -301,13 +301,13 @@ func (i *initCmd) run() error { return nil } -func (i *initCmd) ping() error { +func (i *initCmd) ping(image string) error { if i.wait { _, kubeClient, err := getKubeClient(settings.KubeContext, settings.KubeConfig) if err != nil { return err } - if !watchTillerUntilReady(settings.TillerNamespace, kubeClient, settings.TillerConnectionTimeout) { + if !watchTillerUntilReady(settings.TillerNamespace, kubeClient, settings.TillerConnectionTimeout, image) { return fmt.Errorf("tiller was not found. polling deadline exceeded") } @@ -439,7 +439,7 @@ func ensureRepoFileFormat(file string, out io.Writer) error { // want to wait before we call New(). // // Returns true if it exists. If the timeout was reached and it could not find the pod, it returns false. -func watchTillerUntilReady(namespace string, client kubernetes.Interface, timeout int64) bool { +func watchTillerUntilReady(namespace string, client kubernetes.Interface, timeout int64, newImage string) bool { deadlinePollingChan := time.NewTimer(time.Duration(timeout) * time.Second).C checkTillerPodTicker := time.NewTicker(500 * time.Millisecond) doneChan := make(chan bool) @@ -448,8 +448,8 @@ func watchTillerUntilReady(namespace string, client kubernetes.Interface, timeou go func() { for range checkTillerPodTicker.C { - _, err := portforwarder.GetTillerPodName(client.CoreV1(), namespace) - if err == nil { + image, err := portforwarder.GetTillerPodImage(client.CoreV1(), namespace) + if err == nil && image == newImage { doneChan <- true break } diff --git a/cmd/helm/installer/install.go b/cmd/helm/installer/install.go index c9ba1b0ca..6027fdba8 100644 --- a/cmd/helm/installer/install.go +++ b/cmd/helm/installer/install.go @@ -68,7 +68,7 @@ func Upgrade(client kubernetes.Interface, opts *Options) error { if semverCompare(tillerImage) == -1 && !opts.ForceUpgrade { return errors.New("current Tiller version is newer, use --force-upgrade to downgrade") } - obj.Spec.Template.Spec.Containers[0].Image = opts.selectImage() + obj.Spec.Template.Spec.Containers[0].Image = opts.SelectImage() obj.Spec.Template.Spec.Containers[0].ImagePullPolicy = opts.pullPolicy() obj.Spec.Template.Spec.ServiceAccountName = opts.ServiceAccount if _, err := client.ExtensionsV1beta1().Deployments(opts.Namespace).Update(obj); err != nil { @@ -223,7 +223,7 @@ func generateDeployment(opts *Options) (*v1beta1.Deployment, error) { Containers: []v1.Container{ { Name: "tiller", - Image: opts.selectImage(), + Image: opts.SelectImage(), ImagePullPolicy: opts.pullPolicy(), Ports: []v1.ContainerPort{ {ContainerPort: 44134, Name: "tiller"}, diff --git a/cmd/helm/installer/options.go b/cmd/helm/installer/options.go index 729bdf20b..196ad8de4 100644 --- a/cmd/helm/installer/options.go +++ b/cmd/helm/installer/options.go @@ -99,7 +99,8 @@ type Options struct { Values []string } -func (opts *Options) selectImage() string { +// SelectImage returns the image according to whether UseCanary is true or not +func (opts *Options) SelectImage() string { switch { case opts.UseCanary: return defaultImage + ":canary" diff --git a/pkg/helm/portforwarder/portforwarder.go b/pkg/helm/portforwarder/portforwarder.go index cc3261d1c..e962eef7f 100644 --- a/pkg/helm/portforwarder/portforwarder.go +++ b/pkg/helm/portforwarder/portforwarder.go @@ -54,6 +54,21 @@ func GetTillerPodName(client corev1.PodsGetter, namespace string) (string, error return pod.ObjectMeta.GetName(), nil } +// GetTillerPodImage fetches the image of tiller pod running in the given namespace. +func GetTillerPodImage(client corev1.PodsGetter, namespace string) (string, error) { + selector := tillerPodLabels.AsSelector() + pod, err := getFirstRunningPod(client, namespace, selector) + if err != nil { + return "", err + } + for _, c := range pod.Spec.Containers { + if c.Name == "tiller" { + return c.Image, nil + } + } + return "", fmt.Errorf("could not find a tiller pod") +} + func getFirstRunningPod(client corev1.PodsGetter, namespace string, selector labels.Selector) (*v1.Pod, error) { options := metav1.ListOptions{LabelSelector: selector.String()} pods, err := client.Pods(namespace).List(options)