mirror of https://github.com/artifacthub/hub.git
92 lines
2.3 KiB
Go
92 lines
2.3 KiB
Go
package repo
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"io/ioutil"
|
|
"net/url"
|
|
"path"
|
|
"time"
|
|
|
|
"github.com/artifacthub/hub/internal/hub"
|
|
"helm.sh/helm/v3/pkg/getter"
|
|
helmrepo "helm.sh/helm/v3/pkg/repo"
|
|
"sigs.k8s.io/yaml"
|
|
)
|
|
|
|
const (
|
|
helmRepoIndexFile = "index.yaml"
|
|
)
|
|
|
|
// HelmIndexLoader provides a mechanism to load a Helm repository index file,
|
|
// verifying it is valid.
|
|
type HelmIndexLoader struct{}
|
|
|
|
// LoadIndex downloads and parses the index file of the provided repository.
|
|
func (l *HelmIndexLoader) LoadIndex(r *hub.Repository) (*helmrepo.IndexFile, string, error) {
|
|
repoConfig := &helmrepo.Entry{
|
|
Name: r.Name,
|
|
URL: r.URL,
|
|
Username: r.AuthUser,
|
|
Password: r.AuthPass,
|
|
}
|
|
getters := getter.Providers{
|
|
{
|
|
Schemes: []string{"http", "https"},
|
|
New: func(options ...getter.Option) (getter.Getter, error) {
|
|
return getter.NewHTTPGetter(getter.WithTimeout(10 * time.Second))
|
|
},
|
|
},
|
|
}
|
|
chartRepository, err := helmrepo.NewChartRepository(repoConfig, getters)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
indexBytes, err := downloadIndexFile(chartRepository)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
indexFile, err := loadIndexFile(indexBytes)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
hash := sha256.Sum256(indexBytes)
|
|
digest := hex.EncodeToString(hash[:])
|
|
return indexFile, digest, nil
|
|
}
|
|
|
|
// downloadIndexFile downloads a Helm repository's index file.
|
|
func downloadIndexFile(r *helmrepo.ChartRepository) ([]byte, error) {
|
|
// Prepare index file url
|
|
parsedURL, err := url.Parse(r.Config.URL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
parsedURL.RawPath = path.Join(parsedURL.RawPath, helmRepoIndexFile)
|
|
parsedURL.Path = path.Join(parsedURL.Path, helmRepoIndexFile)
|
|
indexURL := parsedURL.String()
|
|
|
|
// Fetch index file content from remote location
|
|
resp, err := r.Client.Get(indexURL,
|
|
getter.WithURL(r.Config.URL),
|
|
getter.WithBasicAuth(r.Config.Username, r.Config.Password),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ioutil.ReadAll(resp)
|
|
}
|
|
|
|
// loadIndexFile reads and parses a Helm repository's index file.
|
|
func loadIndexFile(indexBytes []byte) (*helmrepo.IndexFile, error) {
|
|
indexFile := &helmrepo.IndexFile{}
|
|
if err := yaml.UnmarshalStrict(indexBytes, indexFile); err != nil {
|
|
return nil, err
|
|
}
|
|
if indexFile.APIVersion == "" {
|
|
return nil, helmrepo.ErrNoAPIVersion
|
|
}
|
|
indexFile.SortEntries()
|
|
return indexFile, nil
|
|
}
|