Skip to content

Commit

Permalink
Merge pull request #316 from somtochiama/sourceignore
Browse files Browse the repository at this point in the history
[pkg/oci]: Add options to filter tags by semver and regex
  • Loading branch information
stefanprodan authored Aug 17, 2022
2 parents 17398b5 + 5c5f691 commit 63d691c
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 13 deletions.
44 changes: 43 additions & 1 deletion oci/client/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,25 @@ import (
"bytes"
"context"
"fmt"
"regexp"
"sort"
"strings"

"github.com/Masterminds/semver/v3"
"github.com/google/go-containerregistry/pkg/crane"
gcrv1 "github.com/google/go-containerregistry/pkg/v1"

"github.com/fluxcd/pkg/version"
)

// ListOptions contains options for listing tags from an OCI repository
type ListOptions struct {
semverFilter string
regexFilter string
}

// List fetches the tags and their manifests for a given OCI repository.
func (c *Client) List(ctx context.Context, url string) ([]Metadata, error) {
func (c *Client) List(ctx context.Context, url string, opts ListOptions) ([]Metadata, error) {
metas := make([]Metadata, 0)
tags, err := crane.ListTags(url, c.options...)
if err != nil {
Expand All @@ -37,12 +47,44 @@ func (c *Client) List(ctx context.Context, url string) ([]Metadata, error) {

sort.Slice(tags, func(i, j int) bool { return tags[i] > tags[j] })

var constraint *semver.Constraints
if opts.semverFilter != "" {
constraint, err = semver.NewConstraint(opts.semverFilter)
if err != nil {
return nil, fmt.Errorf("semver '%s' parse error: %w", opts.semverFilter, err)
}
}

var re *regexp.Regexp
if opts.regexFilter != "" {
re, err = regexp.Compile(opts.regexFilter)
if err != nil {
return nil, fmt.Errorf("regex '%s' parse error: %w", opts.regexFilter, err)
}
}

for _, tag := range tags {
// exclude cosign signatures
if strings.HasSuffix(tag, ".sig") {
continue
}

if constraint != nil {
v, err := version.ParseVersion(tag)
// version isn't a valid semver so we can skip
if err != nil {
continue
}

if !constraint.Check(v) {
continue
}
}

if re != nil && !re.Match([]byte(tag)) {
continue
}

meta := Metadata{
URL: fmt.Sprintf("%s:%s", url, tag),
}
Expand Down
60 changes: 48 additions & 12 deletions oci/client/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func Test_List(t *testing.T) {
ctx := context.Background()
c := NewLocalClient()
repo := "test-list" + randStringRunes(5)
tags := []string{"v0.0.1", "v0.0.2", "v0.0.3"}
tags := []string{"v0.0.1", "v0.0.2", "v0.0.3", "v6.0.0", "v6.0.1", "v6.0.2", "v6.0.2-rc.1", "v6.0.2-alpha", "staging-fb3355b"}
source := "github.com/fluxcd/fluxv2"
rev := "rev"
ct := time.Now()
Expand All @@ -54,19 +54,55 @@ func Test_List(t *testing.T) {
g.Expect(err).ToNot(HaveOccurred())
}

metadata, err := c.List(ctx, fmt.Sprintf("%s/%s", dockerReg, repo))
g.Expect(err).ToNot(HaveOccurred())
tests := []struct {
name string
regexFilter string
semverFilter string
expectedTags []string
}{
{
name: "list all tags",
expectedTags: tags,
},
{
name: "list 6.0.x tags",
semverFilter: "6.0.x",
expectedTags: []string{"v6.0.0", "v6.0.1", "v6.0.2"},
},
{
name: "list tags starting with staging",
regexFilter: "^staging.*$",
expectedTags: []string{"staging-fb3355b"},
},
{
name: "filter for alpha 6.0.x",
semverFilter: ">=6.0.0-rc",
regexFilter: "alpha",
expectedTags: []string{"v6.0.2-alpha"},
},
}

g.Expect(len(metadata)).To(Equal(len(tags)))
for _, meta := range metadata {
tag, err := name.NewTag(meta.URL)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(tag.TagStr()).Should(BeElementOf(tags))
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
metadata, err := c.List(ctx, fmt.Sprintf("%s/%s", dockerReg, repo), ListOptions{
semverFilter: tt.semverFilter,
regexFilter: tt.regexFilter,
})
g.Expect(err).ToNot(HaveOccurred())

g.Expect(meta.ToAnnotations()).To(Equal(m.ToAnnotations()))
g.Expect(len(metadata)).To(Equal(len(tt.expectedTags)))
for _, meta := range metadata {
tag, err := name.NewTag(meta.URL)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(tag.TagStr()).Should(BeElementOf(tt.expectedTags))

digest, err := crane.Digest(meta.URL, c.options...)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(meta.Digest).To(Equal(digest))
g.Expect(meta.ToAnnotations()).To(Equal(m.ToAnnotations()))

digest, err := crane.Digest(meta.URL, c.options...)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(meta.Digest).To(Equal(digest))
}
})
}
}
3 changes: 3 additions & 0 deletions oci/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ go 1.18
replace (
github.com/fluxcd/pkg/sourceignore => ../sourceignore
github.com/fluxcd/pkg/untar => ../untar
github.com/fluxcd/pkg/version => ../version
)

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0
github.com/Masterminds/semver/v3 v3.1.1
github.com/aws/aws-sdk-go v1.44.53
github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f
github.com/fluxcd/pkg/sourceignore v0.1.0
github.com/fluxcd/pkg/untar v0.1.0
github.com/fluxcd/pkg/version v0.1.0
github.com/google/go-containerregistry v0.10.0
github.com/onsi/gomega v1.19.0
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
Expand Down
2 changes: 2 additions & 0 deletions oci/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5H
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
Expand Down

0 comments on commit 63d691c

Please sign in to comment.