github.com/zsuzhengdu/helm@v3.0.0-beta.3+incompatible/internal/monocular/search.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 monocular 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "net/http" 23 "net/url" 24 "path" 25 "time" 26 27 "helm.sh/helm/internal/version" 28 "helm.sh/helm/pkg/chart" 29 ) 30 31 // SearchPath is the url path to the search API in monocular. 32 const SearchPath = "api/chartsvc/v1/charts/search" 33 34 // The structs below represent the structure of the response from the monocular 35 // search API. The structs were not imported from monocular because monocular 36 // imports from Helm v2 (avoiding circular version dependency) and the mappings 37 // are slightly different (monocular search results do not directly reflect 38 // the struct definitions). 39 40 // SearchResult represents an individual chart result 41 type SearchResult struct { 42 ID string `json:"id"` 43 Type string `json:"type"` 44 Attributes Chart `json:"attributes"` 45 Links Links `json:"links"` 46 Relationships Relationships `json:"relationships"` 47 } 48 49 // Chart is the attributes for the chart 50 type Chart struct { 51 Name string `json:"name"` 52 Repo Repo `json:"repo"` 53 Description string `json:"description"` 54 Home string `json:"home"` 55 Keywords []string `json:"keywords"` 56 Maintainers []chart.Maintainer `json:"maintainers"` 57 Sources []string `json:"sources"` 58 Icon string `json:"icon"` 59 } 60 61 // Repo contains the name in monocular the the url for the repository 62 type Repo struct { 63 Name string `json:"name"` 64 URL string `json:"url"` 65 } 66 67 // Links provides a set of links relative to the chartsvc base 68 type Links struct { 69 Self string `json:"self"` 70 } 71 72 // Relationships provides information on the latest version of the chart 73 type Relationships struct { 74 LatestChartVersion LatestChartVersion `json:"latestChartVersion"` 75 } 76 77 // LatestChartVersion provides the details on the latest version of the chart 78 type LatestChartVersion struct { 79 Data ChartVersion `json:"data"` 80 Links Links `json:"links"` 81 } 82 83 // ChartVersion provides the specific data on the chart version 84 type ChartVersion struct { 85 Version string `json:"version"` 86 AppVersion string `json:"app_version"` 87 Created time.Time `json:"created"` 88 Digest string `json:"digest"` 89 Urls []string `json:"urls"` 90 Readme string `json:"readme"` 91 Values string `json:"values"` 92 } 93 94 // Search performs a search against the monocular search API 95 func (c *Client) Search(term string) ([]SearchResult, error) { 96 97 // Create the URL to the search endpoint 98 // Note, this is currently an internal API for the Hub. This should be 99 // formatted without showing how monocular operates. 100 p, err := url.Parse(c.BaseURL) 101 if err != nil { 102 return nil, err 103 } 104 105 // Set the path to the monocular API endpoint for search 106 p.Path = path.Join(p.Path, SearchPath) 107 108 p.RawQuery = "q=" + url.QueryEscape(term) 109 110 // Create request 111 req, err := http.NewRequest("GET", p.String(), nil) 112 if err != nil { 113 return nil, err 114 } 115 116 // Set the user agent so that monocular can identify where the request 117 // is coming from 118 req.Header.Set("User-Agent", version.GetUserAgent()) 119 120 res, err := http.DefaultClient.Do(req) 121 if err != nil { 122 return nil, err 123 } 124 defer res.Body.Close() 125 126 if res.StatusCode != 200 { 127 return nil, fmt.Errorf("failed to fetch %s : %s", p.String(), res.Status) 128 } 129 130 result := &searchResponse{} 131 132 json.NewDecoder(res.Body).Decode(result) 133 134 return result.Data, nil 135 } 136 137 type searchResponse struct { 138 Data []SearchResult `json:"data"` 139 }