...
1
2
3 package unpack
4
5 import (
6 "fmt"
7
8 v1 "github.com/google/go-containerregistry/pkg/v1"
9
10 "edge-infra.dev/pkg/f8n/warehouse/cluster"
11 "edge-infra.dev/pkg/f8n/warehouse/oci"
12 "edge-infra.dev/pkg/f8n/warehouse/oci/layer"
13 "edge-infra.dev/pkg/f8n/warehouse/oci/walk"
14 "edge-infra.dev/pkg/f8n/warehouse/pallet"
15 )
16
17
18
19 type Fn func(p pallet.Pallet, layers []layer.Layer) error
20
21
22
23
24 func Walk(a oci.Artifact, fn Fn, opts ...Option) error {
25 options, err := makeOptions(opts...)
26 if err != nil {
27 return err
28 }
29
30
31 switch a := a.(type) {
32
33
34 case oci.Unwrapper:
35 if img, ok := a.Unwrap().(v1.Image); ok {
36 return unpackImg(img, fn, options)
37 }
38
39 case v1.Image:
40 return unpackImg(a, fn, options)
41 }
42
43
44
45 if options.provider == "" {
46 return cluster.ErrNoProviders
47 }
48
49
50 p, err := pallet.New(a)
51 if err != nil {
52 return err
53 }
54 if err := p.Providers().IsValid(options.provider); err != nil {
55 return err
56 }
57
58
59 visited := map[string]v1.Hash{}
60 walker := &walk.Fns{
61 Image: func(img v1.Image, parent v1.ImageIndex) error {
62 var (
63 p pallet.Pallet
64 err error
65 )
66
67 isPkg, err := oci.IsPackage(img, parent)
68 if !isPkg || err != nil {
69 p, err = pallet.New(parent)
70 if err != nil {
71 return err
72 }
73 } else {
74 p, err = pallet.New(img)
75 if err != nil {
76 return err
77 }
78 }
79
80
81
82
83 if !p.Supports(options.provider) {
84 return nil
85 }
86
87
88
89 digest, err := p.Digest()
90 if err != nil {
91 return err
92 }
93
94 if visited[p.Name()] != (v1.Hash{}) {
95 if visited[p.Name()] != digest {
96 return fmt.Errorf("unpack.Walk: %w", oci.NewConflictErr(
97 p.Name(), visited[p.Name()], digest,
98 ))
99 }
100
101
102
103 return nil
104 }
105
106 layers, err := unpackPallet(p, *options)
107 if err != nil {
108 return err
109 }
110
111
112
113 visited[p.Name()] = digest
114
115 return fn(p, layers)
116 },
117 }
118
119 return walk.Walk(a, walker)
120 }
121
122
123 func unpackImg(img v1.Image, fn Fn, opts *options) error {
124 p, err := pallet.New(img)
125 if err != nil {
126 return err
127 }
128
129 layers, err := unpackPallet(p, *opts)
130 if err != nil {
131 return err
132 }
133
134 return fn(p, layers)
135 }
136
View as plain text