Skip to content

Commit 5d0cc07

Browse files
committed
add soci convert feature
Signed-off-by: Arjun Raja Yogidas <[email protected]>
1 parent 694c405 commit 5d0cc07

File tree

9 files changed

+56467
-26
lines changed

9 files changed

+56467
-26
lines changed

Q

Lines changed: 56247 additions & 0 deletions
Large diffs are not rendered by default.

cmd/nerdctl/image/image_convert.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ func convertCommand() *cobra.Command {
8989
cmd.Flags().String("overlaybd-dbstr", "", "Database config string for overlaybd")
9090
// #endregion
9191

92+
// #region soci flags
93+
cmd.Flags().Bool("soci", false, "Convert image to SOCI Index V2 format.")
94+
cmd.Flags().Int64("soci-min-layer-size", -1, "The minimum size of layers that will be converted to SOCI Index V2 format")
95+
cmd.Flags().Int64("soci-span-size", -1, "The size of SOCI spans")
96+
// #endregion
97+
9298
// #region generic flags
9399
cmd.Flags().Bool("uncompress", false, "Convert tar.gz layers to uncompressed tar layers")
94100
cmd.Flags().Bool("oci", false, "Convert Docker media types to OCI media types")
@@ -213,6 +219,21 @@ func convertOptions(cmd *cobra.Command) (types.ImageConvertOptions, error) {
213219
}
214220
// #endregion
215221

222+
// #region soci flags
223+
soci, err := cmd.Flags().GetBool("soci")
224+
if err != nil {
225+
return types.ImageConvertOptions{}, err
226+
}
227+
sociMinLayerSize, err := cmd.Flags().GetInt64("soci-min-layer-size")
228+
if err != nil {
229+
return types.ImageConvertOptions{}, err
230+
}
231+
sociSpanSize, err := cmd.Flags().GetInt64("soci-span-size")
232+
if err != nil {
233+
return types.ImageConvertOptions{}, err
234+
}
235+
// #endregion
236+
216237
// #region generic flags
217238
uncompress, err := cmd.Flags().GetBool("uncompress")
218239
if err != nil {
@@ -268,6 +289,13 @@ func convertOptions(cmd *cobra.Command) (types.ImageConvertOptions, error) {
268289
OverlayFsType: overlaybdFsType,
269290
OverlaydbDBStr: overlaybdDbstr,
270291
// #endregion
292+
// #region soci flags
293+
Soci: soci,
294+
SociOptions: types.SociOptions{
295+
SpanSize: sociSpanSize,
296+
MinLayerSize: sociMinLayerSize,
297+
},
298+
// #endregion
271299
// #region generic flags
272300
Uncompress: uncompress,
273301
Oci: oci,

cmd/nerdctl/image/image_convert_linux_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ func TestImageConvert(t *testing.T) {
8888
},
8989
Expected: test.Expects(0, nil, nil),
9090
},
91+
{
92+
Description: "soci",
93+
Require: require.All(
94+
require.Not(nerdtest.Docker),
95+
nerdtest.Soci,
96+
),
97+
Cleanup: func(data test.Data, helpers test.Helpers) {
98+
helpers.Anyhow("rmi", "-f", data.Identifier("converted-image"))
99+
},
100+
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
101+
return helpers.Command("image", "convert", "--soci",
102+
"--soci-span-size", "2097152",
103+
"--soci-min-layer-size", "20971520",
104+
testutil.CommonImage, data.Identifier("converted-image"))
105+
},
106+
Expected: test.Expects(0, nil, nil),
107+
},
91108
},
92109
}
93110

docs/command-reference.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,11 @@ Flags:
960960
- `--oci` : convert Docker media types to OCI media types
961961
- `--platform=<PLATFORM>` : convert content for a specific platform
962962
- `--all-platforms` : convert content for all platforms (default: false)
963+
- `--soci`: generate SOCI v2 Indices to oci images.
964+
*[**Note**: content is converted for all platforms by default when using this flag, use the `--platorm` flag to limit this behavior]*
965+
- `--soci-min-layer-size` : Span size in bytes that soci index uses to segment layer data. Default is 4 MiB.
966+
- `--soci-min-layer-size`: Minimum layer size in bytes to build zTOC for. Smaller layers won't have zTOC and not lazy pulled. Default is 10 MiB.
967+
963968

964969
### :nerd_face: nerdctl image encrypt
965970

docs/soci.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,18 @@ For images that already have SOCI indices, see https://gallery.ecr.aws/soci-work
4545
nerdctl push --snapshotter=soci --soci-span-size=2097152 --soci-min-layer-size=20971520 public.ecr.aws/my-registry/my-repo:latest
4646
```
4747
--soci-span-size and --soci-min-layer-size are two properties to customize the SOCI index. See [Command Reference](https://github.com/containerd/nerdctl/blob/377b2077bb616194a8ef1e19ccde32aa1ffd6c84/docs/command-reference.md?plain=1#L773) for further details.
48+
49+
50+
## Enable SOCI for `nerdctl image convert`
51+
52+
| :zap: Requirement | nerdctl >= 2.2.0 |
53+
| ----------------- | ---------------- |
54+
55+
| :zap: Requirement | soci-snapshotter >= 0.10.0 |
56+
| ----------------- | ---------------- |
57+
58+
- Convert an image to generate SOCI Index artifacts v2. Running the `nerdctl image convert` with the `--soci` flag and a `srcImg` and `dstImg`, `nerdctl` will create the SOCI v2 indices and the new image will be present in the `dstImg` address.
59+
```console
60+
nerdctl image convert --soci --soci-span-size=2097152 --soci-min-layer-size=20971520 public.ecr.aws/my-registry/my-repo:latest public.ecr.aws/my-registry/my-repo:soci
61+
```
62+
--soci-span-size and --soci-min-layer-size are two properties to customize the SOCI index. See [Command Reference](https://github.com/containerd/nerdctl/blob/377b2077bb616194a8ef1e19ccde32aa1ffd6c84/docs/command-reference.md?plain=1#L773) for further details.

pkg/api/types/image_types.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package types
1919
import (
2020
"io"
2121

22-
"github.com/opencontainers/image-spec/specs-go/v1"
22+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
2323
)
2424

2525
// ImageListOptions specifies options for `nerdctl image list`.
@@ -124,6 +124,12 @@ type ImageConvertOptions struct {
124124
OverlaydbDBStr string
125125
// #endregion
126126

127+
// #region soci flags
128+
// Soci convert image to SOCI format.eiifc
129+
Soci bool
130+
// SociOptions contains SOCI-specific options
131+
SociOptions SociOptions
132+
// #endregion
127133
}
128134

129135
// ImageCryptOptions specifies options for `nerdctl image encrypt` and `nerdctl image decrypt`.
@@ -200,7 +206,7 @@ type ImagePullOptions struct {
200206
// If nil, it will unpack automatically if only 1 platform is specified.
201207
Unpack *bool
202208
// Content for specific platforms. Empty if `--all-platforms` is true
203-
OCISpecPlatform []v1.Platform
209+
OCISpecPlatform []ocispec.Platform
204210
// Pull mode
205211
Mode string
206212
// Suppress verbose output

pkg/cmd/image/convert.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
converterutil "github.com/containerd/nerdctl/v2/pkg/imgutil/converter"
4848
"github.com/containerd/nerdctl/v2/pkg/platformutil"
4949
"github.com/containerd/nerdctl/v2/pkg/referenceutil"
50+
"github.com/containerd/nerdctl/v2/pkg/snapshotterutil"
5051
)
5152

5253
func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRawRef string, options types.ImageConvertOptions) error {
@@ -86,8 +87,9 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa
8687
zstdchunked := options.ZstdChunked
8788
overlaybd := options.Overlaybd
8889
nydus := options.Nydus
90+
soci := options.Soci
8991
var finalize func(ctx context.Context, cs content.Store, ref string, desc *ocispec.Descriptor) (*images.Image, error)
90-
if estargz || zstd || zstdchunked || overlaybd || nydus {
92+
if estargz || zstd || zstdchunked || overlaybd || nydus || soci {
9193
convertCount := 0
9294
if estargz {
9395
convertCount++
@@ -104,9 +106,12 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa
104106
if nydus {
105107
convertCount++
106108
}
109+
if soci {
110+
convertCount++
111+
}
107112

108113
if convertCount > 1 {
109-
return errors.New("options --estargz, --zstdchunked, --overlaybd and --nydus lead to conflict, only one of them can be used")
114+
return errors.New("options --estargz, --zstdchunked, --overlaybd, --nydus and --soci lead to conflict, only one of them can be used")
110115
}
111116

112117
var convertFunc converter.ConvertFunc
@@ -164,6 +169,16 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa
164169
)),
165170
)
166171
convertType = "nydus"
172+
case soci:
173+
// Convert image to SOCI format
174+
convertedRef, err := snapshotterutil.ConvertSociIndexV2(ctx, client, srcRef, targetRef, options.GOptions, options.Platforms, options.SociOptions)
175+
if err != nil {
176+
return fmt.Errorf("failed to convert image to SOCI format: %w", err)
177+
}
178+
res := converterutil.ConvertedImageInfo{
179+
Image: convertedRef,
180+
}
181+
return printConvertedImage(options.Stdout, options, res)
167182
}
168183

169184
if convertType != "overlaybd" {

pkg/cmd/image/push.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options
209209
return err
210210
}
211211
if options.GOptions.Snapshotter == "soci" {
212-
if err = snapshotterutil.CreateSoci(ref, options.GOptions, options.AllPlatforms, options.Platforms, options.SociOptions); err != nil {
212+
if err = snapshotterutil.CreateSociIndexV1(ref, options.GOptions, options.AllPlatforms, options.Platforms, options.SociOptions); err != nil {
213213
return err
214214
}
215215
if err = snapshotterutil.PushSoci(ref, options.GOptions, options.AllPlatforms, options.Platforms); err != nil {

0 commit comments

Comments
 (0)