1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package content 18 19 import ( 20 "context" 21 "io" 22 "time" 23 24 "github.com/opencontainers/go-digest" 25 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 26 ) 27 28 // Store combines the methods of content-oriented interfaces into a set that 29 // are commonly provided by complete implementations. 30 // 31 // Overall content lifecycle: 32 // - Ingester is used to initiate a write operation (aka ingestion) 33 // - IngestManager is used to manage (e.g. list, abort) active ingestions 34 // - Once an ingestion is complete (see Writer.Commit), Provider is used to 35 // query a single piece of content by its digest 36 // - Manager is used to manage (e.g. list, delete) previously committed content 37 // 38 // Note that until ingestion is complete, its content is not visible through 39 // Provider or Manager. Once ingestion is complete, it is no longer exposed 40 // through IngestManager. 41 type Store interface { 42 Manager 43 Provider 44 IngestManager 45 Ingester 46 } 47 48 // ReaderAt extends the standard io.ReaderAt interface with reporting of Size and io.Closer 49 type ReaderAt interface { 50 io.ReaderAt 51 io.Closer 52 Size() int64 53 } 54 55 // Provider provides a reader interface for specific content 56 type Provider interface { 57 // ReaderAt only requires desc.Digest to be set. 58 // Other fields in the descriptor may be used internally for resolving 59 // the location of the actual data. 60 ReaderAt(ctx context.Context, desc ocispec.Descriptor) (ReaderAt, error) 61 } 62 63 // Ingester writes content 64 type Ingester interface { 65 // Writer initiates a writing operation (aka ingestion). A single ingestion 66 // is uniquely identified by its ref, provided using a WithRef option. 67 // Writer can be called multiple times with the same ref to access the same 68 // ingestion. 69 // Once all the data is written, use Writer.Commit to complete the ingestion. 70 Writer(ctx context.Context, opts ...WriterOpt) (Writer, error) 71 } 72 73 // IngestManager provides methods for managing ingestions. An ingestion is a 74 // not-yet-complete writing operation initiated using Ingester and identified 75 // by a ref string. 76 type IngestManager interface { 77 // Status returns the status of the provided ref. 78 Status(ctx context.Context, ref string) (Status, error) 79 80 // ListStatuses returns the status of any active ingestions whose ref match 81 // the provided regular expression. If empty, all active ingestions will be 82 // returned. 83 ListStatuses(ctx context.Context, filters ...string) ([]Status, error) 84 85 // Abort completely cancels the ingest operation targeted by ref. 86 Abort(ctx context.Context, ref string) error 87 } 88 89 // Info holds content specific information 90 type Info struct { 91 Digest digest.Digest 92 Size int64 93 CreatedAt time.Time 94 UpdatedAt time.Time 95 Labels map[string]string 96 } 97 98 // Status of a content operation (i.e. an ingestion) 99 type Status struct { 100 Ref string 101 Offset int64 102 Total int64 103 Expected digest.Digest 104 StartedAt time.Time 105 UpdatedAt time.Time 106 } 107 108 // WalkFunc defines the callback for a blob walk. 109 type WalkFunc func(Info) error 110 111 // InfoProvider provides info for content inspection. 112 type InfoProvider interface { 113 // Info will return metadata about content available in the content store. 114 // 115 // If the content is not present, ErrNotFound will be returned. 116 Info(ctx context.Context, dgst digest.Digest) (Info, error) 117 } 118 119 // Manager provides methods for inspecting, listing and removing content. 120 type Manager interface { 121 InfoProvider 122 123 // Update updates mutable information related to content. 124 // If one or more fieldpaths are provided, only those 125 // fields will be updated. 126 // Mutable fields: 127 // labels.* 128 Update(ctx context.Context, info Info, fieldpaths ...string) (Info, error) 129 130 // Walk will call fn for each item in the content store which 131 // match the provided filters. If no filters are given all 132 // items will be walked. 133 Walk(ctx context.Context, fn WalkFunc, filters ...string) error 134 135 // Delete removes the content from the store. 136 Delete(ctx context.Context, dgst digest.Digest) error 137 } 138 139 // Writer handles writing of content into a content store 140 type Writer interface { 141 // Close closes the writer, if the writer has not been 142 // committed this allows resuming or aborting. 143 // Calling Close on a closed writer will not error. 144 io.WriteCloser 145 146 // Digest may return empty digest or panics until committed. 147 Digest() digest.Digest 148 149 // Commit commits the blob (but no roll-back is guaranteed on an error). 150 // size and expected can be zero-value when unknown. 151 // Commit always closes the writer, even on error. 152 // ErrAlreadyExists aborts the writer. 153 Commit(ctx context.Context, size int64, expected digest.Digest, opts ...Opt) error 154 155 // Status returns the current state of write 156 Status() (Status, error) 157 158 // Truncate updates the size of the target blob 159 Truncate(size int64) error 160 } 161 162 // Opt is used to alter the mutable properties of content 163 type Opt func(*Info) error 164 165 // WithLabels allows labels to be set on content 166 func WithLabels(labels map[string]string) Opt { 167 return func(info *Info) error { 168 info.Labels = labels 169 return nil 170 } 171 } 172 173 // WriterOpts is internally used by WriterOpt. 174 type WriterOpts struct { 175 Ref string 176 Desc ocispec.Descriptor 177 } 178 179 // WriterOpt is used for passing options to Ingester.Writer. 180 type WriterOpt func(*WriterOpts) error 181 182 // WithDescriptor specifies an OCI descriptor. 183 // Writer may optionally use the descriptor internally for resolving 184 // the location of the actual data. 185 // Write does not require any field of desc to be set. 186 // If the data size is unknown, desc.Size should be set to 0. 187 // Some implementations may also accept negative values as "unknown". 188 func WithDescriptor(desc ocispec.Descriptor) WriterOpt { 189 return func(opts *WriterOpts) error { 190 opts.Desc = desc 191 return nil 192 } 193 } 194 195 // WithRef specifies a ref string. 196 func WithRef(ref string) WriterOpt { 197 return func(opts *WriterOpts) error { 198 opts.Ref = ref 199 return nil 200 } 201 } 202