github.com/Racer159/helm-experiment@v0.0.0-20230822001441-1eb31183f614/src/search_hub.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 cmd 18 19 import ( 20 "fmt" 21 "io" 22 23 "github.com/gosuri/uitable" 24 "github.com/spf13/cobra" 25 26 "helm.sh/helm/v3/pkg/cli/output" 27 ) 28 29 const searchHubDesc = ` 30 Search for Helm charts in the Artifact Hub or your own hub instance. 31 32 Artifact Hub is a web-based application that enables finding, installing, and 33 publishing packages and configurations for CNCF projects, including publicly 34 available distributed charts Helm charts. It is a Cloud Native Computing 35 Foundation sandbox project. You can browse the hub at https://artifacthub.io/ 36 37 The [KEYWORD] argument accepts either a keyword string, or quoted string of rich 38 query options. For rich query options documentation, see 39 https://artifacthub.github.io/hub/api/?urls.primaryName=Monocular%20compatible%20search%20API#/Monocular/get_api_chartsvc_v1_charts_search 40 41 Previous versions of Helm used an instance of Monocular as the default 42 'endpoint', so for backwards compatibility Artifact Hub is compatible with the 43 Monocular search API. Similarly, when setting the 'endpoint' flag, the specified 44 endpoint must also be implement a Monocular compatible search API endpoint. 45 Note that when specifying a Monocular instance as the 'endpoint', rich queries 46 are not supported. For API details, see https://github.com/helm/monocular 47 ` 48 49 type searchHubOptions struct { 50 searchEndpoint string 51 maxColWidth uint 52 outputFormat output.Format 53 listRepoURL bool 54 } 55 56 func newSearchHubCmd(out io.Writer) *cobra.Command { 57 o := &searchHubOptions{} 58 59 cmd := &cobra.Command{ 60 Use: "hub [KEYWORD]", 61 Short: "search for charts in the Artifact Hub or your own hub instance", 62 Long: searchHubDesc, 63 // RunE: func(cmd *cobra.Command, args []string) error { 64 // // return o.run(out, args) 65 // }, 66 } 67 68 f := cmd.Flags() 69 f.StringVar(&o.searchEndpoint, "endpoint", "https://hub.helm.sh", "Hub instance to query for charts") 70 f.UintVar(&o.maxColWidth, "max-col-width", 50, "maximum column width for output table") 71 f.BoolVar(&o.listRepoURL, "list-repo-url", false, "print charts repository URL") 72 73 bindOutputFlag(cmd, &o.outputFormat) 74 75 return cmd 76 } 77 78 // func (o *searchHubOptions) run(out io.Writer, args []string) error { 79 // c, err := monocular.New(o.searchEndpoint) 80 // if err != nil { 81 // return errors.Wrap(err, fmt.Sprintf("unable to create connection to %q", o.searchEndpoint)) 82 // } 83 84 // q := strings.Join(args, " ") 85 // results, err := c.Search(q) 86 // if err != nil { 87 // debug("%s", err) 88 // return fmt.Errorf("unable to perform search against %q", o.searchEndpoint) 89 // } 90 91 // return o.outputFormat.Write(out, newHubSearchWriter(results, o.searchEndpoint, o.maxColWidth, o.listRepoURL)) 92 // } 93 94 type hubChartRepo struct { 95 URL string `json:"url"` 96 Name string `json:"name"` 97 } 98 99 type hubChartElement struct { 100 URL string `json:"url"` 101 Version string `json:"version"` 102 AppVersion string `json:"app_version"` 103 Description string `json:"description"` 104 Repository hubChartRepo `json:"repository"` 105 } 106 107 type hubSearchWriter struct { 108 elements []hubChartElement 109 columnWidth uint 110 listRepoURL bool 111 } 112 113 // func newHubSearchWriter(results []monocular.SearchResult, endpoint string, columnWidth uint, listRepoURL bool) *hubSearchWriter { 114 // var elements []hubChartElement 115 // for _, r := range results { 116 // // Backwards compatibility for Monocular 117 // url := endpoint + "/charts/" + r.ID 118 119 // // Check for artifactHub compatibility 120 // if r.ArtifactHub.PackageURL != "" { 121 // url = r.ArtifactHub.PackageURL 122 // } 123 124 // elements = append(elements, hubChartElement{url, r.Relationships.LatestChartVersion.Data.Version, r.Relationships.LatestChartVersion.Data.AppVersion, r.Attributes.Description, hubChartRepo{URL: r.Attributes.Repo.URL, Name: r.Attributes.Repo.Name}}) 125 // } 126 // return &hubSearchWriter{elements, columnWidth, listRepoURL} 127 // } 128 129 func (h *hubSearchWriter) WriteTable(out io.Writer) error { 130 if len(h.elements) == 0 { 131 _, err := out.Write([]byte("No results found\n")) 132 if err != nil { 133 return fmt.Errorf("unable to write results: %s", err) 134 } 135 return nil 136 } 137 table := uitable.New() 138 table.MaxColWidth = h.columnWidth 139 140 if h.listRepoURL { 141 table.AddRow("URL", "CHART VERSION", "APP VERSION", "DESCRIPTION", "REPO URL") 142 } else { 143 table.AddRow("URL", "CHART VERSION", "APP VERSION", "DESCRIPTION") 144 } 145 146 for _, r := range h.elements { 147 if h.listRepoURL { 148 table.AddRow(r.URL, r.Version, r.AppVersion, r.Description, r.Repository.URL) 149 } else { 150 table.AddRow(r.URL, r.Version, r.AppVersion, r.Description) 151 } 152 } 153 return output.EncodeTable(out, table) 154 } 155 156 func (h *hubSearchWriter) WriteJSON(out io.Writer) error { 157 return h.encodeByFormat(out, output.JSON) 158 } 159 160 func (h *hubSearchWriter) WriteYAML(out io.Writer) error { 161 return h.encodeByFormat(out, output.YAML) 162 } 163 164 func (h *hubSearchWriter) encodeByFormat(out io.Writer, format output.Format) error { 165 // Initialize the array so no results returns an empty array instead of null 166 chartList := make([]hubChartElement, 0, len(h.elements)) 167 168 for _, r := range h.elements { 169 chartList = append(chartList, hubChartElement{r.URL, r.Version, r.AppVersion, r.Description, r.Repository}) 170 } 171 172 switch format { 173 case output.JSON: 174 return output.EncodeJSON(out, chartList) 175 case output.YAML: 176 return output.EncodeYAML(out, chartList) 177 } 178 179 // Because this is a non-exported function and only called internally by 180 // WriteJSON and WriteYAML, we shouldn't get invalid types 181 return nil 182 }