Przeglądaj źródła

Merge branch 'nafees/gar-fixes' into dev

Mohammed Nafees 3 lat temu
rodzic
commit
59d97d6aeb

+ 6 - 6
dashboard/src/main/home/launch/launch-flow/LaunchFlow.tsx

@@ -71,16 +71,16 @@ const LaunchFlow: React.FC<PropsType> = (props) => {
   };
 
   const getFullActionConfig = (): FullActionConfigType => {
-    let imageRepoUri = `${selectedRegistry?.url}/${templateName}-${selectedNamespace}`;
+    let imageRepoURI = `${selectedRegistry?.url}/${templateName}-${selectedNamespace}`;
 
     // DockerHub registry integration is per repo
     if (selectedRegistry?.service === "dockerhub") {
-      imageRepoUri = selectedRegistry?.url;
+      imageRepoURI = selectedRegistry?.url;
     }
 
     // Customize image repo URI for GAR
-    if (imageRepoUri.includes("pkg.dev")) {
-      imageRepoUri = `${imageRepoUri}/${templateName}-${selectedNamespace}`;
+    if (imageRepoURI.includes("pkg.dev")) {
+      imageRepoURI = `${imageRepoURI}/${templateName}-${selectedNamespace}`;
     }
 
     if (actionConfig.kind === "github") {
@@ -91,7 +91,7 @@ const LaunchFlow: React.FC<PropsType> = (props) => {
         registry_id: selectedRegistry?.id,
         dockerfile_path: dockerfilePath,
         folder_path: folderPath,
-        image_repo_uri: imageRepoUri,
+        image_repo_uri: imageRepoURI,
         git_repo_id: actionConfig.git_repo_id,
         should_create_workflow: shouldCreateWorkflow,
       };
@@ -103,7 +103,7 @@ const LaunchFlow: React.FC<PropsType> = (props) => {
         registry_id: selectedRegistry?.id,
         dockerfile_path: dockerfilePath,
         folder_path: folderPath,
-        image_repo_uri: imageRepoUri,
+        image_repo_uri: imageRepoURI,
         gitlab_integration_id: actionConfig.gitlab_integration_id,
         should_create_workflow: shouldCreateWorkflow,
       };

+ 90 - 19
internal/registry/registry.go

@@ -31,6 +31,7 @@ import (
 	"github.com/digitalocean/godo"
 	"github.com/docker/cli/cli/config/configfile"
 	"github.com/docker/cli/cli/config/types"
+	"github.com/docker/distribution/reference"
 
 	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry"
 
@@ -77,9 +78,9 @@ func (r *Registry) ListRepositories(
 	if r.GCPIntegrationID != 0 {
 		if strings.Contains(r.URL, "pkg.dev") {
 			return r.listGARRepositories(repo)
-		} else {
-			return r.listGCRRepositories(repo)
 		}
+
+		return r.listGCRRepositories(repo)
 	}
 
 	if r.DOIntegrationID != 0 {
@@ -241,6 +242,9 @@ func (source *garTokenSource) Token() (*oauth2.Token, error) {
 	return source.reg.GetGARToken(source.repo)
 }
 
+// GAR has the concept of a "repository" which is a collection of images, unlike ECR or others
+// where a repository is a single image. This function returns the list of fully qualified names
+// of GAR images including their repository names.
 func (r *Registry) listGARRepositories(
 	repo repository.Repository,
 ) ([]*ptypes.RegistryRepository, error) {
@@ -262,7 +266,7 @@ func (r *Registry) listGARRepositories(
 		return nil, err
 	}
 
-	var res []*ptypes.RegistryRepository
+	var repoNames []string
 	nextToken := ""
 
 	parsedURL, err := url.Parse("https://" + r.URL)
@@ -292,11 +296,7 @@ func (r *Registry) listGARRepositories(
 			repoSlice := strings.Split(resp.GetName(), "/")
 			repoName := repoSlice[len(repoSlice)-1]
 
-			res = append(res, &ptypes.RegistryRepository{
-				Name:      resp.GetName(),
-				CreatedAt: resp.GetCreateTime().AsTime(),
-				URI:       parsedURL.Host + "/" + gcpInt.GCPProjectID + "/" + repoName,
-			})
+			repoNames = append(repoNames, repoName)
 		}
 
 		if it.PageInfo().Token == "" {
@@ -306,6 +306,58 @@ func (r *Registry) listGARRepositories(
 		nextToken = it.PageInfo().Token
 	}
 
+	svc, err := v1artifactregistry.NewService(context.Background(), option.WithTokenSource(&garTokenSource{
+		reg:  r,
+		repo: repo,
+	}), option.WithScopes("roles/artifactregistry.reader"))
+
+	if err != nil {
+		return nil, err
+	}
+
+	resMap := make(map[string]*ptypes.RegistryRepository)
+	dockerSvc := v1artifactregistry.NewProjectsLocationsRepositoriesDockerImagesService(svc)
+
+	for _, repoName := range repoNames {
+		for {
+			resp, err := dockerSvc.List(fmt.Sprintf("projects/%s/locations/%s/repositories/%s",
+				gcpInt.GCPProjectID, location, repoName)).PageSize(1000).PageToken(nextToken).Do()
+
+			if err != nil {
+				return nil, err
+			}
+
+			for _, image := range resp.DockerImages {
+				named, err := reference.ParseNamed(image.Uri)
+
+				if err != nil {
+					// let us skip this image becaue it has a malformed URI coming from the GCP API
+					continue
+				}
+
+				uploadTime, _ := time.Parse(time.RFC3339, image.UploadTime)
+
+				resMap[named.Name()] = &ptypes.RegistryRepository{
+					Name:      repoName,
+					URI:       named.Name(),
+					CreatedAt: uploadTime,
+				}
+			}
+
+			if resp.NextPageToken == "" {
+				break
+			}
+
+			nextToken = resp.NextPageToken
+		}
+	}
+
+	var res []*ptypes.RegistryRepository
+
+	for _, v := range resMap {
+		res = append(res, v)
+	}
+
 	return res, nil
 }
 
@@ -1172,6 +1224,14 @@ func (r *Registry) listGCRImages(repoName string, repo repository.Repository) ([
 }
 
 func (r *Registry) listGARImages(repoName string, repo repository.Repository) ([]*ptypes.Image, error) {
+	// FIXME: GAR implemets the repo/image scheme so we should be looking out for that
+
+	// repoImageSlice := strings.Split(repoName, "/")
+
+	// if len(repoImageSlice) != 2 {
+	// 	return nil, fmt.Errorf("invalid GAR repo name: %s", repoName)
+	// }
+
 	gcpInt, err := repo.GCPIntegration().ReadGCPIntegration(
 		r.ProjectID,
 		r.GCPIntegrationID,
@@ -1190,7 +1250,6 @@ func (r *Registry) listGARImages(repoName string, repo repository.Repository) ([
 		return nil, err
 	}
 
-	nextToken := ""
 	var res []*ptypes.Image
 
 	parsedURL, err := url.Parse("https://" + r.URL)
@@ -1200,8 +1259,8 @@ func (r *Registry) listGARImages(repoName string, repo repository.Repository) ([
 	}
 
 	location := strings.TrimSuffix(parsedURL.Host, "-docker.pkg.dev")
-
 	dockerSvc := v1artifactregistry.NewProjectsLocationsRepositoriesDockerImagesService(svc)
+	nextToken := ""
 
 	for {
 		resp, err := dockerSvc.List(fmt.Sprintf("projects/%s/locations/%s/repositories/%s",
@@ -1212,15 +1271,27 @@ func (r *Registry) listGARImages(repoName string, repo repository.Repository) ([
 		}
 
 		for _, image := range resp.DockerImages {
-			uploadTime, _ := time.Parse(time.RFC3339, image.UploadTime)
-
-			for _, tag := range image.Tags {
-				res = append(res, &ptypes.Image{
-					RepositoryName: repoName,
-					Tag:            tag,
-					PushedAt:       &uploadTime,
-					Digest:         strings.Split(image.Name, "@")[1],
-				})
+			named, err := reference.ParseNamed(image.Uri)
+
+			if err != nil {
+				continue
+			}
+
+			paths := strings.Split(reference.Path(named), "/")
+
+			imageName := paths[len(paths)-1]
+
+			if imageName == repoName {
+				uploadTime, _ := time.Parse(time.RFC3339, image.UploadTime)
+
+				for _, tag := range image.Tags {
+					res = append(res, &ptypes.Image{
+						RepositoryName: repoName,
+						Tag:            tag,
+						PushedAt:       &uploadTime,
+						Digest:         strings.Split(image.Uri, "@")[1],
+					})
+				}
 			}
 		}