Skip to content

Commit 5fe141b

Browse files
committed
Support Shared Memory Size
1 parent 6302882 commit 5fe141b

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

ecs-cli/modules/cli/compose/project/project_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,15 @@ func TestParseComposeForVersion2Files(t *testing.T) {
209209
mysqlImage := "mysql"
210210
ports := []string{"80:80"}
211211
memoryReservation := int64(500000000)
212+
shmSize := yaml.MemStringorInt(1073741824) // 1 gb = 1024 * 1024 * 1024 bytes
212213

213214
composeFileString := `version: '2'
214215
services:
215216
wordpress:
216217
image: wordpress
217218
ports: ["80:80"]
218219
mem_reservation: 500000000
220+
shm_size: 1gb
219221
mysql:
220222
image: mysql`
221223

@@ -241,6 +243,7 @@ services:
241243
}
242244

243245
assert.Equal(t, memoryReservation, int64(wordpress.MemReservation), "Expected memoryReservation to match")
246+
assert.Equal(t, shmSize, wordpress.ShmSize, "Expected shmSize to match")
244247

245248
// verify mysql ServiceConfig
246249
mysql, ok := configs.Get("mysql")

ecs-cli/modules/utils/compose/convert_task_definition.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
const (
3333
defaultMemLimit = 512
3434
kiB = 1024
35+
miB = kiB * kiB // 1048576 bytes
3536

3637
// access mode with which the volume is mounted
3738
readOnlyVolumeAccessMode = "ro"
@@ -44,7 +45,7 @@ var supportedComposeYamlOptions = []string{
4445
"cpu_shares", "command", "dns", "dns_search", "entrypoint", "env_file",
4546
"environment", "extra_hosts", "hostname", "image", "labels", "links",
4647
"logging", "log_driver", "log_opt", "mem_limit", "mem_reservation", "ports", "privileged", "read_only",
47-
"security_opt", "ulimits", "user", "volumes", "volumes_from", "working_dir", "cap_add", "cap_drop",
48+
"security_opt", "ulimits", "user", "volumes", "volumes_from", "working_dir", "cap_add", "cap_drop", "shm_size",
4849
}
4950

5051
var supportedComposeYamlOptionsMap = getSupportedComposeYamlOptionsMap()
@@ -53,7 +54,6 @@ type volumes struct {
5354
volumeWithHost map[string]string
5455
volumeEmptyHost []string
5556
}
56-
5757
func getSupportedComposeYamlOptionsMap() map[string]bool {
5858
optionsMap := make(map[string]bool)
5959
for _, value := range supportedComposeYamlOptions {
@@ -233,10 +233,10 @@ func isZero(v reflect.Value) bool {
233233
}
234234

235235
// convertToContainerDef transforms each service in the compose yml
236-
// to an equivalent container definition
236+
// to an equivalent ECS container definition
237237
func convertToContainerDef(context *project.Context, inputCfg *config.ServiceConfig,
238238
volumes *volumes, outputContDef *ecs.ContainerDefinition, ecsContainerDef *ContainerDef) error {
239-
// setting memory
239+
// setting memory limit
240240
var mem int64
241241
var memoryReservation int64
242242
if inputCfg.MemReservation != 0 {
@@ -251,10 +251,20 @@ func convertToContainerDef(context *project.Context, inputCfg *config.ServiceCon
251251
return errors.New("mem_limit should not be less than mem_reservation")
252252
}
253253

254+
// TODO: We should be letting docker set the default here -- see note on default shared
255+
// memory size?
254256
if mem == 0 && memoryReservation == 0 {
255257
mem = defaultMemLimit
256258
}
257259

260+
// convert shared memory size
261+
var shmSize int64
262+
if inputCfg.ShmSize != 0 {
263+
// libcompose will parse this field in the docker compose file as bytes but ECS
264+
// expects sharedMemorySize in MiB
265+
shmSize = int64(inputCfg.ShmSize) / miB
266+
}
267+
258268
// convert environment variables
259269
environment := convertToKeyValuePairs(context, inputCfg.Environment, *outputContDef.Name)
260270

@@ -340,6 +350,13 @@ func convertToContainerDef(context *project.Context, inputCfg *config.ServiceCon
340350
outputContDef.LinuxParameters.Capabilities.SetDrop(aws.StringSlice(inputCfg.CapDrop))
341351
}
342352

353+
// Only set shmSize if specified. Otherwise we expect this sharedMemorySize for the
354+
// containerDefinition to be null; Docker will by default allocate 64M for shared memory if
355+
// shmSize is null.
356+
if shmSize != 0 {
357+
outputContDef.LinuxParameters.SetSharedMemorySize(shmSize)
358+
}
359+
343360
if ecsContainerDef != nil {
344361
outputContDef.Essential = aws.Bool(ecsContainerDef.Essential)
345362
}

ecs-cli/modules/utils/compose/convert_task_definition_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func TestConvertToTaskDefinition(t *testing.T) {
5757
user := "user"
5858
workingDir := "/var"
5959
taskRoleArn := "arn:aws:iam::123456789012:role/my_role"
60+
6061
serviceConfig := &config.ServiceConfig{
6162
CPUShares: yaml.StringorInt(cpu),
6263
Command: []string{command},
@@ -105,6 +106,8 @@ func TestConvertToTaskDefinition(t *testing.T) {
105106

106107
assert.Equal(t, memoryReservation, aws.Int64Value(containerDef.MemoryReservation), "Expected memoryReservation to match")
107108

109+
assert.Nil(t, containerDef.LinuxParameters.SharedMemorySize, "Expected sharedMemorySize to be null")
110+
108111
if privileged != aws.BoolValue(containerDef.Privileged) {
109112
t.Errorf("Expected privileged [%t] But was [%t]", privileged, aws.BoolValue(containerDef.Privileged))
110113
}
@@ -129,6 +132,31 @@ func TestConvertToTaskDefinition(t *testing.T) {
129132
}
130133
}
131134

135+
func TestConvertToTaskDefinitionWithNoSharedMemorySize(t *testing.T) {
136+
serviceConfig := serviceConfigWithDefaultNetworks()
137+
138+
taskDefinition := convertToTaskDefinitionInTest(t, "name", serviceConfig, "", "")
139+
containerDef := *taskDefinition.ContainerDefinitions[0]
140+
141+
assert.Nil(t, containerDef.LinuxParameters.SharedMemorySize, "Expected sharedMemorySize to be null")
142+
}
143+
144+
func TestConvertToTaskDefinitionWithSharedMemorySize(t *testing.T) {
145+
// Realistically, we expect customers to specify sizes larger than the default of 64M
146+
expectedMBs := 128
147+
shmSize := yaml.MemStringorInt(int64(expectedMBs * miB))
148+
149+
serviceConfig := &config.ServiceConfig{
150+
ShmSize: shmSize,
151+
Networks: &yaml.Networks{Networks: []*yaml.Network{defaultNetwork}},
152+
}
153+
154+
taskDefinition := convertToTaskDefinitionInTest(t, "name", serviceConfig, "", "")
155+
containerDef := *taskDefinition.ContainerDefinitions[0]
156+
157+
assert.Equal(t, int64(expectedMBs), aws.Int64Value(containerDef.LinuxParameters.SharedMemorySize), "Expected sharedMemorySize to match")
158+
}
159+
132160
func TestConvertToTaskDefinitionLaunchTypeEmpty(t *testing.T) {
133161
serviceConfig := serviceConfigWithDefaultNetworks()
134162

0 commit comments

Comments
 (0)