diff --git a/cmd/helm/search.go b/cmd/helm/search.go index 99ffafbd3..5deab0a7c 100644 --- a/cmd/helm/search.go +++ b/cmd/helm/search.go @@ -17,6 +17,7 @@ limitations under the License. package main import ( + "encoding/json" "fmt" "io" "strings" @@ -48,6 +49,18 @@ type searchCmd struct { regexp bool version string colWidth uint + output string +} + +type resultEntry struct { + Name string `json:"name"` + ChartVersion string `json:"chartVersion"` + AppVersion string `json:"appVersion"` + Description string `json:"description"` +} + +type results struct { + SearchResults []resultEntry `json:"searchResults"` } func newSearchCmd(out io.Writer) *cobra.Command { @@ -68,6 +81,7 @@ func newSearchCmd(out io.Writer) *cobra.Command { f.BoolVarP(&sc.versions, "versions", "l", false, "Show the long listing, with each version of each chart on its own line") f.StringVarP(&sc.version, "version", "v", "", "Search using semantic versioning constraints") f.UintVar(&sc.colWidth, "col-width", 60, "Specifies the max column width of output") + f.StringVarP(&sc.output, "output", "o", "", "Show the output in specified format") return cmd } @@ -95,6 +109,16 @@ func (s *searchCmd) run(args []string) error { return err } + if s.output == "json" { + formattedResults, err := s.formatSearchResultsJSON(data, s.colWidth) + if err != nil { + return err + } + + fmt.Fprintln(s.out, formattedResults) + return nil + } + fmt.Fprintln(s.out, s.formatSearchResults(data, s.colWidth)) return nil @@ -141,6 +165,30 @@ func (s *searchCmd) formatSearchResults(res []*search.Result, colWidth uint) str return table.String() } +func (s *searchCmd) formatSearchResultsJSON(res []*search.Result, colWidth uint) (string, error) { + var resultJSON []resultEntry + + if len(res) == 0 { + return "No results found", nil + } + + for _, r := range res { + resultRow := resultEntry{ + Name: r.Name, + ChartVersion: r.Chart.Version, + AppVersion: r.Chart.AppVersion, + Description: r.Chart.Description, + } + resultJSON = append(resultJSON, resultRow) + } + jsonSearchResults, err := json.MarshalIndent(results{SearchResults: resultJSON}, "", " ") + if err != nil { + return "", err + } + + return string(jsonSearchResults), nil +} + func (s *searchCmd) buildIndex() (*search.Index, error) { // Load the repositories.yaml rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile()) diff --git a/cmd/helm/search_test.go b/cmd/helm/search_test.go index 233f94572..4617ea151 100644 --- a/cmd/helm/search_test.go +++ b/cmd/helm/search_test.go @@ -84,6 +84,12 @@ func TestSearchCmd(t *testing.T) { flags: []string{"--regexp"}, err: true, }, + { + name: "search for 'alpine', expect two matches in json", + args: []string{"alpine"}, + flags: []string{"--output", "json"}, + expected: "{\n \"searchResults\": \\[\n {\n \"name\": \"testing/alpine\",\n \"chartVersion\": \"0.2.0\",\n \"appVersion\": \"2.3.4\",\n \"description\": \"Deploy a basic Alpine Linux pod\"\n }\n \\]\n}", + }, } cleanup := resetEnv()