From b1fbc391edfb97b15dfa546a1243d962551906f8 Mon Sep 17 00:00:00 2001 From: John Welsh Date: Thu, 27 Apr 2017 01:20:28 -0700 Subject: [PATCH] Added a stubbed out logs command --- cmd/helm/helm.go | 1 + cmd/helm/logs.go | 105 ++++++++++------------------------- pkg/helm/client.go | 31 +++++++---- pkg/tiller/release_server.go | 21 +++++++ 4 files changed, 70 insertions(+), 88 deletions(-) diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index ced336ac4..e20e5835e 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -134,6 +134,7 @@ func newRootCmd(out io.Writer) *cobra.Command { addFlagsTLS(newHistoryCmd(nil, out)), addFlagsTLS(newInstallCmd(nil, out)), addFlagsTLS(newListCmd(nil, out)), + addFlagsTLS(newLogsCmd(nil, out)), addFlagsTLS(newRollbackCmd(nil, out)), addFlagsTLS(newStatusCmd(nil, out)), addFlagsTLS(newUpgradeCmd(nil, out)), diff --git a/cmd/helm/logs.go b/cmd/helm/logs.go index b635e6186..a43b12a33 100644 --- a/cmd/helm/logs.go +++ b/cmd/helm/logs.go @@ -17,118 +17,69 @@ limitations under the License. package main import ( - "fmt" "io" - "regexp" - "text/tabwriter" - - "github.com/gosuri/uitable" - "github.com/gosuri/uitable/util/strutil" "github.com/spf13/cobra" "k8s.io/helm/pkg/helm" - "k8s.io/helm/pkg/proto/hapi/release" - "k8s.io/helm/pkg/proto/hapi/services" - "k8s.io/helm/pkg/timeconv" + "fmt" ) -var statusHelp = ` -This command shows the status of a named release. -The status consists of: -- last deployment time -- k8s namespace in which the release lives -- state of the release (can be: UNKNOWN, DEPLOYED, DELETED, SUPERSEDED, FAILED or DELETING) -- list of resources that this release consists of, sorted by kind -- details on last test suite run, if applicable -- additional notes provided by the chart +var logsHelp = ` +This command gets logs for a named release ` -type statusCmd struct { +type logsCmd struct { release string out io.Writer client helm.Interface version int32 } -func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { - status := &statusCmd{ +func newLogsCmd(client helm.Interface, out io.Writer) *cobra.Command { + logs := &logsCmd{ out: out, client: client, } cmd := &cobra.Command{ - Use: "status [flags] RELEASE_NAME", - Short: "displays the status of the named release", - Long: statusHelp, + Use: "logs [flags] RELEASE_NAME", + Short: "Streams logs for the given release", + Long: logsHelp, PersistentPreRunE: setupConnection, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errReleaseRequired } - status.release = args[0] - if status.client == nil { - status.client = helm.NewClient(helm.Host(settings.TillerHost)) + logs.release = args[0] + if logs.client == nil { + logs.client = helm.NewClient(helm.Host(settings.TillerHost)) } - return status.run() + return logs.run() }, } - cmd.PersistentFlags().Int32Var(&status.version, "revision", 0, "if set, display the status of the named release with revision") - return cmd } -func (s *statusCmd) run() error { - res, err := s.client.ReleaseStatus(s.release, helm.StatusReleaseVersion(s.version)) +func (l *logsCmd) run() error { + done := make(chan struct{}) + stream, err := l.client.ReleaseLogs(l.release, done) + + fmt.Println("Listening for logs") + for { + select { + case l, ok := <-stream: + if !ok { + return nil + } + fmt.Println(l) + } + } + if err != nil { return prettyError(err) } - PrintStatus(s.out, res) return nil } -// PrintStatus prints out the status of a release. Shared because also used by -// install / upgrade -func PrintStatus(out io.Writer, res *services.GetReleaseStatusResponse) { - if res.Info.LastDeployed != nil { - fmt.Fprintf(out, "LAST DEPLOYED: %s\n", timeconv.String(res.Info.LastDeployed)) - } - fmt.Fprintf(out, "NAMESPACE: %s\n", res.Namespace) - fmt.Fprintf(out, "STATUS: %s\n", res.Info.Status.Code) - fmt.Fprintf(out, "\n") - if len(res.Info.Status.Resources) > 0 { - re := regexp.MustCompile(" +") - - w := tabwriter.NewWriter(out, 0, 0, 2, ' ', tabwriter.TabIndent) - fmt.Fprintf(w, "RESOURCES:\n%s\n", re.ReplaceAllString(res.Info.Status.Resources, "\t")) - w.Flush() - } - if res.Info.Status.LastTestSuiteRun != nil { - lastRun := res.Info.Status.LastTestSuiteRun - fmt.Fprintf(out, "TEST SUITE:\n%s\n%s\n\n%s\n", - fmt.Sprintf("Last Started: %s", timeconv.String(lastRun.StartedAt)), - fmt.Sprintf("Last Completed: %s", timeconv.String(lastRun.CompletedAt)), - formatTestResults(lastRun.Results)) - } - - if len(res.Info.Status.Notes) > 0 { - fmt.Fprintf(out, "NOTES:\n%s\n", res.Info.Status.Notes) - } -} - -func formatTestResults(results []*release.TestRun) string { - tbl := uitable.New() - tbl.MaxColWidth = 50 - tbl.AddRow("TEST", "STATUS", "INFO", "STARTED", "COMPLETED") - for i := 0; i < len(results); i++ { - r := results[i] - n := r.Name - s := strutil.PadRight(r.Status.String(), 10, ' ') - i := r.Info - ts := timeconv.String(r.StartedAt) - tc := timeconv.String(r.CompletedAt) - tbl.AddRow(n, s, i, ts, tc) - } - return tbl.String() -} diff --git a/pkg/helm/client.go b/pkg/helm/client.go index 02f9097d2..ddb34658e 100644 --- a/pkg/helm/client.go +++ b/pkg/helm/client.go @@ -404,19 +404,28 @@ func (h *Client) logs(ctx context.Context, req *rls.GetReleaseLogsRequest, done defer close(out) defer c.Close() for { - select { - case rs := s.Recv(): - if err == io.EOF { - return - } - if err != nil { - fmt.Println("gRPC error streaming logs: ", grpc.ErrorDesc(err)) - return - } - out <- rs - case <-done: + rs, err := s.Recv() + if err == io.EOF { + return + } + if err != nil { + fmt.Println("gRPC error streaming logs: ", grpc.ErrorDesc(err)) return } + out <- rs + //select { + ////case rs, err := s.Recv(): + //// if err == io.EOF { + //// return + //// } + //// if err != nil { + //// fmt.Println("gRPC error streaming logs: ", grpc.ErrorDesc(err)) + //// return + //// } + //// out <- rs + //case <-done: + // return + //} } }() diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index 5bd0a48de..c122086b9 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -42,6 +42,8 @@ import ( "k8s.io/helm/pkg/tiller/environment" "k8s.io/helm/pkg/timeconv" "k8s.io/helm/pkg/version" + "k8s.io/helm/pkg/tiller/logdistributor" + "time" ) // releaseNameMaxLen is the maximum length of a release name. @@ -84,6 +86,7 @@ var ValidName = regexp.MustCompile("^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])+ type ReleaseServer struct { env *environment.Environment clientset internalclientset.Interface + logs *logdistributor.Pubsub } // NewReleaseServer creates a new release server. @@ -91,6 +94,7 @@ func NewReleaseServer(env *environment.Environment, clientset internalclientset. return &ReleaseServer{ env: env, clientset: clientset, + logs: logdistributor.New(), } } @@ -281,6 +285,23 @@ func (s *ReleaseServer) GetReleaseContent(c ctx.Context, req *services.GetReleas return &services.GetReleaseContentResponse{Release: rel}, err } +func (s *ReleaseServer) GetReleaseLogs(req *services.GetReleaseLogsRequest, stream services.ReleaseService_GetReleaseLogsServer) error { + t := time.NewTicker(time.Second) + //go func() { + for { + select { + case <-t.C: + fmt.Println("Sending a log") + stream.Send(&services.GetReleaseLogsResponse{Log: &release.Log{Log: "Test log!"}}) + } + } + //}() + fmt.Println("Out of the for loop") + + stream.Send(&services.GetReleaseLogsResponse{Log: &release.Log{Log: "Starting to stream logs!"}}) + return nil +} + // UpdateRelease takes an existing release and new information, and upgrades the release. func (s *ReleaseServer) UpdateRelease(c ctx.Context, req *services.UpdateReleaseRequest) (*services.UpdateReleaseResponse, error) { currentRelease, updatedRelease, err := s.prepareUpdate(req)