Commit 49491a8a authored by Adam Reese's avatar Adam Reese
Browse files

fix(cmd): ensure tiller is running for connection

Fixes: https://github.com/kubernetes/helm/issues/981
parent 877d9b28
main Release add-codeql dependabot/go_modules/github.com/docker/distribution-2.8.2incompatible dependabot/go_modules/github.com/lib/pq-1.10.9 dependabot/go_modules/github.com/rubenv/sql-migrate-1.4.0 dependabot/go_modules/golang.org/x/crypto-0.9.0 dependabot/go_modules/golang.org/x/term-0.8.0 dependabot/go_modules/k8s.io/klog/v2-2.100.1 dev-v2 feat-v3/event-emitter-lua kube-update-test release-2.0 release-2.1 release-2.10 release-2.11 release-2.12 release-2.13 release-2.14 release-2.15 release-2.16 release-2.17 release-2.2 release-2.3 release-2.4 release-2.5 release-2.6 release-2.7 release-2.8 release-2.9 release-3.0 release-3.1 release-3.10 release-3.11 release-3.12 release-3.2 release-3.3 release-3.4 release-3.5 release-3.6 release-3.6.1 release-3.6.2 release-3.7 release-3.8 release-3.9 release-v3.0.0-beta.4 v3.12.0 v3.12.0-rc.1 v3.12.0-dev.1 v3.11.3 v3.11.2 v3.11.1 v3.11.0 v3.11.0-rc.2 v3.11.0-rc.1 v3.10.3 v3.10.2 v3.10.1 v3.10.0 v3.10.0-rc.1 v3.9.4 v3.9.3 v3.9.2 v3.9.1 v3.9.0 v3.9.0-rc.1 v3.8.2 v3.8.1 v3.8.0 v3.8.0-rc.2 v3.8.0-rc.1 v3.7.2 v3.7.1 v3.7.0 v3.7.0-rc.3 v3.7.0-rc.2 v3.7.0-rc.1 v3.6.3 v3.6.2 v3.6.1 v3.6.0 v3.6.0-rc.1 v3.5.4 v3.5.3 v3.5.2 v3.5.1 v3.5.0 v3.5.0-rc.2 v3.5.0-rc.1 v3.4.2 v3.4.1 v3.4.0 v3.4.0-rc.1 v3.3.4 v3.3.3 v3.3.2 v3.3.1 v3.3.0 v3.3.0-rc.2 v3.3.0-rc.1 v3.2.4 v3.2.3 v3.2.2 v3.2.1 v3.2.0 v3.2.0-rc.1 v3.1.3 v3.1.2 v3.1.1 v3.1.0 v3.1.0-rc.3 v3.1.0-rc.2 v3.1.0-rc.1 v3.0.3 v3.0.2 v3.0.1 v3.0.0 v3.0.0-rc.4 v3.0.0-rc.3 v3.0.0-rc.2 v3.0.0-rc.1 v3.0.0-beta.5 v3.0.0-beta.4 v3.0.0-beta.3 v3.0.0-beta.2 v3.0.0-beta.1 v3.0.0-alpha.2 v3.0.0-alpha.1 v2.17.0 v2.17.0-rc.1 v2.16.12 v2.16.11 v2.16.10 v2.16.9 v2.16.8 v2.16.7 v2.16.6 v2.16.5 v2.16.4 v2.16.3 v2.16.2 v2.16.1 v2.16.0 v2.16.0-rc.2 v2.16.0-rc.1 v2.15.2 v2.15.1 v2.15.0 v2.15.0-rc.2 v2.15.0-rc.1 v2.14.3 v2.14.2 v2.14.1 v2.14.0 v2.14.0-rc.2 v2.14.0-rc.1 v2.13.1 v2.13.1-rc.1 v2.13.0 v2.13.0-rc.2 v2.13.0-rc.1 v2.12.3 v2.12.2 v2.12.1 v2.12.0 v2.12.0-rc.2 v2.12.0-rc.1 v2.11.0 v2.11.0-rc.4 v2.11.0-rc.3 v2.11.0-rc.2 v2.11.0-rc.1 v2.10.0 v2.10.0-rc.3 v2.10.0-rc.2 v2.10.0-rc.1 v2.9.1 v2.9.0 v2.9.0-rc5 v2.9.0-rc4 v2.9.0-rc3 v2.9.0-rc2 v2.9.0-rc1 v2.8.2 v2.8.2-rc1 v2.8.1 v2.8.0 v2.8.0-rc.1 v2.7.2 v2.7.1 v2.7.0 v2.7.0-rc1 v2.6.2 v2.6.1 v2.6.0 v2.5.1 v2.5.0 v2.4.2 v2.4.1 v2.4.0 v2.3.1 v2.3.0 v2.2.3 v2.2.2 v2.2.1 v2.2.0 v2.1.3 v2.1.2 v2.1.1 v2.1.0 v2.0.2 v2.0.1 v2.0.0 v2.0.0-rc.2 v2.0.0-rc.1 v2.0.0-beta.2 v2.0.0-beta.1 v2.0.0-alpha.5 v2.0.0-alpha.4 v2.0.0-alpha.3
No related merge requests found
Showing with 115 additions and 10 deletions
+115 -10
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"
...@@ -29,30 +30,43 @@ import ( ...@@ -29,30 +30,43 @@ import (
var tunnel *kube.Tunnel var tunnel *kube.Tunnel
func newTillerPortForwarder(namespace string) (*kube.Tunnel, error) { func newTillerPortForwarder(namespace string) (*kube.Tunnel, error) {
podName, err := getTillerPodName(namespace) kc := kube.New(nil)
client, err := kc.Client()
if err != nil {
return nil, err
}
podName, err := getTillerPodName(client, namespace)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// FIXME use a constain that is accessible on init
const tillerPort = 44134 const tillerPort = 44134
return kube.New(nil).ForwardPort(namespace, podName, tillerPort) return kc.ForwardPort(namespace, podName, tillerPort)
} }
func getTillerPodName(namespace string) (string, error) { func getTillerPodName(client unversioned.PodsNamespacer, namespace string) (string, error) {
client, err := kube.New(nil).Client() // TODO use a const for labels
selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector()
pod, err := getFirstRunningPod(client, namespace, selector)
if err != nil { if err != nil {
return "", err return "", err
} }
return pod.ObjectMeta.GetName(), nil
}
// TODO use a const for labels func getFirstRunningPod(client unversioned.PodsNamespacer, namespace string, selector labels.Selector) (*api.Pod, error) {
selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector()
options := api.ListOptions{LabelSelector: selector} options := api.ListOptions{LabelSelector: selector}
pods, err := client.Pods(namespace).List(options) pods, err := client.Pods(namespace).List(options)
if err != nil { if err != nil {
return "", err return nil, err
} }
if len(pods.Items) < 1 { if len(pods.Items) < 1 {
return "", fmt.Errorf("I could not find tiller") return nil, fmt.Errorf("could not find tiller")
}
for _, p := range pods.Items {
if api.IsPodReady(&p) {
return &p, nil
}
} }
return pods.Items[0].ObjectMeta.GetName(), nil return nil, fmt.Errorf("could not find a ready pod")
} }
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
"k8s.io/kubernetes/pkg/runtime"
)
func mockTillerPod() api.Pod {
return api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "orca",
Namespace: api.NamespaceDefault,
Labels: map[string]string{"app": "helm", "name": "tiller"},
},
Status: api.PodStatus{
Phase: api.PodRunning,
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
}
}
func mockTillerPodPending() api.Pod {
p := mockTillerPod()
p.Name = "blue"
p.Status.Conditions[0].Status = api.ConditionFalse
return p
}
func TestGetFirstPod(t *testing.T) {
tests := []struct {
name string
pods []api.Pod
expected string
err bool
}{
{
name: "with a ready pod",
pods: []api.Pod{mockTillerPod()},
expected: "orca",
},
{
name: "without a ready pod",
pods: []api.Pod{mockTillerPodPending()},
err: true,
},
{
name: "without a pod",
pods: []api.Pod{},
err: true,
},
}
for _, tt := range tests {
client := &testclient.Fake{}
client.PrependReactor("list", "pods", func(action testclient.Action) (handled bool, ret runtime.Object, err error) {
return true, &api.PodList{Items: tt.pods}, nil
})
name, err := getTillerPodName(client, api.NamespaceDefault)
if (err != nil) != tt.err {
t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err)
}
if name != tt.expected {
t.Errorf("%q. expected %q, got %q", tt.name, tt.expected, name)
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment