github.com/vtuson/helm@v2.8.2+incompatible/cmd/helm/status.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"io"
    23  	"regexp"
    24  	"text/tabwriter"
    25  
    26  	"github.com/ghodss/yaml"
    27  	"github.com/gosuri/uitable"
    28  	"github.com/gosuri/uitable/util/strutil"
    29  	"github.com/spf13/cobra"
    30  
    31  	"k8s.io/helm/pkg/helm"
    32  	"k8s.io/helm/pkg/proto/hapi/release"
    33  	"k8s.io/helm/pkg/proto/hapi/services"
    34  	"k8s.io/helm/pkg/timeconv"
    35  )
    36  
    37  var statusHelp = `
    38  This command shows the status of a named release.
    39  The status consists of:
    40  - last deployment time
    41  - k8s namespace in which the release lives
    42  - state of the release (can be: UNKNOWN, DEPLOYED, DELETED, SUPERSEDED, FAILED or DELETING)
    43  - list of resources that this release consists of, sorted by kind
    44  - details on last test suite run, if applicable
    45  - additional notes provided by the chart
    46  `
    47  
    48  type statusCmd struct {
    49  	release string
    50  	out     io.Writer
    51  	client  helm.Interface
    52  	version int32
    53  	outfmt  string
    54  }
    55  
    56  func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command {
    57  	status := &statusCmd{
    58  		out:    out,
    59  		client: client,
    60  	}
    61  
    62  	cmd := &cobra.Command{
    63  		Use:     "status [flags] RELEASE_NAME",
    64  		Short:   "displays the status of the named release",
    65  		Long:    statusHelp,
    66  		PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() },
    67  		RunE: func(cmd *cobra.Command, args []string) error {
    68  			if len(args) == 0 {
    69  				return errReleaseRequired
    70  			}
    71  			status.release = args[0]
    72  			if status.client == nil {
    73  				status.client = newClient()
    74  			}
    75  			return status.run()
    76  		},
    77  	}
    78  
    79  	cmd.PersistentFlags().Int32Var(&status.version, "revision", 0, "if set, display the status of the named release with revision")
    80  	cmd.PersistentFlags().StringVarP(&status.outfmt, "output", "o", "", "output the status in the specified format (json or yaml)")
    81  
    82  	return cmd
    83  }
    84  
    85  func (s *statusCmd) run() error {
    86  	res, err := s.client.ReleaseStatus(s.release, helm.StatusReleaseVersion(s.version))
    87  	if err != nil {
    88  		return prettyError(err)
    89  	}
    90  
    91  	switch s.outfmt {
    92  	case "":
    93  		PrintStatus(s.out, res)
    94  		return nil
    95  	case "json":
    96  		data, err := json.Marshal(res)
    97  		if err != nil {
    98  			return fmt.Errorf("Failed to Marshal JSON output: %s", err)
    99  		}
   100  		s.out.Write(data)
   101  		return nil
   102  	case "yaml":
   103  		data, err := yaml.Marshal(res)
   104  		if err != nil {
   105  			return fmt.Errorf("Failed to Marshal YAML output: %s", err)
   106  		}
   107  		s.out.Write(data)
   108  		return nil
   109  	}
   110  
   111  	return fmt.Errorf("Unknown output format %q", s.outfmt)
   112  }
   113  
   114  // PrintStatus prints out the status of a release. Shared because also used by
   115  // install / upgrade
   116  func PrintStatus(out io.Writer, res *services.GetReleaseStatusResponse) {
   117  	if res.Info.LastDeployed != nil {
   118  		fmt.Fprintf(out, "LAST DEPLOYED: %s\n", timeconv.String(res.Info.LastDeployed))
   119  	}
   120  	fmt.Fprintf(out, "NAMESPACE: %s\n", res.Namespace)
   121  	fmt.Fprintf(out, "STATUS: %s\n", res.Info.Status.Code)
   122  	fmt.Fprintf(out, "\n")
   123  	if len(res.Info.Status.Resources) > 0 {
   124  		re := regexp.MustCompile("  +")
   125  
   126  		w := tabwriter.NewWriter(out, 0, 0, 2, ' ', tabwriter.TabIndent)
   127  		fmt.Fprintf(w, "RESOURCES:\n%s\n", re.ReplaceAllString(res.Info.Status.Resources, "\t"))
   128  		w.Flush()
   129  	}
   130  	if res.Info.Status.LastTestSuiteRun != nil {
   131  		lastRun := res.Info.Status.LastTestSuiteRun
   132  		fmt.Fprintf(out, "TEST SUITE:\n%s\n%s\n\n%s\n",
   133  			fmt.Sprintf("Last Started: %s", timeconv.String(lastRun.StartedAt)),
   134  			fmt.Sprintf("Last Completed: %s", timeconv.String(lastRun.CompletedAt)),
   135  			formatTestResults(lastRun.Results))
   136  	}
   137  
   138  	if len(res.Info.Status.Notes) > 0 {
   139  		fmt.Fprintf(out, "NOTES:\n%s\n", res.Info.Status.Notes)
   140  	}
   141  }
   142  
   143  func formatTestResults(results []*release.TestRun) string {
   144  	tbl := uitable.New()
   145  	tbl.MaxColWidth = 50
   146  	tbl.AddRow("TEST", "STATUS", "INFO", "STARTED", "COMPLETED")
   147  	for i := 0; i < len(results); i++ {
   148  		r := results[i]
   149  		n := r.Name
   150  		s := strutil.PadRight(r.Status.String(), 10, ' ')
   151  		i := r.Info
   152  		ts := timeconv.String(r.StartedAt)
   153  		tc := timeconv.String(r.CompletedAt)
   154  		tbl.AddRow(n, s, i, ts, tc)
   155  	}
   156  	return tbl.String()
   157  }