@@ -142,26 +142,27 @@ type HostConfig struct {
142142 // Binds []string // List of volume bindings for this container
143143 ContainerIDFile string // File (path) where the containerId is written
144144 LogConfig loggerLogConfig // Configuration of the logs for this container
145- // NetworkMode NetworkMode // Network mode to use for the container
146- PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
147- // RestartPolicy RestartPolicy // Restart policy to be used for the container
148- // AutoRemove bool // Automatically remove container when it exits
145+ NetworkMode string // Network mode to use for the container
146+ PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
147+ RestartPolicy RestartPolicy // Restart policy to be used for the container
148+ AutoRemove bool // Automatically remove container when it exits
149149 // VolumeDriver string // Name of the volume driver used to mount volumes
150150 // VolumesFrom []string // List of volumes to take from other container
151- // CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
152- // CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
153-
154- CgroupnsMode string // Cgroup namespace mode to use for the container
155- DNS []string `json:"Dns"` // List of DNS server to lookup
156- DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
157- DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
158- ExtraHosts []string // List of extra hosts
159- GroupAdd []string // GroupAdd specifies additional groups to join
160- IpcMode string `json:"IpcMode"` // IPC namespace to use for the container
151+ CapAdd []string // List of kernel capabilities to add to the container
152+ CapDrop []string // List of kernel capabilities to remove from the container
153+
154+ CgroupnsMode string // Cgroup namespace mode to use for the container
155+ DNS []string `json:"Dns"` // List of DNS server to lookup
156+ DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
157+ DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
158+ ExtraHosts []string // List of extra hosts
159+ GroupAdd []string // GroupAdd specifies additional groups to join
160+ IpcMode string `json:"IpcMode"` // IPC namespace to use for the container
161+ Annotations map [string ]string `json:",omitempty"` // Arbitrary non-identifying metadata attached to container and provided to the runtime
161162 // Cgroup CgroupSpec // Cgroup to use for the container
162163 OomScoreAdj int // specifies the tune container’s OOM preferences (-1000 to 1000, rootless: 100 to 1000)
163164 PidMode string // PID namespace to use for the container
164- // Privileged bool // Is the container in privileged mode
165+ Privileged bool // Is the container in privileged mode
165166 // PublishAllPorts bool // Should docker publish all exposed port for the container
166167 ReadonlyRootfs bool // Is the container root filesystem in read-only
167168 // SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux.
@@ -180,6 +181,10 @@ type HostConfig struct {
180181 CPURealtimeRuntime int64 `json:"CpuRealtimeRuntime"` // Limits the CPU real-time runtime in microseconds
181182 Memory int64 // Memory limit (in bytes)
182183 MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
184+ MemoryReservation int64 // Memory soft limit (in bytes)
185+ MemorySwappiness * int64 // Tuning container memory swappiness (0 to 100); nil means not set
186+ PidsLimit int64 // Setting PIDs limit for a container; 0 or -1 for unlimited
187+ Ulimits []* units.Ulimit // List of ulimits to be set in the container
183188 OomKillDisable bool // specifies whether to disable OOM Killer
184189 Devices []DeviceMapping // List of devices to map inside the container
185190 BlkioSettings
@@ -268,6 +273,12 @@ type DeviceMapping struct {
268273 CgroupPermissions string
269274}
270275
276+ // RestartPolicy represents the restart policies of the container.
277+ type RestartPolicy struct {
278+ Name string
279+ MaximumRetryCount int
280+ }
281+
271282type CPUSettings struct {
272283 CPUSetCpus string
273284 CPUSetMems string
@@ -309,6 +320,26 @@ type NetworkEndpointSettings struct {
309320 // TODO DriverOpts map[string]string
310321}
311322
323+ // defaultCaps mirrors containerd's defaultUnixCaps() — the 14 capabilities
324+ // granted to non-privileged containers by default. Used as the baseline for
325+ // reconstructing CapAdd/CapDrop from the OCI spec's bounding set.
326+ var defaultCaps = map [string ]struct {}{
327+ "CAP_CHOWN" : {},
328+ "CAP_DAC_OVERRIDE" : {},
329+ "CAP_FSETID" : {},
330+ "CAP_FOWNER" : {},
331+ "CAP_MKNOD" : {},
332+ "CAP_NET_RAW" : {},
333+ "CAP_SETGID" : {},
334+ "CAP_SETUID" : {},
335+ "CAP_SETFCAP" : {},
336+ "CAP_SETPCAP" : {},
337+ "CAP_NET_BIND_SERVICE" : {},
338+ "CAP_SYS_CHROOT" : {},
339+ "CAP_KILL" : {},
340+ "CAP_AUDIT_WRITE" : {},
341+ }
342+
312343// ContainerFromNative instantiates a Docker-compatible Container from containerd-native Container.
313344func ContainerFromNative (n * native.Container ) (* Container , error ) {
314345 var hostname string
@@ -500,6 +531,11 @@ func ContainerFromNative(n *native.Container) (*Container, error) {
500531 c .HostConfig .OomKillDisable = memorySettings .DisableOOMKiller
501532 c .HostConfig .Memory = memorySettings .Limit
502533 c .HostConfig .MemorySwap = memorySettings .Swap
534+ c .HostConfig .MemoryReservation = memorySettings .Reservation
535+ if memorySettings .Swappiness != nil {
536+ swappiness := int64 (* memorySettings .Swappiness )
537+ c .HostConfig .MemorySwappiness = & swappiness
538+ }
503539
504540 dnsSettings , err := getDNSFromNative (n .Labels )
505541 if err != nil {
@@ -573,6 +609,63 @@ func ContainerFromNative(n *native.Container) (*Container, error) {
573609 c .Config .User = n .Labels [labels .User ]
574610 }
575611
612+ capAdd , capDrop , err := getCapabilitiesFromNative (n .Spec .(* specs.Spec ))
613+ if err != nil {
614+ return nil , fmt .Errorf ("failed to get capabilities: %w" , err )
615+ }
616+ c .HostConfig .CapAdd = capAdd
617+ c .HostConfig .CapDrop = capDrop
618+
619+ ulimits , err := getUlimitsFromNative (n .Spec .(* specs.Spec ))
620+ if err != nil {
621+ return nil , fmt .Errorf ("failed to get ulimits: %w" , err )
622+ }
623+ c .HostConfig .Ulimits = ulimits
624+
625+ if policyStr := n .Labels [restart .PolicyLabel ]; policyStr != "" {
626+ rp , err := restart .NewPolicy (policyStr )
627+ if err != nil {
628+ return nil , fmt .Errorf ("failed to parse restart policy: %w" , err )
629+ }
630+ c .HostConfig .RestartPolicy = RestartPolicy {
631+ Name : rp .Name (),
632+ MaximumRetryCount : rp .MaximumRetryCount (),
633+ }
634+ }
635+
636+ if len (containerAnnotations ) > 0 {
637+ userAnnotations := make (map [string ]string )
638+ for k , v := range containerAnnotations {
639+ if ! strings .HasPrefix (k , labels .Prefix ) {
640+ userAnnotations [k ] = v
641+ }
642+ }
643+ if len (userAnnotations ) > 0 {
644+ c .HostConfig .Annotations = userAnnotations
645+ }
646+ }
647+
648+ if sp , ok := n .Spec .(* specs.Spec ); ok {
649+ if sp .Linux != nil && sp .Linux .Resources != nil &&
650+ sp .Linux .Resources .Pids != nil && sp .Linux .Resources .Pids .Limit != nil {
651+ c .HostConfig .PidsLimit = * sp .Linux .Resources .Pids .Limit
652+ }
653+ }
654+
655+ if networksJSON := n .Labels [labels .Networks ]; networksJSON != "" {
656+ var networks []string
657+ if err := json .Unmarshal ([]byte (networksJSON ), & networks ); err != nil {
658+ return nil , fmt .Errorf ("failed to parse networks label: %v" , err )
659+ }
660+ if len (networks ) > 0 {
661+ c .HostConfig .NetworkMode = networks [0 ]
662+ }
663+ }
664+
665+ c .HostConfig .Privileged = n .Labels [labels .Privileged ] == "true"
666+
667+ c .HostConfig .AutoRemove = n .Labels [labels .ContainerAutoRemove ] == "true"
668+
576669 // Add health check config if present in labels
577670 if hConfig , ok := n .Labels [labels .HealthCheck ]; ok && hConfig != "" {
578671 healthCheckConfig , err := healthcheck .HealthCheckFromJSON (hConfig )
@@ -850,6 +943,15 @@ func getMemorySettingsFromNative(sp *specs.Spec) (*MemorySetting, error) {
850943 if sp .Linux .Resources .Memory .Swap != nil {
851944 res .Swap = * sp .Linux .Resources .Memory .Swap
852945 }
946+
947+ if sp .Linux .Resources .Memory .Reservation != nil {
948+ res .Reservation = * sp .Linux .Resources .Memory .Reservation
949+ }
950+
951+ if sp .Linux .Resources .Memory .Swappiness != nil {
952+ v := * sp .Linux .Resources .Memory .Swappiness
953+ res .Swappiness = & v
954+ }
853955 }
854956 return res , nil
855957}
@@ -904,6 +1006,41 @@ func getSysctlFromNative(sp *specs.Spec) (map[string]string, error) {
9041006 return res , nil
9051007}
9061008
1009+ func getCapabilitiesFromNative (sp * specs.Spec ) (capAdd , capDrop []string , err error ) {
1010+ if sp .Process == nil || sp .Process .Capabilities == nil {
1011+ return nil , nil , nil
1012+ }
1013+ boundingSet := make (map [string ]struct {}, len (sp .Process .Capabilities .Bounding ))
1014+ for _ , cap := range sp .Process .Capabilities .Bounding {
1015+ boundingSet [cap ] = struct {}{}
1016+ if _ , isDefault := defaultCaps [cap ]; ! isDefault {
1017+ capAdd = append (capAdd , cap )
1018+ }
1019+ }
1020+ for cap := range defaultCaps {
1021+ if _ , present := boundingSet [cap ]; ! present {
1022+ capDrop = append (capDrop , cap )
1023+ }
1024+ }
1025+ return capAdd , capDrop , nil
1026+ }
1027+
1028+ func getUlimitsFromNative (sp * specs.Spec ) ([]* units.Ulimit , error ) {
1029+ if sp .Process == nil || len (sp .Process .Rlimits ) == 0 {
1030+ return nil , nil
1031+ }
1032+ var ulimits []* units.Ulimit
1033+ for _ , rl := range sp .Process .Rlimits {
1034+ name := strings .ToLower (strings .TrimPrefix (rl .Type , "RLIMIT_" ))
1035+ ulimits = append (ulimits , & units.Ulimit {
1036+ Name : name ,
1037+ Hard : int64 (rl .Hard ),
1038+ Soft : int64 (rl .Soft ),
1039+ })
1040+ }
1041+ return ulimits , nil
1042+ }
1043+
9071044type IPAMConfig struct {
9081045 Subnet string `json:"Subnet,omitempty"`
9091046 Gateway string `json:"Gateway,omitempty"`
@@ -944,9 +1081,11 @@ type structuredCNI struct {
9441081}
9451082
9461083type MemorySetting struct {
947- Limit int64 `json:"limit"`
948- Swap int64 `json:"swap"`
949- DisableOOMKiller bool `json:"disableOOMKiller"`
1084+ Limit int64 `json:"limit"`
1085+ Swap int64 `json:"swap"`
1086+ Reservation int64 `json:"reservation"`
1087+ Swappiness * uint64 `json:"swappiness"`
1088+ DisableOOMKiller bool `json:"disableOOMKiller"`
9501089}
9511090
9521091// parseNetworkSubnets extracts and parses subnet configurations from IPAM config
0 commit comments