| package containerd | |
| import ( | |
| "slices" | |
| dockerspec "github.com/moby/docker-image-spec/specs-go/v1" | |
| "github.com/moby/moby/api/types/container" | |
| "github.com/moby/moby/api/types/network" | |
| "github.com/moby/moby/v2/daemon/internal/image" | |
| ocispec "github.com/opencontainers/image-spec/specs-go/v1" | |
| ) | |
| // dockerOciImageToDockerImagePartial creates an image.Image from the imagespec.DockerOCIImage | |
| // It doesn't set: | |
| // - V1Image.ContainerConfig | |
| // - V1Image.Container | |
| // - Details | |
| func dockerOciImageToDockerImagePartial(id image.ID, img dockerspec.DockerOCIImage) *image.Image { | |
| v1Image := image.V1Image{ | |
| Config: dockerOCIImageConfigToContainerConfig(img.Config), | |
| Architecture: img.Platform.Architecture, | |
| Variant: img.Platform.Variant, | |
| OS: img.Platform.OS, | |
| Author: img.Author, | |
| Created: img.Created, | |
| } | |
| out := image.NewImage(id) | |
| out.V1Image = v1Image | |
| out.RootFS = &image.RootFS{ | |
| Type: img.RootFS.Type, | |
| DiffIDs: slices.Clone(img.RootFS.DiffIDs), | |
| } | |
| out.History = img.History | |
| out.OSFeatures = img.OSFeatures | |
| out.OSVersion = img.OSVersion | |
| return out | |
| } | |
| func dockerImageToDockerOCIImage(img image.Image) dockerspec.DockerOCIImage { | |
| return dockerspec.DockerOCIImage{ | |
| Image: ocispec.Image{ | |
| Created: img.Created, | |
| Author: img.Author, | |
| Platform: ocispec.Platform{ | |
| Architecture: img.Architecture, | |
| Variant: img.Variant, | |
| OS: img.OS, | |
| OSVersion: img.OSVersion, | |
| OSFeatures: img.OSFeatures, | |
| }, | |
| RootFS: ocispec.RootFS{ | |
| Type: img.RootFS.Type, | |
| DiffIDs: slices.Clone(img.RootFS.DiffIDs), | |
| }, | |
| History: img.History, | |
| }, | |
| Config: containerConfigToDockerOCIImageConfig(img.Config), | |
| } | |
| } | |
| func containerConfigToDockerOCIImageConfig(cfg *container.Config) dockerspec.DockerOCIImageConfig { | |
| var ociCfg ocispec.ImageConfig | |
| var ext dockerspec.DockerOCIImageConfigExt | |
| if cfg != nil { | |
| ociCfg = ocispec.ImageConfig{ | |
| User: cfg.User, | |
| Env: cfg.Env, | |
| Entrypoint: cfg.Entrypoint, | |
| Cmd: cfg.Cmd, | |
| Volumes: cfg.Volumes, | |
| WorkingDir: cfg.WorkingDir, | |
| Labels: cfg.Labels, | |
| StopSignal: cfg.StopSignal, | |
| ArgsEscaped: cfg.ArgsEscaped, //nolint:staticcheck // Ignore SA1019. Need to keep it in image. | |
| } | |
| if len(cfg.ExposedPorts) > 0 { | |
| ociCfg.ExposedPorts = map[string]struct{}{} | |
| for k := range cfg.ExposedPorts { | |
| ociCfg.ExposedPorts[k.String()] = struct{}{} | |
| } | |
| } | |
| ext.Healthcheck = cfg.Healthcheck | |
| ext.OnBuild = cfg.OnBuild | |
| ext.Shell = cfg.Shell | |
| } | |
| return dockerspec.DockerOCIImageConfig{ | |
| ImageConfig: ociCfg, | |
| DockerOCIImageConfigExt: ext, | |
| } | |
| } | |
| func dockerOCIImageConfigToContainerConfig(cfg dockerspec.DockerOCIImageConfig) *container.Config { | |
| exposedPorts := make(network.PortSet, len(cfg.ExposedPorts)) | |
| for k := range cfg.ExposedPorts { | |
| if p, err := network.ParsePort(k); err == nil { | |
| exposedPorts[p] = struct{}{} | |
| } | |
| } | |
| return &container.Config{ | |
| Entrypoint: cfg.Entrypoint, | |
| Env: cfg.Env, | |
| Cmd: cfg.Cmd, | |
| User: cfg.User, | |
| WorkingDir: cfg.WorkingDir, | |
| ExposedPorts: exposedPorts, | |
| Volumes: cfg.Volumes, | |
| Labels: cfg.Labels, | |
| ArgsEscaped: cfg.ArgsEscaped, //nolint:staticcheck // Ignore SA1019. Need to keep it in image. | |
| StopSignal: cfg.StopSignal, | |
| Healthcheck: cfg.Healthcheck, | |
| OnBuild: cfg.OnBuild, | |
| Shell: cfg.Shell, | |
| } | |
| } |