github.com/werf/3p-helm@v2.8.1+incompatible/cmd/helm/search.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 "fmt" 21 "io" 22 "strings" 23 24 "github.com/Masterminds/semver" 25 "github.com/gosuri/uitable" 26 "github.com/spf13/cobra" 27 28 "k8s.io/helm/cmd/helm/search" 29 "k8s.io/helm/pkg/helm/helmpath" 30 "k8s.io/helm/pkg/repo" 31 ) 32 33 const searchDesc = ` 34 Search reads through all of the repositories configured on the system, and 35 looks for matches. 36 37 Repositories are managed with 'helm repo' commands. 38 ` 39 40 // searchMaxScore suggests that any score higher than this is not considered a match. 41 const searchMaxScore = 25 42 43 type searchCmd struct { 44 out io.Writer 45 helmhome helmpath.Home 46 47 versions bool 48 regexp bool 49 version string 50 } 51 52 func newSearchCmd(out io.Writer) *cobra.Command { 53 sc := &searchCmd{out: out} 54 55 cmd := &cobra.Command{ 56 Use: "search [keyword]", 57 Short: "search for a keyword in charts", 58 Long: searchDesc, 59 RunE: func(cmd *cobra.Command, args []string) error { 60 sc.helmhome = settings.Home 61 return sc.run(args) 62 }, 63 } 64 65 f := cmd.Flags() 66 f.BoolVarP(&sc.regexp, "regexp", "r", false, "use regular expressions for searching") 67 f.BoolVarP(&sc.versions, "versions", "l", false, "show the long listing, with each version of each chart on its own line") 68 f.StringVarP(&sc.version, "version", "v", "", "search using semantic versioning constraints") 69 70 return cmd 71 } 72 73 func (s *searchCmd) run(args []string) error { 74 index, err := s.buildIndex() 75 if err != nil { 76 return err 77 } 78 79 var res []*search.Result 80 if len(args) == 0 { 81 res = index.All() 82 } else { 83 q := strings.Join(args, " ") 84 res, err = index.Search(q, searchMaxScore, s.regexp) 85 if err != nil { 86 return nil 87 } 88 } 89 90 search.SortScore(res) 91 data, err := s.applyConstraint(res) 92 if err != nil { 93 return err 94 } 95 96 fmt.Fprintln(s.out, s.formatSearchResults(data)) 97 98 return nil 99 } 100 101 func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, error) { 102 if len(s.version) == 0 { 103 return res, nil 104 } 105 106 constraint, err := semver.NewConstraint(s.version) 107 if err != nil { 108 return res, fmt.Errorf("an invalid version/constraint format: %s", err) 109 } 110 111 data := res[:0] 112 foundNames := map[string]bool{} 113 for _, r := range res { 114 if _, found := foundNames[r.Name]; found { 115 continue 116 } 117 v, err := semver.NewVersion(r.Chart.Version) 118 if err != nil || constraint.Check(v) { 119 data = append(data, r) 120 if !s.versions { 121 foundNames[r.Name] = true // If user hasn't requested all versions, only show the latest that matches 122 } 123 } 124 } 125 126 return data, nil 127 } 128 129 func (s *searchCmd) formatSearchResults(res []*search.Result) string { 130 if len(res) == 0 { 131 return "No results found" 132 } 133 table := uitable.New() 134 table.MaxColWidth = 50 135 table.AddRow("NAME", "CHART VERSION", "APP VERSION", "DESCRIPTION") 136 for _, r := range res { 137 table.AddRow(r.Name, r.Chart.Version, r.Chart.AppVersion, r.Chart.Description) 138 } 139 return table.String() 140 } 141 142 func (s *searchCmd) buildIndex() (*search.Index, error) { 143 // Load the repositories.yaml 144 rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile()) 145 if err != nil { 146 return nil, err 147 } 148 149 i := search.NewIndex() 150 for _, re := range rf.Repositories { 151 n := re.Name 152 f := s.helmhome.CacheIndex(n) 153 ind, err := repo.LoadIndexFile(f) 154 if err != nil { 155 fmt.Fprintf(s.out, "WARNING: Repo %q is corrupt or missing. Try 'helm repo update'.", n) 156 continue 157 } 158 159 i.AddRepo(n, ind, s.versions || len(s.version) > 0) 160 } 161 return i, nil 162 }