Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit ca9eaab

Browse files
author
Jean-Christophe Sirot
committed
Large refactoring of the bundle store in order to handle ids in commands
Signed-off-by: Jean-Christophe Sirot <[email protected]>
1 parent 0d08d65 commit ca9eaab

File tree

5 files changed

+175
-43
lines changed

5 files changed

+175
-43
lines changed

internal/cnab/cnab.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/docker/app/internal"
1111
"github.com/docker/app/internal/log"
1212
"github.com/docker/app/internal/packager"
13-
"github.com/docker/app/internal/store"
1413
appstore "github.com/docker/app/internal/store"
1514
"github.com/docker/cli/cli/command"
1615
"github.com/docker/cnab-to-oci/remotes"
@@ -90,7 +89,9 @@ func ResolveBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name
9089

9190
// GetBundle searches for the bundle locally and tries to pull it if not found
9291
func GetBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name string) (*bundle.Bundle, reference.Reference, error) {
93-
ref, err := store.StringToRef(name)
92+
//ref, err := store.StringToRef(name)
93+
ref, err := bundleStore.LookUp(name)
94+
fmt.Println(ref)
9495
if err != nil {
9596
return nil, nil, err
9697
}

internal/store/app.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ func (a ApplicationStore) BundleStore() (BundleStore, error) {
7474
if err := os.MkdirAll(path, 0755); err != nil {
7575
return nil, errors.Wrapf(err, "failed to create bundle store directory %q", path)
7676
}
77-
return &bundleStore{path: path}, nil
77+
//return &bundleStore{path: path}, nil
78+
return NewBundleStore(path)
7879
}
7980

8081
func makeDigestedDirectory(context string) string {

internal/store/bundle.go

Lines changed: 158 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111

1212
"github.com/deislabs/cnab-go/bundle"
1313
"github.com/docker/distribution/reference"
14-
"github.com/opencontainers/go-digest"
1514
"github.com/pkg/errors"
1615
)
1716

@@ -22,12 +21,27 @@ type BundleStore interface {
2221
Read(ref reference.Reference) (*bundle.Bundle, error)
2322
List() ([]reference.Reference, error)
2423
Remove(ref reference.Reference) error
24+
LookUp(refOrID string) (reference.Reference, error)
2525
}
2626

2727
var _ BundleStore = &bundleStore{}
2828

2929
type bundleStore struct {
30-
path string
30+
path string
31+
referenceMap map[ID][]reference.Reference
32+
}
33+
34+
func NewBundleStore(path string) (BundleStore, error) {
35+
bundleStore := &bundleStore{
36+
path: path,
37+
referenceMap: make(map[ID][]reference.Reference),
38+
}
39+
err := bundleStore.scanAllBundles()
40+
if err != nil {
41+
return nil, err
42+
}
43+
fmt.Println(bundleStore.referenceMap)
44+
return bundleStore, nil
3145
}
3246

3347
// We store bundles either by image:tags, image:digest or by unique ID (actually, bundle's sha256).
@@ -72,56 +86,27 @@ func (b *bundleStore) Store(ref reference.Reference, bndle *bundle.Bundle) (refe
7286
}
7387

7488
func (b *bundleStore) Read(ref reference.Reference) (*bundle.Bundle, error) {
75-
path, err := b.storePath(ref)
89+
paths, err := b.storePaths(ref)
90+
fmt.Println(paths)
7691
if err != nil {
7792
return nil, errors.Wrapf(err, "failed to read bundle %q", ref)
7893
}
7994

80-
data, err := ioutil.ReadFile(filepath.Join(path, "bundle.json"))
95+
bndl, err := b.fetchBundleJSON(filepath.Join(paths[0], "bundle.json"))
8196
if err != nil {
8297
return nil, errors.Wrapf(err, "failed to read bundle %q", ref)
8398
}
84-
var bndle bundle.Bundle
85-
if err := json.Unmarshal(data, &bndle); err != nil {
86-
return nil, errors.Wrapf(err, "failed to read bundle %q", ref)
87-
}
88-
return &bndle, nil
99+
return bndl, nil
89100
}
90101

91102
// Returns the list of all bundles present in the bundle store
92103
func (b *bundleStore) List() ([]reference.Reference, error) {
93104
var references []reference.Reference
94-
digests := filepath.Join(b.path, "_ids")
95-
if err := filepath.Walk(b.path, func(path string, info os.FileInfo, err error) error {
96-
if err != nil {
97-
return err
98-
}
99-
100-
if info.IsDir() {
101-
return nil
102-
}
103-
104-
if !strings.HasSuffix(info.Name(), ".json") {
105-
return nil
106-
}
107-
108-
if strings.HasPrefix(path, digests) {
109-
rel := path[len(digests)+1:]
110-
dg := strings.Split(filepath.ToSlash(rel), "/")[0]
111-
references = append(references, ID{digest.NewDigestFromEncoded(digest.SHA256, dg)})
112-
return nil
113-
}
114105

115-
ref, err := b.pathToReference(path)
116-
if err != nil {
117-
return err
106+
for _, refAliases := range b.referenceMap {
107+
for _, ref := range refAliases {
108+
references = append(references, ref)
118109
}
119-
120-
references = append(references, ref)
121-
122-
return nil
123-
}); err != nil {
124-
return nil, err
125110
}
126111

127112
sort.Slice(references, func(i, j int) bool {
@@ -143,6 +128,75 @@ func (b *bundleStore) Remove(ref reference.Reference) error {
143128
return os.RemoveAll(path)
144129
}
145130

131+
func (b *bundleStore) LookUp(refOrID string) (reference.Reference, error) {
132+
ref, err := FromString(refOrID)
133+
if err == nil {
134+
return ref, nil
135+
}
136+
if isShortID(refOrID) {
137+
ref, err := b.matchShortID(refOrID)
138+
if err == nil {
139+
return ref, nil
140+
}
141+
}
142+
return reference.ParseNormalizedNamed(refOrID)
143+
}
144+
145+
func (b *bundleStore) matchShortID(shortID string) (reference.Reference, error) {
146+
var found reference.Reference
147+
for id := range b.referenceMap {
148+
if strings.HasPrefix(id.String(), shortID) {
149+
if found != nil && found != id {
150+
return nil, fmt.Errorf("Ambiguous reference found")
151+
}
152+
found = id
153+
}
154+
}
155+
if found == nil {
156+
return nil, fmt.Errorf("Could not find reference")
157+
}
158+
fmt.Printf("found = %s\n", found)
159+
return found, nil
160+
}
161+
162+
func (b *bundleStore) referenceToID(ref reference.Reference) (ID, error) {
163+
if id, ok := ref.(ID); ok {
164+
return id, nil
165+
}
166+
for id, refs := range b.referenceMap {
167+
for _, r := range refs {
168+
if r == ref {
169+
return id, nil
170+
}
171+
}
172+
}
173+
return ID{}, fmt.Errorf("%s: reference not found", ref.String())
174+
}
175+
176+
func (b *bundleStore) storePaths(ref reference.Reference) ([]string, error) {
177+
var paths []string
178+
179+
id, err := b.referenceToID(ref)
180+
if err != nil {
181+
return nil, err
182+
}
183+
184+
if refs, exist := b.referenceMap[id]; exist {
185+
for _, rf := range refs {
186+
path, err := b.storePath(rf)
187+
if err != nil {
188+
continue
189+
}
190+
paths = append(paths, path)
191+
}
192+
}
193+
194+
if len(paths) == 0 {
195+
return nil, fmt.Errorf("%s: reference not found", ref.String())
196+
}
197+
return paths, nil
198+
}
199+
146200
func (b *bundleStore) storePath(ref reference.Reference) (string, error) {
147201
named, ok := ref.(reference.Named)
148202
if !ok {
@@ -175,6 +229,72 @@ func (b *bundleStore) storePath(ref reference.Reference) (string, error) {
175229
return storeDir, nil
176230
}
177231

232+
// Returns the list of all bundles present in the bundle store
233+
func (b *bundleStore) scanAllBundles() error {
234+
digests := filepath.Join(b.path, "_ids")
235+
if err := filepath.Walk(b.path, func(path string, info os.FileInfo, err error) error {
236+
if err != nil {
237+
return err
238+
}
239+
240+
if info.IsDir() {
241+
return nil
242+
}
243+
244+
if !strings.HasSuffix(info.Name(), ".json") {
245+
return nil
246+
}
247+
248+
if strings.HasPrefix(path, digests) {
249+
rel := path[len(digests)+1:]
250+
dg := strings.Split(filepath.ToSlash(rel), "/")[0]
251+
//references = append(references, ID{dg})
252+
id := ID{dg}
253+
if _, ok := b.referenceMap[id]; !ok {
254+
b.referenceMap[id] = []reference.Reference{id}
255+
} else {
256+
b.referenceMap[id] = append(b.referenceMap[id], id)
257+
}
258+
return nil
259+
}
260+
261+
ref, err := b.pathToReference(path)
262+
if err != nil {
263+
return err
264+
}
265+
bndl, err := b.fetchBundleJSON(path)
266+
if err != nil {
267+
return err
268+
}
269+
id, err := FromBundle(bndl)
270+
if err != nil {
271+
return err
272+
}
273+
if _, ok := b.referenceMap[id]; !ok {
274+
b.referenceMap[id] = []reference.Reference{ref}
275+
} else {
276+
b.referenceMap[id] = append(b.referenceMap[id], ref)
277+
}
278+
279+
return nil
280+
}); err != nil {
281+
return err
282+
}
283+
return nil
284+
}
285+
286+
func (b *bundleStore) fetchBundleJSON(bundlePath string) (*bundle.Bundle, error) {
287+
data, err := ioutil.ReadFile(bundlePath)
288+
if err != nil {
289+
return nil, errors.Wrapf(err, "failed to read file %s", bundlePath)
290+
}
291+
var bndle bundle.Bundle
292+
if err := json.Unmarshal(data, &bndle); err != nil {
293+
return nil, errors.Wrapf(err, "failed to read file %s", bundlePath)
294+
}
295+
return &bndle, nil
296+
}
297+
178298
func (b *bundleStore) pathToReference(path string) (reference.Named, error) {
179299
// Clean the path and remove the local bundle store path
180300
cleanpath := filepath.ToSlash(path)

internal/store/digest.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ import (
1111
"github.com/opencontainers/go-digest"
1212
)
1313

14+
var (
15+
identifierRegexp = regexp.MustCompile(`^([a-f0-9]{64})$`)
16+
17+
shortIdentifierRegexp = regexp.MustCompile(`^([a-f0-9]{1,64})$`)
18+
)
19+
20+
func isShortID(ref string) bool {
21+
return shortIdentifierRegexp.MatchString(ref)
22+
}
23+
1424
// ComputeDigest takes a bundle and produce a unigue reference.Digested
1525
func ComputeDigest(bundle io.WriterTo) (digest.Digest, error) {
1626
b := bytes.Buffer{}
@@ -29,7 +39,7 @@ func StringToRef(s string) (reference.Reference, error) {
2939
}
3040

3141
func FromString(s string) (ID, error) {
32-
if ok, _ := regexp.MatchString("[a-z0-9]{64}", s); !ok {
42+
if ok := identifierRegexp.MatchString(s); !ok {
3343
return ID{}, fmt.Errorf("could not parse '%s' as a valid reference", s)
3444
}
3545
digest := digest.NewDigestFromEncoded(digest.SHA256, s)

internal/store/installation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func NewInstallation(name string, reference string) (*Installation, error) {
3434
}, nil
3535
}
3636

37-
// SetParameters sets the parameter value if the installation bundle has
37+
// SetParameter sets the parameter value if the installation bundle has
3838
// a defined parameter with that name.
3939
func (i Installation) SetParameter(name string, value string) {
4040
if _, ok := i.Bundle.Parameters[name]; ok {

0 commit comments

Comments
 (0)