Просмотр исходного кода

Merge pull request #1683 from porter-dev/nafees/gcr-tags-fix

[hotfix] Fix GCR URL for fetching tags
abelanger5 4 лет назад
Родитель
Сommit
2d3a973fb3
5 измененных файлов с 37 добавлено и 48 удалено
  1. 1 1
      cli/cmd/deploy/create.go
  2. 1 1
      cli/cmd/deploy/deploy.go
  3. 31 45
      cli/cmd/docker/agent.go
  4. 1 1
      go.mod
  5. 3 0
      go.sum

+ 1 - 1
cli/cmd/deploy/create.go

@@ -273,7 +273,7 @@ func (c *CreateAgent) CreateFromDocker(
 		return "", err
 	}
 
-	imageExists := agent.CheckIfImageExists(fmt.Sprintf("%s:%s", imageURL, imageTag))
+	imageExists := agent.CheckIfImageExists(imageURL, imageTag)
 
 	if imageExists && imageTag != "latest" && !forceBuild {
 		fmt.Printf("%s:%s already exists in the registry, so skipping build\n", imageURL, imageTag)

+ 1 - 1
cli/cmd/deploy/deploy.go

@@ -140,7 +140,7 @@ func NewDeployAgent(client *client.Client, app string, opts *DeployOpts) (*Deplo
 	err = coalesceEnvGroups(deployAgent.client, deployAgent.opts.ProjectID, deployAgent.opts.ClusterID,
 		deployAgent.opts.Namespace, deployAgent.opts.EnvGroups, deployAgent.release.Config)
 
-	deployAgent.imageExists = deployAgent.agent.CheckIfImageExists(fmt.Sprintf("%s:%s", deployAgent.imageRepo, deployAgent.tag))
+	deployAgent.imageExists = deployAgent.agent.CheckIfImageExists(deployAgent.imageRepo, deployAgent.tag)
 
 	return deployAgent, err
 }

+ 31 - 45
cli/cmd/docker/agent.go

@@ -11,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/digitalocean/godo"
 	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/container"
@@ -159,17 +160,21 @@ var PullImageErrNotFound = fmt.Errorf("Requested image not found")
 
 var PullImageErrUnauthorized = fmt.Errorf("Could not pull image: unauthorized")
 
-func getRegistryRepositoryPair(image, prefix string) []string {
-	if !strings.HasSuffix(prefix, "/") {
-		prefix = prefix + "/"
+func getRegistryRepositoryPair(imageRepo string) ([]string, error) {
+	named, err := reference.ParseNamed(imageRepo)
+
+	if err != nil {
+		return nil, err
 	}
 
-	return strings.Split(strings.TrimPrefix(strings.Split(image, ":")[0], prefix), "/")
+	path := reference.Path(named)
+
+	return strings.SplitN(path, "/", 2), nil
 }
 
 // CheckIfImageExists checks if the image exists in the registry
-func (a *Agent) CheckIfImageExists(image string) bool {
-	registryToken, err := a.getContainerRegistryToken(image)
+func (a *Agent) CheckIfImageExists(imageRepo, imageTag string) bool {
+	registryToken, err := a.getContainerRegistryToken(imageRepo)
 
 	if err != nil {
 		return false
@@ -178,15 +183,21 @@ func (a *Agent) CheckIfImageExists(image string) bool {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
 	defer cancel()
 
-	if strings.Contains(image, "gcr.io") {
-		gcrRegRepo := getRegistryRepositoryPair(image, "gcr.io")
+	if strings.Contains(imageRepo, "gcr.io") {
+		gcrRegRepo, err := getRegistryRepositoryPair(imageRepo)
 
-		if len(gcrRegRepo) != 2 {
+		if err != nil {
+			return false
+		}
+
+		named, err := reference.ParseNamed(imageRepo)
+
+		if err != nil {
 			return false
 		}
 
 		req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf(
-			"https://gcr.io/v2/%s/%s/tags/list", gcrRegRepo[0], gcrRegRepo[1],
+			"https://%s/v2/%s/%s/tags/list", reference.Domain(named), gcrRegRepo[0], gcrRegRepo[1],
 		), nil)
 
 		if err != nil {
@@ -214,59 +225,33 @@ func (a *Agent) CheckIfImageExists(image string) bool {
 			return false
 		}
 
-		reqTag := strings.Split(image, ":")[1]
-
 		for _, tag := range tags.Tags {
-			if tag == reqTag {
+			if tag == imageTag {
 				return true
 			}
 		}
 
 		return false
-	} else if strings.Contains(image, "registry.digitalocean.com") {
-		doRegRepo := getRegistryRepositoryPair(image, "registry.digitalocean.com")
-
-		if len(doRegRepo) != 2 {
-			return false
-		}
-
-		req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf(
-			"https://api.digitalocean.com/v2/registry/%s/repositories/%s/digests", doRegRepo[0], doRegRepo[1],
-		), nil)
-
-		if err != nil {
-			return false
-		}
-
-		req.Header.Add("Content-Type", "application/json")
-		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", registryToken))
-
-		resp, err := http.DefaultClient.Do(req)
+	} else if strings.Contains(imageRepo, "registry.digitalocean.com") {
+		doRegRepo, err := getRegistryRepositoryPair(imageRepo)
 
 		if err != nil {
 			return false
 		}
 
-		defer resp.Body.Close()
+		doClient := godo.NewFromToken(registryToken)
 
-		// refer https://github.com/digitalocean/godo/blob/main/registry.go#L106
-		var digest struct {
-			Manifests []struct {
-				Tags []string `json:"tags,omitempty"`
-			} `json:"manifests,omitempty"`
-		}
-
-		err = json.NewDecoder(resp.Body).Decode(&digest)
+		manifests, _, err := doClient.Registry.ListRepositoryManifests(
+			ctx, doRegRepo[0], doRegRepo[1], &godo.ListOptions{},
+		)
 
 		if err != nil {
 			return false
 		}
 
-		reqTag := strings.Split(image, ":")[1]
-
-		for _, manifest := range digest.Manifests {
+		for _, manifest := range manifests {
 			for _, tag := range manifest.Tags {
-				if tag == reqTag {
+				if tag == imageTag {
 					return true
 				}
 			}
@@ -275,6 +260,7 @@ func (a *Agent) CheckIfImageExists(image string) bool {
 		return false
 	}
 
+	image := imageRepo + ":" + imageTag
 	encodedRegistryAuth, err := a.getEncodedRegistryAuth(image)
 
 	if err != nil {

+ 1 - 1
go.mod

@@ -11,7 +11,7 @@ require (
 	github.com/buildpacks/pack v0.19.0
 	github.com/cli/cli v1.11.0
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
-	github.com/digitalocean/godo v1.56.0
+	github.com/digitalocean/godo v1.75.0
 	github.com/docker/cli v20.10.11+incompatible
 	github.com/docker/distribution v2.7.1+incompatible
 	github.com/docker/docker v20.10.12+incompatible

+ 3 - 0
go.sum

@@ -431,6 +431,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/digitalocean/godo v1.56.0 h1:wXqWJyywrDO3YO2T4Kh8TwbCPOa+OI2vC8qh0/Ngmjk=
 github.com/digitalocean/godo v1.56.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU=
+github.com/digitalocean/godo v1.75.0 h1:UijUv60I095CqJqGKdjY2RTPnnIa4iFddmq+1wfyS4Y=
+github.com/digitalocean/godo v1.75.0/go.mod h1:GBmu8MkjZmNARE7IXRPmkbbnocNN8+uBm0xbEVw2LCs=
 github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684 h1:DBZ2sN7CK6dgvHVpQsQj4sRMCbWTmd17l+5SUCjnQSY=
 github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684/go.mod h1:UfCu3YXJJCI+IdnqGgYP82dk2+Joxmv+mUTVBES6wac=
 github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
@@ -1644,6 +1646,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
 golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=