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
17 type Repository struct {
18 Name string
19 ProjectID string
20 Registry string
21 Ref string
22 }
23
24 func (repo Repository) String() string {
25 return repo.Ref
26 }
27
28
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
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
49 func (repo Repository) PackageTagRef(pkgName, version string) string {
50 return fmt.Sprintf("%s/%s:%s", repo.Ref, pkgName, version)
51 }
52
53
54 func (repo Repository) PackageDigestRef(pkgName, version string) string {
55 return fmt.Sprintf("%s/%s@%s", repo.Ref, pkgName, version)
56 }
57
58
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
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
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
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
113 pkgs, err := remote.Catalog(ctx, registry)
114 if err != nil {
115 return nil, err
116 }
117
118
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