diff --git a/deployment/dockerdeploy/ghcrimageprovider.go b/deployment/dockerdeploy/ghcrimageprovider.go index ad45054..e7c55c4 100644 --- a/deployment/dockerdeploy/ghcrimageprovider.go +++ b/deployment/dockerdeploy/ghcrimageprovider.go @@ -135,20 +135,15 @@ func (p *GhcrImageProvider) ListImages(ctx context.Context) ([]deployment.Image, } func (p *GhcrImageProvider) SearchImages(ctx context.Context, version string) ([]deployment.Image, error) { - var respData struct { - Name string `json:"name"` - Tags []string `json:"tags"` - } - err := doRegistryGet(ctx, - "https://ghcr.io/v2/cb-vanilla/server/tags/list?n=10000", - "Bearer "+base64.StdEncoding.EncodeToString([]byte(p.GhcrPassword)), - &respData) + tags, err := doRegistryListTags(ctx, + "https://ghcr.io", "cb-vanilla", "server", + "Bearer "+base64.StdEncoding.EncodeToString([]byte(p.GhcrPassword))) if err != nil { return nil, errors.Wrap(err, "failed to search images") } var images []deployment.Image - for _, tagName := range respData.Tags { + for _, tagName := range tags { parsedParts := strings.Split(tagName, "-") if len(parsedParts) == 1 { // we ignore generic tags with no build number diff --git a/deployment/dockerdeploy/registrytools.go b/deployment/dockerdeploy/registrytools.go index 4d3f681..a7c57ef 100644 --- a/deployment/dockerdeploy/registrytools.go +++ b/deployment/dockerdeploy/registrytools.go @@ -3,8 +3,10 @@ package dockerdeploy import ( "context" "encoding/json" + "fmt" "net/http" + "github.com/peterhellberg/link" "github.com/pkg/errors" ) @@ -30,3 +32,59 @@ func doRegistryGet(ctx context.Context, url string, auth string, respData interf return nil } + +func doRegistryListTagsGet(ctx context.Context, url string, auth string, respData interface{}) (string, error) { + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return "", errors.Wrap(err, "failed to create request") + } + + if auth != "" { + req.Header.Set("Authorization", auth) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return "", errors.Wrap(err, "failed to list tags") + } + + err = json.NewDecoder(resp.Body).Decode(respData) + if err != nil { + return "", errors.Wrap(err, "failed to decode response") + } + + linkHdr := resp.Header.Get("Link") + links := link.Parse(linkHdr) + + nextLink := "" + for _, l := range links { + if l.Rel == "next" { + nextLink = l.URI + break + } + } + + return nextLink, nil +} + +func doRegistryListTags(ctx context.Context, url string, repo string, image string, auth string) ([]string, error) { + var respData struct { + Name string `json:"name"` + Tags []string `json:"tags"` + } + + nextPath := fmt.Sprintf("/v2/%s/%s/tags/list?n=1000", repo, image) + var allTags []string + for nextPath != "" { + reqNextPath, err := doRegistryListTagsGet(ctx, url+nextPath, auth, &respData) + if err != nil { + return nil, errors.Wrap(err, "failed to search images") + } + + allTags = append(allTags, respData.Tags...) + + nextPath = reqNextPath + } + + return allTags, nil +} diff --git a/go.mod b/go.mod index 4942ef4..977e488 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/peterhellberg/link v1.2.0 // indirect go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect diff --git a/go.sum b/go.sum index 79dfa74..9a4930a 100644 --- a/go.sum +++ b/go.sum @@ -163,6 +163,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c= +github.com/peterhellberg/link v1.2.0/go.mod h1:gYfAh+oJgQu2SrZHg5hROVRQe1ICoK0/HHJTcE0edxc= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=