1 package storage
2
3 import (
4 "context"
5 "regexp"
6
7 "github.com/distribution/reference"
8 "github.com/docker/distribution"
9 "github.com/docker/distribution/registry/storage/cache"
10 storagedriver "github.com/docker/distribution/registry/storage/driver"
11 "github.com/docker/libtrust"
12 )
13
14
15
16 type registry struct {
17 blobStore *blobStore
18 blobServer *blobServer
19 statter *blobStatter
20 blobDescriptorCacheProvider cache.BlobDescriptorCacheProvider
21 deleteEnabled bool
22 schema1Enabled bool
23 resumableDigestEnabled bool
24 schema1SigningKey libtrust.PrivateKey
25 blobDescriptorServiceFactory distribution.BlobDescriptorServiceFactory
26 manifestURLs manifestURLs
27 driver storagedriver.StorageDriver
28 }
29
30
31 type manifestURLs struct {
32 allow *regexp.Regexp
33 deny *regexp.Regexp
34 }
35
36
37 type RegistryOption func(*registry) error
38
39
40
41 func EnableRedirect(registry *registry) error {
42 registry.blobServer.redirect = true
43 return nil
44 }
45
46
47
48 func EnableDelete(registry *registry) error {
49 registry.deleteEnabled = true
50 return nil
51 }
52
53
54
55 func EnableSchema1(registry *registry) error {
56 registry.schema1Enabled = true
57 return nil
58 }
59
60
61
62 func DisableDigestResumption(registry *registry) error {
63 registry.resumableDigestEnabled = false
64 return nil
65 }
66
67
68 func ManifestURLsAllowRegexp(r *regexp.Regexp) RegistryOption {
69 return func(registry *registry) error {
70 registry.manifestURLs.allow = r
71 return nil
72 }
73 }
74
75
76 func ManifestURLsDenyRegexp(r *regexp.Regexp) RegistryOption {
77 return func(registry *registry) error {
78 registry.manifestURLs.deny = r
79 return nil
80 }
81 }
82
83
84
85 func Schema1SigningKey(key libtrust.PrivateKey) RegistryOption {
86 return func(registry *registry) error {
87 registry.schema1SigningKey = key
88 return nil
89 }
90 }
91
92
93
94 func BlobDescriptorServiceFactory(factory distribution.BlobDescriptorServiceFactory) RegistryOption {
95 return func(registry *registry) error {
96 registry.blobDescriptorServiceFactory = factory
97 return nil
98 }
99 }
100
101
102
103
104 func BlobDescriptorCacheProvider(blobDescriptorCacheProvider cache.BlobDescriptorCacheProvider) RegistryOption {
105
106
107
108
109
110 return func(registry *registry) error {
111 if blobDescriptorCacheProvider != nil {
112 statter := cache.NewCachedBlobStatter(blobDescriptorCacheProvider, registry.statter)
113 registry.blobStore.statter = statter
114 registry.blobServer.statter = statter
115 registry.blobDescriptorCacheProvider = blobDescriptorCacheProvider
116 }
117 return nil
118 }
119 }
120
121
122
123
124
125 func NewRegistry(ctx context.Context, driver storagedriver.StorageDriver, options ...RegistryOption) (distribution.Namespace, error) {
126
127 statter := &blobStatter{
128 driver: driver,
129 }
130
131 bs := &blobStore{
132 driver: driver,
133 statter: statter,
134 }
135
136 registry := ®istry{
137 blobStore: bs,
138 blobServer: &blobServer{
139 driver: driver,
140 statter: statter,
141 pathFn: bs.path,
142 },
143 statter: statter,
144 resumableDigestEnabled: true,
145 driver: driver,
146 }
147
148 for _, option := range options {
149 if err := option(registry); err != nil {
150 return nil, err
151 }
152 }
153
154 return registry, nil
155 }
156
157
158
159 func (reg *registry) Scope() distribution.Scope {
160 return distribution.GlobalScope
161 }
162
163
164
165
166 func (reg *registry) Repository(ctx context.Context, canonicalName reference.Named) (distribution.Repository, error) {
167 var descriptorCache distribution.BlobDescriptorService
168 if reg.blobDescriptorCacheProvider != nil {
169 var err error
170 descriptorCache, err = reg.blobDescriptorCacheProvider.RepositoryScoped(canonicalName.Name())
171 if err != nil {
172 return nil, err
173 }
174 }
175
176 return &repository{
177 ctx: ctx,
178 registry: reg,
179 name: canonicalName,
180 descriptorCache: descriptorCache,
181 }, nil
182 }
183
184 func (reg *registry) Blobs() distribution.BlobEnumerator {
185 return reg.blobStore
186 }
187
188 func (reg *registry) BlobStatter() distribution.BlobStatter {
189 return reg.statter
190 }
191
192
193 type repository struct {
194 *registry
195 ctx context.Context
196 name reference.Named
197 descriptorCache distribution.BlobDescriptorService
198 }
199
200
201 func (repo *repository) Named() reference.Named {
202 return repo.name
203 }
204
205 func (repo *repository) Tags(ctx context.Context) distribution.TagService {
206 tags := &tagStore{
207 repository: repo,
208 blobStore: repo.registry.blobStore,
209 }
210
211 return tags
212 }
213
214
215
216
217 func (repo *repository) Manifests(ctx context.Context, options ...distribution.ManifestServiceOption) (distribution.ManifestService, error) {
218 manifestLinkPathFns := []linkPathFunc{
219
220
221 manifestRevisionLinkPath,
222 blobLinkPath,
223 }
224
225 manifestDirectoryPathSpec := manifestRevisionsPathSpec{name: repo.name.Name()}
226
227 var statter distribution.BlobDescriptorService = &linkedBlobStatter{
228 blobStore: repo.blobStore,
229 repository: repo,
230 linkPathFns: manifestLinkPathFns,
231 }
232
233 if repo.registry.blobDescriptorServiceFactory != nil {
234 statter = repo.registry.blobDescriptorServiceFactory.BlobAccessController(statter)
235 }
236
237 blobStore := &linkedBlobStore{
238 ctx: ctx,
239 blobStore: repo.blobStore,
240 repository: repo,
241 deleteEnabled: repo.registry.deleteEnabled,
242 blobAccessController: statter,
243
244
245
246 linkPathFns: manifestLinkPathFns,
247 linkDirectoryPathSpec: manifestDirectoryPathSpec,
248 }
249
250 var v1Handler ManifestHandler
251 if repo.schema1Enabled {
252 v1Handler = &signedManifestHandler{
253 ctx: ctx,
254 schema1SigningKey: repo.schema1SigningKey,
255 repository: repo,
256 blobStore: blobStore,
257 }
258 } else {
259 v1Handler = &v1UnsupportedHandler{
260 innerHandler: &signedManifestHandler{
261 ctx: ctx,
262 schema1SigningKey: repo.schema1SigningKey,
263 repository: repo,
264 blobStore: blobStore,
265 },
266 }
267 }
268
269 ms := &manifestStore{
270 ctx: ctx,
271 repository: repo,
272 blobStore: blobStore,
273 schema1Handler: v1Handler,
274 schema2Handler: &schema2ManifestHandler{
275 ctx: ctx,
276 repository: repo,
277 blobStore: blobStore,
278 manifestURLs: repo.registry.manifestURLs,
279 },
280 manifestListHandler: &manifestListHandler{
281 ctx: ctx,
282 repository: repo,
283 blobStore: blobStore,
284 },
285 ocischemaHandler: &ocischemaManifestHandler{
286 ctx: ctx,
287 repository: repo,
288 blobStore: blobStore,
289 manifestURLs: repo.registry.manifestURLs,
290 },
291 }
292
293
294 for _, option := range options {
295 err := option.Apply(ms)
296 if err != nil {
297 return nil, err
298 }
299 }
300
301 return ms, nil
302 }
303
304
305
306
307 func (repo *repository) Blobs(ctx context.Context) distribution.BlobStore {
308 var statter distribution.BlobDescriptorService = &linkedBlobStatter{
309 blobStore: repo.blobStore,
310 repository: repo,
311 linkPathFns: []linkPathFunc{blobLinkPath},
312 }
313
314 if repo.descriptorCache != nil {
315 statter = cache.NewCachedBlobStatter(repo.descriptorCache, statter)
316 }
317
318 if repo.registry.blobDescriptorServiceFactory != nil {
319 statter = repo.registry.blobDescriptorServiceFactory.BlobAccessController(statter)
320 }
321
322 return &linkedBlobStore{
323 registry: repo.registry,
324 blobStore: repo.blobStore,
325 blobServer: repo.blobServer,
326 blobAccessController: statter,
327 repository: repo,
328 ctx: ctx,
329
330
331
332 linkPathFns: []linkPathFunc{blobLinkPath},
333 deleteEnabled: repo.registry.deleteEnabled,
334 resumableDigestEnabled: repo.resumableDigestEnabled,
335 }
336 }
337
View as plain text