diff --git a/cmd/helm/init.go b/cmd/helm/init.go index c8753874f..399802d97 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -23,16 +23,17 @@ import ( "fmt" "io" "os" + "time" "github.com/spf13/cobra" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/client-go/kubernetes" - "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/kubernetes" "k8s.io/helm/cmd/helm/installer" "k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm/helmpath" + "k8s.io/helm/pkg/helm/portforwarder" "k8s.io/helm/pkg/repo" ) @@ -87,6 +88,7 @@ type initCmd struct { serviceAccount string maxHistory int wait bool + timeout int } func newInitCmd(out io.Writer) *cobra.Command { @@ -102,10 +104,11 @@ func newInitCmd(out io.Writer) *cobra.Command { } i.namespace = settings.TillerNamespace i.home = settings.Home - i.client = ensureHelmClient(i.client) - return i.run() }, + PostRunE: func(cmd *cobra.Command, args []string) error { + return i.ensureTillerRunning() + }, } f := cmd.Flags() @@ -117,6 +120,7 @@ func newInitCmd(out io.Writer) *cobra.Command { f.BoolVar(&i.dryRun, "dry-run", false, "do not install local or remote") f.BoolVar(&i.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache") f.BoolVar(&i.wait, "wait", false, "block until Tiller is running and ready to receive requests") + f.IntVar(&i.timeout, "timeout", 10, "number of seconds to wait for tiller before timing out") f.BoolVar(&tlsEnable, "tiller-tls", false, "install Tiller with TLS enabled") f.BoolVar(&tlsVerify, "tiller-tls-verify", false, "install Tiller with TLS enabled and to verify remote certificates") @@ -298,18 +302,12 @@ 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 { - return err - } fmt.Fprintln(i.out, "\nTiller (the Helm server-side component) has been upgraded to the current version.") } else { 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.)") } } else { - if err := i.ping(); err != nil { - return err - } fmt.Fprintln(i.out, "\nTiller (the Helm server-side component) has been installed into your Kubernetes Cluster.") } } else { @@ -320,11 +318,27 @@ func (i *initCmd) run() error { return nil } -func (i *initCmd) ping() error { - if i.wait { - if err := i.client.PingTiller(); err != nil { - return fmt.Errorf("could not ping Tiller: %s", err) +func (i *initCmd) ensureTillerRunning() error { + if !i.wait { + return nil + } + + var retryCount int + +retry: + config, client, err := getKubeClient(settings.KubeContext) + if err != nil { + return err + } + + _, err = portforwarder.New(settings.TillerNamespace, client, config) + if err != nil { + if err == portforwarder.ErrTillerNotFound && retryCount <= i.timeout { + retryCount++ + time.Sleep(time.Second) + goto retry } + return err } return nil diff --git a/docs/helm/helm_init.md b/docs/helm/helm_init.md index 856e9b565..22f69b544 100644 --- a/docs/helm/helm_init.md +++ b/docs/helm/helm_init.md @@ -51,6 +51,7 @@ helm init --tiller-tls-cert string path to TLS certificate file to install with Tiller --tiller-tls-key string path to TLS key file to install with Tiller --tiller-tls-verify install Tiller with TLS enabled and to verify remote certificates + --timeout int number of seconds to wait for tiller before timing out (default 10) --tls-ca-cert string path to CA root certificate --upgrade upgrade if Tiller is already installed --wait block until Tiller is running and ready to receive requests @@ -69,4 +70,4 @@ helm init ### SEE ALSO * [helm](helm.md) - The Helm package manager for Kubernetes. -###### Auto generated by spf13/cobra on 25-Jan-2018 +###### Auto generated by spf13/cobra on 9-Feb-2018 diff --git a/pkg/helm/client.go b/pkg/helm/client.go index c7ef4d89e..0f3c251a3 100644 --- a/pkg/helm/client.go +++ b/pkg/helm/client.go @@ -297,12 +297,6 @@ func (h *Client) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-ch return h.test(ctx, req) } -// PingTiller pings the Tiller pod and ensure's that it is up and running -func (h *Client) PingTiller() error { - ctx := NewContext() - return h.ping(ctx) -} - // connect returns a gRPC connection to Tiller or error. The gRPC dial options // are constructed here. func (h *Client) connect(ctx context.Context) (conn *grpc.ClientConn, err error) { @@ -479,15 +473,3 @@ func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan return ch, errc } - -// Executes tiller.Ping RPC. -func (h *Client) ping(ctx context.Context) error { - c, err := h.connect(ctx) - if err != nil { - return err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - return rlc.PingTiller(ctx) -} diff --git a/pkg/helm/fake.go b/pkg/helm/fake.go index dbb488610..8d809f658 100644 --- a/pkg/helm/fake.go +++ b/pkg/helm/fake.go @@ -184,11 +184,6 @@ func (c *FakeClient) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) ( return results, errc } -// PingTiller pings the Tiller pod and ensure's that it is up and running -func (c *FakeClient) PingTiller() error { - return nil -} - // MockHookTemplate is the hook template used for all mock release objects. var MockHookTemplate = `apiVersion: v1 kind: Job diff --git a/pkg/helm/interface.go b/pkg/helm/interface.go index 10c04c710..bff110b34 100644 --- a/pkg/helm/interface.go +++ b/pkg/helm/interface.go @@ -35,5 +35,4 @@ type Interface interface { ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) GetVersion(opts ...VersionOption) (*rls.GetVersionResponse, error) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) - PingTiller() error } diff --git a/pkg/helm/portforwarder/portforwarder.go b/pkg/helm/portforwarder/portforwarder.go index 07e692e9a..ef9896db7 100644 --- a/pkg/helm/portforwarder/portforwarder.go +++ b/pkg/helm/portforwarder/portforwarder.go @@ -31,6 +31,8 @@ import ( var ( tillerPodLabels labels.Set = labels.Set{"app": "helm", "name": "tiller"} + // ErrTillerNotFound thrown when a running tiller instance is not found + ErrTillerNotFound = fmt.Errorf("could not find a ready tiller pod") ) // New creates a new and initialized tunnel. @@ -67,5 +69,5 @@ func getFirstRunningPod(client corev1.PodsGetter, namespace string, selector lab return &p, nil } } - return nil, fmt.Errorf("could not find a ready tiller pod") + return nil, ErrTillerNotFound } diff --git a/pkg/proto/hapi/services/tiller.pb.go b/pkg/proto/hapi/services/tiller.pb.go index 2112ea67f..023749c4f 100644 --- a/pkg/proto/hapi/services/tiller.pb.go +++ b/pkg/proto/hapi/services/tiller.pb.go @@ -949,8 +949,6 @@ type ReleaseServiceClient interface { GetHistory(ctx context.Context, in *GetHistoryRequest, opts ...grpc.CallOption) (*GetHistoryResponse, error) // RunReleaseTest executes the tests defined of a named release RunReleaseTest(ctx context.Context, in *TestReleaseRequest, opts ...grpc.CallOption) (ReleaseService_RunReleaseTestClient, error) - // PingTiller sends a test/ping signal to Tiller to ensure that it's up - PingTiller(ctx context.Context) error } type releaseServiceClient struct { @@ -1080,14 +1078,6 @@ func (c *releaseServiceClient) RunReleaseTest(ctx context.Context, in *TestRelea return x, nil } -func (c *releaseServiceClient) PingTiller(ctx context.Context) error { - err := grpc.Invoke(ctx, "/hapi.services.tiller.ReleaseService/PingTiller", "Ping", nil, c.cc, grpc.FailFast(false)) - if err != nil { - return err - } - return nil -} - type ReleaseService_RunReleaseTestClient interface { Recv() (*TestReleaseResponse, error) grpc.ClientStream @@ -1310,10 +1300,6 @@ func _ReleaseService_RunReleaseTest_Handler(srv interface{}, stream grpc.ServerS return srv.(ReleaseServiceServer).RunReleaseTest(m, &releaseServiceRunReleaseTestServer{stream}) } -func _ReleaseService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - return "Pong", nil -} - type ReleaseService_RunReleaseTestServer interface { Send(*TestReleaseResponse) error grpc.ServerStream @@ -1363,10 +1349,6 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{ MethodName: "GetHistory", Handler: _ReleaseService_GetHistory_Handler, }, - { - MethodName: "PingTiller", - Handler: _ReleaseService_Ping_Handler, - }, }, Streams: []grpc.StreamDesc{ { diff --git a/pkg/version/version.go b/pkg/version/version.go index 6f5a1a452..98836a36e 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -26,7 +26,7 @@ var ( // Increment major number for new feature additions and behavioral changes. // Increment minor number for bug fixes and performance enhancements. // Increment patch number for critical fixes to existing releases. - Version = "v2.8" + Version = "v2.8.1" // BuildMetadata is extra build time data BuildMetadata = "unreleased"