Skip to content

Commit c4fc1c9

Browse files
authored
feat: Add ShmSize, Sysctl and Runtime option (runfinch#235)
* feat: Add ShmSize, Sysctl and Runtime option Signed-off-by: Arjun Raja Yogidas <[email protected]>
1 parent abfa7f7 commit c4fc1c9

File tree

4 files changed

+149
-4
lines changed

4 files changed

+149
-4
lines changed

api/handlers/container/create.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,20 @@ func (h *handler) create(w http.ResponseWriter, r *http.Request) {
179179
if req.HostConfig.GroupAdd != nil {
180180
groupAdd = req.HostConfig.GroupAdd
181181
}
182+
sysctl := []string{}
183+
if req.HostConfig.Sysctls != nil {
184+
sysctl = translateSysctls(req.HostConfig.Sysctls)
185+
}
186+
187+
shmSize := ""
188+
if req.HostConfig.ShmSize > 0 {
189+
shmSize = fmt.Sprint(req.HostConfig.ShmSize)
190+
}
191+
192+
runtime := defaults.Runtime
193+
if req.HostConfig.Runtime != "" {
194+
runtime = req.HostConfig.Runtime
195+
}
182196

183197
globalOpt := ncTypes.GlobalCommandOptions(*h.Config)
184198
createOpt := ncTypes.ContainerCreateOptions{
@@ -228,6 +242,7 @@ func (h *handler) create(w http.ResponseWriter, r *http.Request) {
228242
BlkioDeviceReadIOps: throttleDevicesToStrings(req.HostConfig.BlkioDeviceReadIOps),
229243
BlkioDeviceWriteIOps: throttleDevicesToStrings(req.HostConfig.BlkioDeviceWriteIOps),
230244
IPC: req.HostConfig.IpcMode, // IPC namespace to use
245+
ShmSize: shmSize,
231246
// #endregion
232247

233248
// #region for user flags
@@ -242,7 +257,8 @@ func (h *handler) create(w http.ResponseWriter, r *http.Request) {
242257
Privileged: req.HostConfig.Privileged,
243258
// #endregion
244259
// #region for runtime flags
245-
Runtime: defaults.Runtime, // nerdctl default.
260+
Runtime: runtime, // Runtime to use for this container, e.g. "crun", or "io.containerd.runc.v2".
261+
Sysctl: sysctl,
246262
// #endregion
247263

248264
// #region for volume flags
@@ -392,3 +408,16 @@ func throttleDevicesToStrings(devices []*blkiodev.ThrottleDevice) []string {
392408
}
393409
return strings
394410
}
411+
412+
// translateSysctls converts a map of sysctls to a slice of strings in the format "KEY=VALUE".
413+
func translateSysctls(sysctls map[string]string) []string {
414+
if sysctls == nil {
415+
return nil
416+
}
417+
418+
var result []string
419+
for key, val := range sysctls {
420+
result = append(result, fmt.Sprintf("%s=%s", key, val))
421+
}
422+
return result
423+
}

api/handlers/container/create_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,31 @@ var _ = Describe("Container Create API ", func() {
880880
Expect(rr.Body).Should(MatchJSON(jsonResponse))
881881
})
882882

883+
It("should set ShmSize, Sysctl and Runtime option", func() {
884+
body := []byte(`{
885+
"Image": "test-image",
886+
"HostConfig": {
887+
"Sysctls": { "net.ipv4.ip_forward": "1" },
888+
"ShmSize": 302348,
889+
"Runtime": "crun"
890+
}
891+
}`)
892+
req, _ := http.NewRequest(http.MethodPost, "/containers/create", bytes.NewReader(body))
893+
894+
// expected create options
895+
createOpt.ShmSize = "302348"
896+
createOpt.Sysctl = []string{"net.ipv4.ip_forward=1"}
897+
createOpt.Runtime = "crun"
898+
899+
service.EXPECT().Create(gomock.Any(), "test-image", nil, equalTo(createOpt), equalTo(netOpt)).Return(
900+
cid, nil)
901+
902+
// handler should return success message with 201 status code.
903+
h.create(rr, req)
904+
Expect(rr).Should(HaveHTTPStatus(http.StatusCreated))
905+
Expect(rr.Body).Should(MatchJSON(jsonResponse))
906+
})
907+
883908
Context("translate port mappings", func() {
884909
It("should return empty if port mappings is nil", func() {
885910
Expect(translatePortMappings(nil)).Should(BeEmpty())
@@ -1060,6 +1085,7 @@ func getDefaultCreateOpt(conf config.Config) types.ContainerCreateOptions {
10601085

10611086
// #region for runtime flags
10621087
Runtime: defaults.Runtime, // nerdctl default.
1088+
Sysctl: []string{},
10631089
// #endregion
10641090

10651091
// #region for volume flags

api/types/container_types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ type ContainerHostConfig struct {
9292
// TODO: SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. (["key=value"])
9393
Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
9494
UTSMode string // UTS namespace to use for the container
95-
// TODO: ShmSize int64 // Size of /dev/shm in bytes. The size must be greater than 0.
96-
// TODO: Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container
97-
// TODO: Runtime string `json:",omitempty"` // Runtime to use with this container
95+
ShmSize int64 // Size of /dev/shm in bytes. The size must be greater than 0.
96+
Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container
97+
Runtime string `json:",omitempty"` // Runtime to use with this container
9898
// TODO: PublishAllPorts bool // Should docker publish all exposed port for the container
9999
// TODO: StorageOpt map[string]string `json:",omitempty"` // Storage driver options per container.
100100
// TODO: UsernsMode UsernsMode // The user namespace to use for the container

e2e/tests/container_create.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,96 @@ func ContainerCreate(opt *option.Option) {
12651265
}
12661266
Expect(foundAllowAllDevices).Should(BeTrue())
12671267
})
1268+
1269+
It("should create a container with specified ShmSize", func() {
1270+
// Define options
1271+
options.Cmd = []string{"sleep", "Infinity"}
1272+
options.HostConfig.ShmSize = 134217728 // 128MB
1273+
1274+
// Create container
1275+
statusCode, ctr := createContainer(uClient, url, testContainerName, options)
1276+
Expect(statusCode).Should(Equal(http.StatusCreated))
1277+
Expect(ctr.ID).ShouldNot(BeEmpty())
1278+
1279+
// Start container
1280+
command.Run(opt, "start", testContainerName)
1281+
1282+
// Inspect container using Docker-compatible format
1283+
resp := command.Stdout(opt, "inspect", testContainerName)
1284+
var inspect []*dockercompat.Container
1285+
err := json.Unmarshal(resp, &inspect)
1286+
Expect(err).Should(BeNil())
1287+
Expect(inspect).Should(HaveLen(1))
1288+
1289+
// Verify ShmSize in HostConfig
1290+
Expect(inspect[0].HostConfig.ShmSize).Should(Equal(options.HostConfig.ShmSize))
1291+
})
1292+
1293+
It("should create a container with specified Sysctls", func() {
1294+
// Define options
1295+
options.Cmd = []string{"sleep", "Infinity"}
1296+
options.HostConfig.Sysctls = map[string]string{
1297+
"net.ipv4.ip_forward": "1",
1298+
"kernel.msgmax": "65536",
1299+
}
1300+
1301+
// Create container
1302+
statusCode, ctr := createContainer(uClient, url, testContainerName, options)
1303+
Expect(statusCode).Should(Equal(http.StatusCreated))
1304+
Expect(ctr.ID).ShouldNot(BeEmpty())
1305+
1306+
// Start container
1307+
command.Run(opt, "start", testContainerName)
1308+
1309+
// Verify sysctls using native inspect
1310+
nativeResp := command.Stdout(opt, "inspect", "--mode=native", testContainerName)
1311+
var nativeInspect []map[string]interface{}
1312+
err := json.Unmarshal(nativeResp, &nativeInspect)
1313+
Expect(err).Should(BeNil())
1314+
Expect(nativeInspect).Should(HaveLen(1))
1315+
1316+
// Navigate to the sysctls section
1317+
spec, ok := nativeInspect[0]["Spec"].(map[string]interface{})
1318+
Expect(ok).Should(BeTrue())
1319+
linux, ok := spec["linux"].(map[string]interface{})
1320+
Expect(ok).Should(BeTrue())
1321+
sysctls, ok := linux["sysctl"].(map[string]interface{})
1322+
Expect(ok).Should(BeTrue())
1323+
1324+
// Verify sysctl values
1325+
Expect(sysctls["net.ipv4.ip_forward"]).Should(Equal("1"))
1326+
Expect(sysctls["kernel.msgmax"]).Should(Equal("65536"))
1327+
})
1328+
1329+
It("should create a container with specified Runtime", func() {
1330+
// Define options
1331+
options.Cmd = []string{"sleep", "Infinity"}
1332+
options.HostConfig.Runtime = "io.containerd.runc.v2"
1333+
1334+
// Create container
1335+
statusCode, ctr := createContainer(uClient, url, testContainerName, options)
1336+
Expect(statusCode).Should(Equal(http.StatusCreated))
1337+
Expect(ctr.ID).ShouldNot(BeEmpty())
1338+
1339+
// Start container
1340+
command.Run(opt, "start", testContainerName)
1341+
1342+
// Verify runtime using native inspect
1343+
nativeResp := command.Stdout(opt, "inspect", "--mode=native", testContainerName)
1344+
var nativeInspect []map[string]interface{}
1345+
err := json.Unmarshal(nativeResp, &nativeInspect)
1346+
Expect(err).Should(BeNil())
1347+
Expect(nativeInspect).Should(HaveLen(1))
1348+
1349+
// Navigate to the Runtime section
1350+
runtime, ok := nativeInspect[0]["Runtime"].(map[string]interface{})
1351+
Expect(ok).Should(BeTrue())
1352+
1353+
// Verify runtime name
1354+
runtimeName, ok := runtime["Name"].(string)
1355+
Expect(ok).Should(BeTrue())
1356+
Expect(runtimeName).Should(Equal(options.HostConfig.Runtime))
1357+
})
12681358
})
12691359
}
12701360

0 commit comments

Comments
 (0)