github.com/wangchanggan/helm@v0.0.0-20211020154240-11b1b7d5406d/cmd/helm/inspect.go (about)

     1  /*
     2  Copyright The Helm Authors.
     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  	"fmt"
    21  	"github.com/ghodss/yaml"
    22  	"github.com/golang/protobuf/ptypes/any"
    23  	"github.com/spf13/cobra"
    24  	"io"
    25  	"strings"
    26  
    27  	"k8s.io/helm/pkg/chartutil"
    28  )
    29  
    30  const (
    31  	inspectDesc = `
    32  This command inspects a chart and displays information. It takes a chart reference
    33  ('stable/drupal'), a full path to a directory or packaged chart, or a URL.
    34  
    35  Inspect prints the contents of the Chart.yaml file and the values.yaml file.
    36  `
    37  	inspectValuesDesc = `
    38  This command inspects a chart (directory, file, or URL) and displays the contents
    39  of the values.yaml file
    40  `
    41  	inspectChartDesc = `
    42  This command inspects a chart (directory, file, or URL) and displays the contents
    43  of the Charts.yaml file
    44  `
    45  	readmeChartDesc = `
    46  This command inspects a chart (directory, file, or URL) and displays the contents
    47  of the README file
    48  `
    49  )
    50  
    51  type inspectCmd struct {
    52  	chartpath string
    53  	output    string
    54  	verify    bool
    55  	keyring   string
    56  	out       io.Writer
    57  	version   string
    58  	repoURL   string
    59  	username  string
    60  	password  string
    61  	devel     bool
    62  
    63  	certFile string
    64  	keyFile  string
    65  	caFile   string
    66  }
    67  
    68  const (
    69  	chartOnly  = "chart"
    70  	valuesOnly = "values"
    71  	readmeOnly = "readme"
    72  	all        = "all"
    73  )
    74  
    75  var readmeFileNames = []string{"readme.md", "readme.txt", "readme"}
    76  
    77  func newInspectCmd(out io.Writer) *cobra.Command {
    78  	insp := &inspectCmd{
    79  		out:    out,
    80  		output: all,
    81  	}
    82  
    83  	inspectCommand := &cobra.Command{
    84  		Use:   "inspect [CHART]",
    85  		Short: "Inspect a chart",
    86  		Long:  inspectDesc,
    87  		RunE: func(cmd *cobra.Command, args []string) error {
    88  			if err := checkArgsLength(len(args), "chart name"); err != nil {
    89  				return err
    90  			}
    91  			if err := insp.prepare(args[0]); err != nil {
    92  				return err
    93  			}
    94  			return insp.run()
    95  		},
    96  	}
    97  
    98  	valuesSubCmd := &cobra.Command{
    99  		Use:   "values [CHART]",
   100  		Short: "shows inspect values",
   101  		Long:  inspectValuesDesc,
   102  		RunE: func(cmd *cobra.Command, args []string) error {
   103  			insp.output = valuesOnly
   104  			if err := checkArgsLength(len(args), "chart name"); err != nil {
   105  				return err
   106  			}
   107  			if err := insp.prepare(args[0]); err != nil {
   108  				return err
   109  			}
   110  			return insp.run()
   111  		},
   112  	}
   113  
   114  	chartSubCmd := &cobra.Command{
   115  		Use:   "chart [CHART]",
   116  		Short: "shows inspect chart",
   117  		Long:  inspectChartDesc,
   118  		RunE: func(cmd *cobra.Command, args []string) error {
   119  			insp.output = chartOnly
   120  			if err := checkArgsLength(len(args), "chart name"); err != nil {
   121  				return err
   122  			}
   123  			if err := insp.prepare(args[0]); err != nil {
   124  				return err
   125  			}
   126  			return insp.run()
   127  		},
   128  	}
   129  
   130  	readmeSubCmd := &cobra.Command{
   131  		Use:   "readme [CHART]",
   132  		Short: "shows inspect readme",
   133  		Long:  readmeChartDesc,
   134  		RunE: func(cmd *cobra.Command, args []string) error {
   135  			insp.output = readmeOnly
   136  			if err := checkArgsLength(len(args), "chart name"); err != nil {
   137  				return err
   138  			}
   139  			if err := insp.prepare(args[0]); err != nil {
   140  				return err
   141  			}
   142  			return insp.run()
   143  		},
   144  	}
   145  
   146  	cmds := []*cobra.Command{inspectCommand, readmeSubCmd, valuesSubCmd, chartSubCmd}
   147  	vflag := "verify"
   148  	vdesc := "Verify the provenance data for this chart"
   149  	for _, subCmd := range cmds {
   150  		subCmd.Flags().BoolVar(&insp.verify, vflag, false, vdesc)
   151  	}
   152  
   153  	kflag := "keyring"
   154  	kdesc := "Path to the keyring containing public verification keys"
   155  	kdefault := defaultKeyring()
   156  	for _, subCmd := range cmds {
   157  		subCmd.Flags().StringVar(&insp.keyring, kflag, kdefault, kdesc)
   158  	}
   159  
   160  	verflag := "version"
   161  	verdesc := "Version of the chart. By default, the newest chart is shown"
   162  	for _, subCmd := range cmds {
   163  		subCmd.Flags().StringVar(&insp.version, verflag, "", verdesc)
   164  	}
   165  
   166  	repoURL := "repo"
   167  	repoURLdesc := "Chart repository url where to locate the requested chart"
   168  	for _, subCmd := range cmds {
   169  		subCmd.Flags().StringVar(&insp.repoURL, repoURL, "", repoURLdesc)
   170  	}
   171  
   172  	username := "username"
   173  	usernamedesc := "Chart repository username where to locate the requested chart"
   174  	inspectCommand.Flags().StringVar(&insp.username, username, "", usernamedesc)
   175  	valuesSubCmd.Flags().StringVar(&insp.username, username, "", usernamedesc)
   176  	chartSubCmd.Flags().StringVar(&insp.username, username, "", usernamedesc)
   177  
   178  	password := "password"
   179  	passworddesc := "Chart repository password where to locate the requested chart"
   180  	inspectCommand.Flags().StringVar(&insp.password, password, "", passworddesc)
   181  	valuesSubCmd.Flags().StringVar(&insp.password, password, "", passworddesc)
   182  	chartSubCmd.Flags().StringVar(&insp.password, password, "", passworddesc)
   183  
   184  	develFlag := "devel"
   185  	develDesc := "Use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored."
   186  	for _, subCmd := range cmds {
   187  		subCmd.Flags().BoolVar(&insp.devel, develFlag, false, develDesc)
   188  	}
   189  
   190  	certFile := "cert-file"
   191  	certFiledesc := "Verify certificates of HTTPS-enabled servers using this CA bundle"
   192  	for _, subCmd := range cmds {
   193  		subCmd.Flags().StringVar(&insp.certFile, certFile, "", certFiledesc)
   194  	}
   195  
   196  	keyFile := "key-file"
   197  	keyFiledesc := "Identify HTTPS client using this SSL key file"
   198  	for _, subCmd := range cmds {
   199  		subCmd.Flags().StringVar(&insp.keyFile, keyFile, "", keyFiledesc)
   200  	}
   201  
   202  	caFile := "ca-file"
   203  	caFiledesc := "Chart repository url where to locate the requested chart"
   204  	for _, subCmd := range cmds {
   205  		subCmd.Flags().StringVar(&insp.caFile, caFile, "", caFiledesc)
   206  	}
   207  
   208  	for _, subCmd := range cmds[1:] {
   209  		inspectCommand.AddCommand(subCmd)
   210  	}
   211  
   212  	return inspectCommand
   213  }
   214  
   215  func (i *inspectCmd) prepare(chart string) error {
   216  	debug("Original chart version: %q", i.version)
   217  	if i.version == "" && i.devel {
   218  		debug("setting version to >0.0.0-0")
   219  		i.version = ">0.0.0-0"
   220  	}
   221  
   222  	cp, err := locateChartPath(i.repoURL, i.username, i.password, chart, i.version, i.verify, i.keyring,
   223  		i.certFile, i.keyFile, i.caFile)
   224  	if err != nil {
   225  		return err
   226  	}
   227  	i.chartpath = cp
   228  	return nil
   229  }
   230  
   231  func (i *inspectCmd) run() error {
   232  	chrt, err := chartutil.Load(i.chartpath)
   233  	if err != nil {
   234  		return err
   235  	}
   236  	cf, err := yaml.Marshal(chrt.Metadata)
   237  	if err != nil {
   238  		return err
   239  	}
   240  
   241  	if i.output == chartOnly || i.output == all {
   242  		fmt.Fprintln(i.out, string(cf))
   243  	}
   244  
   245  	if (i.output == valuesOnly || i.output == all) && chrt.Values != nil {
   246  		if i.output == all {
   247  			fmt.Fprintln(i.out, "---")
   248  		}
   249  		fmt.Fprintln(i.out, chrt.Values.Raw)
   250  	}
   251  
   252  	if i.output == readmeOnly || i.output == all {
   253  		if i.output == all {
   254  			fmt.Fprintln(i.out, "---")
   255  		}
   256  		readme := findReadme(chrt.Files)
   257  		if readme == nil {
   258  			return nil
   259  		}
   260  		fmt.Fprintln(i.out, string(readme.Value))
   261  	}
   262  	return nil
   263  }
   264  
   265  func findReadme(files []*any.Any) (file *any.Any) {
   266  	for _, file := range files {
   267  		if containsString(readmeFileNames, strings.ToLower(file.TypeUrl), nil) {
   268  			return file
   269  		}
   270  	}
   271  	return nil
   272  }
   273  
   274  // containsString checks if a given slice of strings contains the provided string.
   275  // If a modifier func is provided, it is called with the slice item before the comparison.
   276  func containsString(slice []string, s string, modifier func(s string) string) bool {
   277  	for _, item := range slice {
   278  		if item == s {
   279  			return true
   280  		}
   281  		if modifier != nil && modifier(item) == s {
   282  			return true
   283  		}
   284  	}
   285  	return false
   286  }