Detect if tiller is running in hosted mode for Helm commands

pull/2150/head
tamal 9 years ago
parent 6506c145b6
commit 0dfae0adc1

@ -32,6 +32,7 @@ import (
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/helm/cmd/helm/installer"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/helm/portforwarder" "k8s.io/helm/pkg/helm/portforwarder"
@ -58,6 +59,7 @@ var (
var ( var (
helmHome string helmHome string
tillerHost string tillerHost string
usesHostedTiller bool
tillerNamespace string tillerNamespace string
kubeContext string kubeContext string
// TODO refactor out this global var // TODO refactor out this global var
@ -184,16 +186,24 @@ func setupConnection(c *cobra.Command, args []string) error {
return err return err
} }
if externalName, err := installer.GetTillerExternalName(client, tillerNamespace); err != nil {
return err
} else if externalName != "" {
tillerHost = externalName
usesHostedTiller = true
} else {
tunnel, err := portforwarder.New(tillerNamespace, client, config) tunnel, err := portforwarder.New(tillerNamespace, client, config)
if err != nil { if err != nil {
return err return err
} }
tillerTunnel = tunnel
tillerHost = fmt.Sprintf("localhost:%d", tunnel.Local) tillerHost = fmt.Sprintf("localhost:%d", tunnel.Local)
if flagDebug { if flagDebug {
fmt.Printf("Created tunnel using local port: '%d'\n", tunnel.Local) fmt.Printf("Created tunnel using local port: '%d'\n", tunnel.Local)
} }
} }
}
// Set up the gRPC config. // Set up the gRPC config.
if flagDebug { if flagDebug {

@ -230,10 +230,16 @@ func (i *initCmd) run() error {
return fmt.Errorf("error installing: %s", err) return fmt.Errorf("error installing: %s", err)
} }
if i.upgrade { if i.upgrade {
if externalName, err := installer.GetTillerExternalName(i.kubeClient, i.opts.Namespace); err != nil {
return fmt.Errorf("error detecting tiller mode: %s", err)
} else if externalName != "" {
fmt.Fprintf(i.out, "\nThis cluster uses hosted Tiller (the helm server side component) %v. Contact cluster operators regarding upgrading Tiller.\n", externalName)
} else {
if err := installer.Upgrade(i.kubeClient, &i.opts); err != nil { if err := installer.Upgrade(i.kubeClient, &i.opts); err != nil {
return fmt.Errorf("error when upgrading: %s", err) return fmt.Errorf("error when upgrading: %s", err)
} }
fmt.Fprintln(i.out, "\nTiller (the helm server side component) has been upgraded to the current version.") fmt.Fprintln(i.out, "\nTiller (the helm server side component) has been upgraded to the current version.")
}
} else { } else {
fmt.Fprintln(i.out, "Warning: Tiller is already installed in the cluster.\n"+ fmt.Fprintln(i.out, "Warning: Tiller is already installed in the cluster.\n"+
"(Use --client-only to suppress this message, or --upgrade to upgrade Tiller to the current version.)") "(Use --client-only to suppress this message, or --upgrade to upgrade Tiller to the current version.)")

@ -57,11 +57,11 @@ func TestInitCmd(t *testing.T) {
if len(actions) != 2 { if len(actions) != 2 {
t.Errorf("Expected 2 actions, got %d", len(actions)) t.Errorf("Expected 2 actions, got %d", len(actions))
} }
if !actions[0].Matches("create", "deployments") { if !actions[0].Matches("create", "services") {
t.Errorf("unexpected action: %v, expected create deployment", actions[0]) t.Errorf("unexpected action: %v, expected create service", actions[0])
} }
if !actions[1].Matches("create", "services") { if !actions[1].Matches("create", "deployments") {
t.Errorf("unexpected action: %v, expected create service", actions[1]) t.Errorf("unexpected action: %v, expected create deployment", actions[1])
} }
expected := "Tiller (the helm server side component) has been installed into your Kubernetes Cluster." expected := "Tiller (the helm server side component) has been installed into your Kubernetes Cluster."
if !strings.Contains(buf.String(), expected) { if !strings.Contains(buf.String(), expected) {

@ -17,6 +17,7 @@ limitations under the License.
package installer // import "k8s.io/helm/cmd/helm/installer" package installer // import "k8s.io/helm/cmd/helm/installer"
import ( import (
"errors"
"io/ioutil" "io/ioutil"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
@ -34,10 +35,11 @@ import (
// //
// Returns an error if the command failed. // Returns an error if the command failed.
func Install(client internalclientset.Interface, opts *Options) error { func Install(client internalclientset.Interface, opts *Options) error {
if err := createDeployment(client.Extensions(), opts); err != nil { // create service first. If cluster is using hosted Tiller, this will error out and actual deployment will not be created.
if err := createService(client.Core(), opts.Namespace); err != nil {
return err return err
} }
if err := createService(client.Core(), opts.Namespace); err != nil { if err := createDeployment(client.Extensions(), opts); err != nil {
return err return err
} }
if opts.tls() { if opts.tls() {
@ -92,6 +94,19 @@ func createService(client internalversion.ServicesGetter, namespace string) erro
return err return err
} }
// GetTillerExternalName returns the configured external name of a hosted Tiller server.
func GetTillerExternalName(client internalclientset.Interface, namespace string) (string, error) {
if svc, err := client.Core().Services(namespace).Get("tiller-deploy"); err != nil {
return "", err
} else if svc.Spec.Type == api.ServiceTypeExternalName {
if svc.Spec.ExternalName == "" {
return "", errors.New("Missing external name of hosted Tiller")
}
return svc.Spec.ExternalName, nil
}
return "", nil
}
// service gets the service object that installs Tiller. // service gets the service object that installs Tiller.
func service(namespace string) *api.Service { func service(namespace string) *api.Service {
return generateService(namespace) return generateService(namespace)

Loading…
Cancel
Save