github.com/oras-project/oras-go@v0.3.0/pkg/oras/pull_opts.go (about) 1 /* 2 Copyright The ORAS Authors. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 package oras 17 18 import ( 19 "context" 20 "fmt" 21 "io" 22 "sync" 23 24 orascontent "github.com/oras-project/oras-go/pkg/content" 25 26 "github.com/containerd/containerd/images" 27 "github.com/opencontainers/go-digest" 28 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 29 "golang.org/x/sync/semaphore" 30 ) 31 32 type pullOpts struct { 33 allowedMediaTypes []string 34 dispatch func(context.Context, images.Handler, *semaphore.Weighted, ...ocispec.Descriptor) error 35 baseHandlers []images.Handler 36 callbackHandlers []images.Handler 37 contentProvideIngester orascontent.ProvideIngester 38 filterName func(ocispec.Descriptor) bool 39 cachedMediaTypes []string 40 } 41 42 // PullOpt allows callers to set options on the oras pull 43 type PullOpt func(o *pullOpts) error 44 45 func pullOptsDefaults() *pullOpts { 46 return &pullOpts{ 47 dispatch: images.Dispatch, 48 filterName: filterName, 49 cachedMediaTypes: []string{ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex}, 50 } 51 } 52 53 // WithCachedMediaTypes sets the media types normally cached in memory when pulling. 54 func WithCachedMediaTypes(cachedMediaTypes ...string) PullOpt { 55 return func(o *pullOpts) error { 56 o.cachedMediaTypes = cachedMediaTypes 57 return nil 58 } 59 } 60 61 // WithAdditionalCachedMediaTypes adds media types normally cached in memory when pulling. 62 // This does not replace the default media types, but appends to them 63 func WithAdditionalCachedMediaTypes(cachedMediaTypes ...string) PullOpt { 64 return func(o *pullOpts) error { 65 o.cachedMediaTypes = append(o.cachedMediaTypes, cachedMediaTypes...) 66 return nil 67 } 68 } 69 70 // WithAllowedMediaType sets the allowed media types 71 func WithAllowedMediaType(allowedMediaTypes ...string) PullOpt { 72 return func(o *pullOpts) error { 73 o.allowedMediaTypes = append(o.allowedMediaTypes, allowedMediaTypes...) 74 return nil 75 } 76 } 77 78 // WithAllowedMediaTypes sets the allowed media types 79 func WithAllowedMediaTypes(allowedMediaTypes []string) PullOpt { 80 return func(o *pullOpts) error { 81 o.allowedMediaTypes = append(o.allowedMediaTypes, allowedMediaTypes...) 82 return nil 83 } 84 } 85 86 // WithPullByBFS opt to pull in sequence with breath-first search 87 func WithPullByBFS(o *pullOpts) error { 88 o.dispatch = dispatchBFS 89 return nil 90 } 91 92 // WithPullBaseHandler provides base handlers, which will be called before 93 // any pull specific handlers. 94 func WithPullBaseHandler(handlers ...images.Handler) PullOpt { 95 return func(o *pullOpts) error { 96 o.baseHandlers = append(o.baseHandlers, handlers...) 97 return nil 98 } 99 } 100 101 // WithPullCallbackHandler provides callback handlers, which will be called after 102 // any pull specific handlers. 103 func WithPullCallbackHandler(handlers ...images.Handler) PullOpt { 104 return func(o *pullOpts) error { 105 o.callbackHandlers = append(o.callbackHandlers, handlers...) 106 return nil 107 } 108 } 109 110 // WithContentProvideIngester opt to the provided Provider and Ingester 111 // for file system I/O, including caches. 112 func WithContentProvideIngester(store orascontent.ProvideIngester) PullOpt { 113 return func(o *pullOpts) error { 114 o.contentProvideIngester = store 115 return nil 116 } 117 } 118 119 // WithPullEmptyNameAllowed allows pulling blobs with empty name. 120 func WithPullEmptyNameAllowed() PullOpt { 121 return func(o *pullOpts) error { 122 o.filterName = func(ocispec.Descriptor) bool { 123 return true 124 } 125 return nil 126 } 127 } 128 129 // WithPullStatusTrack report results to stdout 130 func WithPullStatusTrack(writer io.Writer) PullOpt { 131 return WithPullCallbackHandler(pullStatusTrack(writer)) 132 } 133 134 func pullStatusTrack(writer io.Writer) images.Handler { 135 var printLock sync.Mutex 136 return images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { 137 if name, ok := orascontent.ResolveName(desc); ok { 138 digestString := desc.Digest.String() 139 if err := desc.Digest.Validate(); err == nil { 140 if algo := desc.Digest.Algorithm(); algo == digest.SHA256 { 141 digestString = desc.Digest.Encoded()[:12] 142 } 143 } 144 printLock.Lock() 145 defer printLock.Unlock() 146 fmt.Fprintln(writer, "Downloaded", digestString, name) 147 } 148 return nil, nil 149 }) 150 }