github.com/uhthomas/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  }