-
Notifications
You must be signed in to change notification settings - Fork 666
add soci to nerdctl image convert [DO NOT MERGE] #4300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -960,6 +960,11 @@ Flags: | |
- `--oci` : convert Docker media types to OCI media types | ||
- `--platform=<PLATFORM>` : convert content for a specific platform | ||
- `--all-platforms` : convert content for all platforms (default: false) | ||
- `--soci`: generate SOCI v2 Indices to oci images. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: format |
||
*[**Note**: content is converted for all platforms by default when using this flag, use the `--platorm` flag to limit this behavior]* | ||
- `--soci-min-layer-size` : Span size in bytes that soci index uses to segment layer data. Default is 4 MiB. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: soci-span-size? |
||
- `--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. | ||
|
||
|
||
### :nerd_face: nerdctl image encrypt | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,3 +45,18 @@ For images that already have SOCI indices, see https://gallery.ecr.aws/soci-work | |
nerdctl push --snapshotter=soci --soci-span-size=2097152 --soci-min-layer-size=20971520 public.ecr.aws/my-registry/my-repo:latest | ||
``` | ||
--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. | ||
|
||
|
||
## Enable SOCI for `nerdctl image convert` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs documentation to distinguish soci option with push vs convert and some details about v1, v2 indexes |
||
|
||
| :zap: Requirement | nerdctl >= 2.2.0 | | ||
| ----------------- | ---------------- | | ||
|
||
| :zap: Requirement | soci-snapshotter >= 0.10.0 | | ||
| ----------------- | ---------------- | | ||
|
||
- 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. | ||
```console | ||
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 | ||
``` | ||
--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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,23 +18,26 @@ package snapshotterutil | |
|
||
import ( | ||
"bufio" | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/containerd/containerd/v2/client" | ||
"github.com/containerd/log" | ||
|
||
"github.com/containerd/nerdctl/v2/pkg/api/types" | ||
) | ||
|
||
// CreateSoci creates a SOCI index(`rawRef`) | ||
func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, platforms []string, sOpts types.SociOptions) error { | ||
// setupSociCommand creates and sets up a SOCI command with common configuration | ||
func setupSociCommand(gOpts types.GlobalCommandOptions) (*exec.Cmd, error) { | ||
sociExecutable, err := exec.LookPath("soci") | ||
if err != nil { | ||
log.L.WithError(err).Error("soci executable not found in path $PATH") | ||
log.L.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") | ||
return err | ||
return nil, err | ||
} | ||
|
||
sociCmd := exec.Command(sociExecutable) | ||
|
@@ -47,7 +50,65 @@ func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform boo | |
if gOpts.Namespace != "" { | ||
sociCmd.Args = append(sociCmd.Args, "--namespace", gOpts.Namespace) | ||
} | ||
// #endregion | ||
|
||
return sociCmd, nil | ||
} | ||
|
||
// ConvertSociIndexV2 converts an image to SOCI format and returns the converted image reference with digest | ||
func ConvertSociIndexV2(ctx context.Context, client *client.Client, srcRef string, destRef string, gOpts types.GlobalCommandOptions, platforms []string, sOpts types.SociOptions) (string, error) { | ||
sociCmd, err := setupSociCommand(gOpts) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will rely on the platform SOCI version to support the convert option as well. For compatibility, should we check the SOCI cli version first, before making the soci call. We should throw an appropriate error/warn message if the platform soci version does not support convert option. |
||
if err != nil { | ||
return "", err | ||
} | ||
|
||
// TODO: Implement conversion logic | ||
sociCmd.Args = append(sociCmd.Args, "convert") | ||
|
||
if len(platforms) > 0 { | ||
// multiple values need to be passed as separate, repeating flags in soci as it uses urfave | ||
// https://github.com/urfave/cli/blob/main/docs/v2/examples/flags.md#multiple-values-per-single-flag | ||
for _, p := range platforms { | ||
sociCmd.Args = append(sociCmd.Args, "--platform", p) | ||
} | ||
} | ||
|
||
if sOpts.SpanSize != -1 { | ||
sociCmd.Args = append(sociCmd.Args, "--span-size", strconv.FormatInt(sOpts.SpanSize, 10)) | ||
} | ||
|
||
if sOpts.MinLayerSize != -1 { | ||
sociCmd.Args = append(sociCmd.Args, "--min-layer-size", strconv.FormatInt(sOpts.MinLayerSize, 10)) | ||
} | ||
|
||
sociCmd.Args = append(sociCmd.Args, srcRef, destRef) | ||
|
||
log.L.Infof("Converting image from %s to %s using SOCI format", srcRef, destRef) | ||
|
||
err = processSociIO(sociCmd) | ||
if err != nil { | ||
return "", err | ||
} | ||
err = sociCmd.Wait() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
// Get the converted image's digest | ||
img, err := client.GetImage(ctx, destRef) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to get converted image: %w", err) | ||
} | ||
|
||
// Return the full reference with digest | ||
return fmt.Sprintf("%s@%s", destRef, img.Target().Digest), nil | ||
} | ||
|
||
// CreateSociIndexV1 creates a SOCI index(`rawRef`) | ||
func CreateSociIndexV1(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, platforms []string, sOpts types.SociOptions) error { | ||
sociCmd, err := setupSociCommand(gOpts) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Global flags have to be put before subcommand before soci upgrades to urfave v3. | ||
// https://github.com/urfave/cli/issues/1113 | ||
|
@@ -73,7 +134,7 @@ func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform boo | |
// --timeout, --debug, --content-store | ||
sociCmd.Args = append(sociCmd.Args, rawRef) | ||
|
||
log.L.Debugf("running %s %v", sociExecutable, sociCmd.Args) | ||
log.L.Debugf("running soci %v", sociCmd.Args) | ||
|
||
err = processSociIO(sociCmd) | ||
if err != nil { | ||
|
@@ -88,25 +149,11 @@ func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform boo | |
func PushSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, platforms []string) error { | ||
log.L.Debugf("pushing SOCI index: %s", rawRef) | ||
|
||
sociExecutable, err := exec.LookPath("soci") | ||
sociCmd, err := setupSociCommand(gOpts) | ||
if err != nil { | ||
log.L.WithError(err).Error("soci executable not found in path $PATH") | ||
log.L.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") | ||
return err | ||
} | ||
|
||
sociCmd := exec.Command(sociExecutable) | ||
sociCmd.Env = os.Environ() | ||
|
||
// #region for global flags. | ||
if gOpts.Address != "" { | ||
sociCmd.Args = append(sociCmd.Args, "--address", gOpts.Address) | ||
} | ||
if gOpts.Namespace != "" { | ||
sociCmd.Args = append(sociCmd.Args, "--namespace", gOpts.Namespace) | ||
} | ||
// #endregion | ||
|
||
// Global flags have to be put before subcommand before soci upgrades to urfave v3. | ||
// https://github.com/urfave/cli/issues/1113 | ||
sociCmd.Args = append(sociCmd.Args, "push") | ||
|
@@ -131,7 +178,7 @@ func PushSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, | |
} | ||
sociCmd.Args = append(sociCmd.Args, rawRef) | ||
|
||
log.L.Debugf("running %s %v", sociExecutable, sociCmd.Args) | ||
log.L.Debugf("running soci %v", sociCmd.Args) | ||
|
||
err = processSociIO(sociCmd) | ||
if err != nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we set the default explicitly instead of passing -1? If we simply want to use SOCI defined defaults, can we simply not pass these options if not set?