diff --git a/internal/experimental/registry/client.go b/internal/experimental/registry/client.go index fdfab76f4..a9badb9d5 100644 --- a/internal/experimental/registry/client.go +++ b/internal/experimental/registry/client.go @@ -22,8 +22,10 @@ import ( "io" "io/ioutil" "net/http" + "sort" "strings" + "github.com/Masterminds/semver/v3" "github.com/containerd/containerd/remotes" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" @@ -553,7 +555,7 @@ func PushOptStrictMode(strictMode bool) PushOption { } } -// Tags lists all tags for a given repository +// Tags provides an all semver compliant tags for a given repository func (c *Client) Tags(ref string) ([]string, error) { parsedReference, err := registry.ParseReference(ref) if err != nil { @@ -565,5 +567,27 @@ func (c *Client) Tags(ref string) ([]string, error) { Client: c.registryAuthorizer, } - return registry.Tags(ctx(c.out, c.debug), &repository) + registrtyTags, err := registry.Tags(ctx(c.out, c.debug), &repository) + if err != nil { + return nil, err + } + + var tagVersions []*semver.Version + for _, tag := range registrtyTags { + tagVersion, err := semver.StrictNewVersion(tag) + if err != nil { + tagVersions = append(tagVersions, tagVersion) + } + } + + sort.Sort(semver.Collection(tagVersions)) + + tags := make([]string, len(tagVersions)) + + for iTv, tv := range tagVersions { + tags[iTv] = tv.String() + } + + return tags, nil + } diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index 634b351a6..27ca9929d 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -18,6 +18,7 @@ package resolver import ( "bytes" "encoding/json" + "fmt" "os" "path/filepath" "strings" @@ -136,15 +137,19 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string } found = false } else { + fmt.Println("Entering OCI block") version = d.Version if !FeatureGateOCI.IsEnabled() { return nil, errors.Wrapf(FeatureGateOCI.Error(), "repository %s is an OCI registry", d.Repository) } - // This works, fake it to test mocking the version - // tags := []string{"0.1.0", "0.1.1", "0.2.0"} - tags := d.OCITagVersions + // Retrive list of tags for repository + tags, err := r.registryClient.Tags(d.Repository) + if err != nil { + return nil, errors.Wrapf(err, "could not retrieve list of tags for repository", d.Repository) + } + vs = make(repo.ChartVersions, len(tags)) for ti, t := range tags { // Mock chart version objects diff --git a/pkg/chart/dependency.go b/pkg/chart/dependency.go index 890fa971f..b2819f373 100644 --- a/pkg/chart/dependency.go +++ b/pkg/chart/dependency.go @@ -47,10 +47,6 @@ type Dependency struct { ImportValues []interface{} `json:"import-values,omitempty"` // Alias usable alias to be used for the chart Alias string `json:"alias,omitempty"` - // OCI tag versions available to check against the constraint when Version - // contains a semantic version range. - // See (*Manager).resolve. - OCITagVersions []string `json:"-"` } // Validate checks for common problems with the dependency datastructure in diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 74286b3fd..d26dfd845 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -233,26 +233,6 @@ func (m *Manager) loadChartDir() (*chart.Chart, error) { // This returns a lock file, which has all of the dependencies normalized to a specific version. func (m *Manager) resolve(req []*chart.Dependency, repoNames map[string]string) (*chart.Lock, error) { res := resolver.New(m.ChartPath, m.RepositoryCache, m.RegistryClient) - // NOTE: When OCI dependencies specify a semver range in Version, - // (*Resolver).Resolve must somehow get the list of OCI tag versions - // available to check against this constraint. However for backward - // compatibility we can not change that function signature to pass a - // *registry.Client required to get tags from the ORAS tag listing API. - // However we can add a new backward compatible struct field to - // *chart.Dependency, so that we can pass these along to - // (*Resolver).resolve from here through reqs []*chart.Dependency. - for i, d := range req { - if registry.IsOCI(d.Repository) { - // TODO(scottrigby): fix HTTP error - // > Error: Get "https://localhost:5000/v2/helm-charts/tags/list": http: server gave HTTP response to HTTPS client - ref := strings.TrimPrefix(d.Repository, "oci://") - tags, err := m.RegistryClient.Tags(ref) - if err != nil { - return nil, err - } - req[i].OCITagVersions = tags - } - } return res.Resolve(req, repoNames) }