@@ -4,33 +4,31 @@ import (
4
4
"context"
5
5
"errors"
6
6
"fmt"
7
- "github.com/containerd/containerd/v2/core/content"
8
- "github.com/containerd/containerd/v2/core/images"
9
- "github.com/containerd/containerd/v2/core/leases"
10
- "github.com/containerd/errdefs"
11
7
"github.com/distribution/distribution/v3"
12
8
"github.com/distribution/distribution/v3/manifest/manifestlist"
13
9
"github.com/distribution/distribution/v3/manifest/ocischema"
14
10
"github.com/distribution/distribution/v3/manifest/schema2"
15
11
"github.com/distribution/reference"
16
12
"github.com/opencontainers/go-digest"
17
- ocispec "github.com/opencontainers/image-spec/specs-go/v1"
18
13
"github.com/sirupsen/logrus"
19
14
)
20
15
21
- // manifestService implements distribution.ManifestService backed by containerd.
16
+ // manifestService implements distribution.ManifestService backed by containerd content store .
22
17
type manifestService struct {
23
- client * Client
24
18
repo reference.Named
25
- blobStore distribution. BlobStore
19
+ blobStore * blobStore
26
20
}
27
21
28
- // Exists checks if a manifest exists in containerd content store by digest.
22
+ // Exists checks if a manifest exists in the blob store by digest.
29
23
func (m * manifestService ) Exists (ctx context.Context , dgst digest.Digest ) (bool , error ) {
30
- return content .Exists (ctx , m .client .ContentStore (), ocispec.Descriptor {Digest : dgst })
24
+ _ , err := m .blobStore .Stat (ctx , dgst )
25
+ if errors .Is (err , distribution .ErrBlobUnknown ) {
26
+ return false , nil
27
+ }
28
+ return err == nil , err
31
29
}
32
30
33
- // Get retrieves a manifest by digest.
31
+ // Get retrieves a manifest from the blob store by its digest.
34
32
func (m * manifestService ) Get (
35
33
ctx context.Context , dgst digest.Digest , _ ... distribution.ManifestServiceOption ,
36
34
) (distribution.Manifest , error ) {
@@ -57,114 +55,34 @@ func (m *manifestService) Get(
57
55
"digest" : dgst ,
58
56
"mediatype" : mediaType ,
59
57
},
60
- ).Debug ("Got manifest from containerd content store." )
58
+ ).Debug ("Got manifest from blob store." )
61
59
}
62
60
63
61
return manifest , nil
64
62
}
65
63
66
- // Put stores a manifest.
64
+ // Put stores a manifest in the blob store and returns its digest .
67
65
func (m * manifestService ) Put (
68
- ctx context.Context , manifest distribution.Manifest , options ... distribution.ManifestServiceOption ,
66
+ ctx context.Context , manifest distribution.Manifest , _ ... distribution.ManifestServiceOption ,
69
67
) (digest.Digest , error ) {
70
- ctx = m .client .Context (ctx )
71
-
72
- // Marshal the manifest
73
68
mediaType , payload , err := manifest .Payload ()
74
69
if err != nil {
75
- return "" , fmt .Errorf ("failed to get manifest payload: %w" , err )
70
+ return "" , fmt .Errorf ("get manifest payload: %w" , err )
76
71
}
77
72
78
- // Calculate digest
79
- dgst := digest .FromBytes (payload )
80
-
81
- // Create a lease to prevent garbage collection during the operation
82
- lease , err := m .client .LeasesService ().Create (ctx , leases .WithRandomID ())
73
+ desc , err := m .blobStore .Put (ctx , mediaType , payload )
83
74
if err != nil {
84
- return "" , fmt .Errorf ("failed to create lease: %w" , err )
85
- }
86
- defer m .client .LeasesService ().Delete (ctx , lease )
87
-
88
- // Write the manifest to the content store
89
- ref := fmt .Sprintf ("%s@%s" , m .repo .String (), dgst )
90
- writer , err := m .client .ContentStore ().Writer (
91
- ctx ,
92
- content .WithRef (ref ),
93
- content .WithDescriptor (
94
- ocispec.Descriptor {
95
- MediaType : mediaType ,
96
- Digest : dgst ,
97
- Size : int64 (len (payload )),
98
- },
99
- ),
100
- )
101
- if err != nil {
102
- return "" , fmt .Errorf ("failed to create content writer: %w" , err )
75
+ return "" , fmt .Errorf ("put manifest in blob store: %w" , err )
103
76
}
104
77
105
- if _ , err := writer .Write (payload ); err != nil {
106
- writer .Close ()
107
- return "" , fmt .Errorf ("failed to write manifest: %w" , err )
108
- }
109
-
110
- if err := writer .Commit (ctx , 0 , dgst ); err != nil {
111
- if ! errdefs .IsAlreadyExists (err ) {
112
- return "" , fmt .Errorf ("failed to commit manifest: %w" , err )
113
- }
114
- }
115
-
116
- // If this is a tag operation (from docker push), update the image store
117
- for _ , option := range options {
118
- if opt , ok := option .(distribution.WithTagOption ); ok {
119
- tag := opt .Tag
120
- if err := m .updateImageStore (ctx , m .repo , tag , dgst , mediaType ); err != nil {
121
- return "" , fmt .Errorf ("failed to update image store: %w" , err )
122
- }
123
- }
124
- }
125
-
126
- return dgst , nil
78
+ return desc .Digest , nil
127
79
}
128
80
129
- // Delete removes a manifest by digest.
130
- func (m * manifestService ) Delete (ctx context.Context , dgst digest.Digest ) error {
131
- ctx = m .client .Context (ctx )
132
-
133
- // For now, we don't support deletion to keep things simple
134
- // Containerd's garbage collection should handle cleanup
81
+ // Delete is not supported to keep things simple.
82
+ func (m * manifestService ) Delete (_ context.Context , _ digest.Digest ) error {
135
83
return distribution .ErrUnsupported
136
84
}
137
85
138
- // updateImageStore updates the containerd image store with the manifest.
139
- func (m * manifestService ) updateImageStore (
140
- ctx context.Context , repo reference.Named , tag string , dgst digest.Digest , mediaType string ,
141
- ) error {
142
- // Create the image reference
143
- ref := fmt .Sprintf ("%s:%s" , repo .String (), tag )
144
-
145
- // Create the image
146
- img := images.Image {
147
- Name : ref ,
148
- Target : ocispec.Descriptor {
149
- MediaType : mediaType ,
150
- Digest : dgst ,
151
- Size : 0 , // Will be filled by containerd
152
- },
153
- }
154
-
155
- // Update or create the image
156
- _ , err := m .client .ImageStore ().Update (ctx , img )
157
- if err != nil {
158
- // If update fails, try to create
159
- _ , err = m .client .ImageStore ().Create (ctx , img )
160
- if err != nil && ! errdefs .IsAlreadyExists (err ) {
161
- return err
162
- }
163
- }
164
-
165
- return nil
166
- }
167
-
168
86
// unmarshalManifest attempts to unmarshal a manifest in various formats.
169
87
func unmarshalManifest (blob []byte ) (distribution.Manifest , error ) {
170
88
// Try OCI manifest.
@@ -185,5 +103,7 @@ func unmarshalManifest(blob []byte) (distribution.Manifest, error) {
185
103
return & manifestList , nil
186
104
}
187
105
106
+ // TODO: handle oci index? Use distribution.UnmarshalManifest + basic unmarshal to get the media type from blob?
107
+
188
108
return nil , fmt .Errorf ("unknown manifest format" )
189
109
}
0 commit comments