...

Source file src/edge-infra.dev/pkg/f8n/warehouse/promote/repository.go

Documentation: edge-infra.dev/pkg/f8n/warehouse/promote

     1  package promote
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path"
     7  	"strings"
     8  
     9  	"github.com/google/go-containerregistry/pkg/name"
    10  
    11  	"edge-infra.dev/pkg/f8n/warehouse/oci/remote"
    12  )
    13  
    14  const dockerRegistrySuffix = "-docker.pkg.dev"
    15  
    16  // repository represents a GAR repository instance
    17  type Repository struct {
    18  	Name      string // name of the GAR repository instance, e.g. warehouse
    19  	ProjectID string // project-id where GAR registry exists, e.g. ret-edge-stage1-foreman
    20  	Registry  string // the OCI compliant registry, e.g. us-east1-docker.pkg.dev
    21  	Ref       string // full GAR repository reference, e.g. us-east1-docker.pkg.dev/ret-edge-stage1-foreman/warehouse
    22  }
    23  
    24  func (repo Repository) String() string {
    25  	return repo.Ref
    26  }
    27  
    28  // Return the full reference for a given package and its tag
    29  func (repo Repository) NewPackageTag(pkgName, tag string) (name.Tag, error) {
    30  	gcTag, err := name.NewTag(fmt.Sprintf("%s/%s:%s", repo.Ref, pkgName, tag))
    31  	if err != nil {
    32  		return name.Tag{}, err
    33  	}
    34  
    35  	return gcTag, nil
    36  }
    37  
    38  // Return the full reference for a given package and its tag
    39  func (repo Repository) NewPackageDigest(pkgName, version string) (name.Digest, error) {
    40  	gcDigest, err := name.NewDigest(fmt.Sprintf("%s/%s@%s", repo.Ref, pkgName, version))
    41  	if err != nil {
    42  		return name.Digest{}, err
    43  	}
    44  
    45  	return gcDigest, nil
    46  }
    47  
    48  // Return the full reference for a given package and its tag
    49  func (repo Repository) PackageTagRef(pkgName, version string) string {
    50  	return fmt.Sprintf("%s/%s:%s", repo.Ref, pkgName, version)
    51  }
    52  
    53  // Return the full reference for a given package and its digest
    54  func (repo Repository) PackageDigestRef(pkgName, version string) string {
    55  	return fmt.Sprintf("%s/%s@%s", repo.Ref, pkgName, version)
    56  }
    57  
    58  // Return the full reference for a given package and its version ("latest" or hash)
    59  func (repo Repository) PackageTagRefs(pkgName string, tags []string) []string {
    60  	packageRefs := []string{}
    61  	for _, tag := range tags {
    62  		packageRefs = append(packageRefs, fmt.Sprintf("%s/%s:%s", repo.Ref, pkgName, tag))
    63  	}
    64  
    65  	return packageRefs
    66  }
    67  
    68  // Finds the hash for the latest version of the package in the repository
    69  func (repo Repository) EnsurePackageDigestExists(pkgName string, digest string) error {
    70  	pkgRef := repo.PackageDigestRef(pkgName, digest)
    71  	ref, err := name.ParseReference(pkgRef)
    72  	if err != nil {
    73  		return fmt.Errorf("package reference is invalid: %s, reason: %v", pkgRef, err)
    74  	}
    75  
    76  	_, err = remote.Head(ref)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	return nil
    82  }
    83  
    84  // Finds the hash for the latest version of the package in the repository
    85  func (repo Repository) GetLatestPackageVersion(pkgName string) (string, error) {
    86  	pkgRef := repo.PackageTagRef(pkgName, Latest)
    87  	ref, err := name.ParseReference(pkgRef)
    88  	if err != nil {
    89  		return "", fmt.Errorf("package reference is invalid: %s, reason: %v", pkgRef, err)
    90  	}
    91  
    92  	artifact, err := remote.Get(ref)
    93  	if err != nil {
    94  		return "", err
    95  	}
    96  
    97  	hash, err := artifact.Digest()
    98  	if err != nil {
    99  		return "", err
   100  	}
   101  
   102  	return hash.String(), nil
   103  }
   104  
   105  // Lists the packages in the repository
   106  func (repo Repository) ListPackages(ctx context.Context) (pkgNames []string, err error) {
   107  	registry, err := name.NewRegistry(repo.Registry)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	// get all OCI repositories (packages) in the registry
   113  	pkgs, err := remote.Catalog(ctx, registry)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	// filter results for packages in this GAR repository instance
   119  	for _, pkg := range pkgs {
   120  		if strings.Contains(pkg, path.Join(repo.ProjectID, repo.Name)) {
   121  			pkgNames = append(pkgNames, path.Base(pkg))
   122  		}
   123  	}
   124  
   125  	return pkgNames, nil
   126  }
   127  
   128  func newRepository(repoName, projectID, gcpLocation string) Repository {
   129  	registry := gcpLocation + dockerRegistrySuffix
   130  	return Repository{
   131  		Name:      repoName,
   132  		ProjectID: projectID,
   133  		Registry:  registry,
   134  		Ref:       path.Join(registry, projectID, repoName),
   135  	}
   136  }
   137  

View as plain text