diff --git a/config/types.go b/config/types.go index 7b0f10916..18291ac72 100644 --- a/config/types.go +++ b/config/types.go @@ -45,9 +45,9 @@ type ServiceConfigV1 struct { Links yaml.MaporColonSlice `yaml:"links,omitempty"` LogDriver string `yaml:"log_driver,omitempty"` MacAddress string `yaml:"mac_address,omitempty"` - MemLimit yaml.StringorInt `yaml:"mem_limit,omitempty"` - MemSwapLimit yaml.StringorInt `yaml:"memswap_limit,omitempty"` - MemSwappiness yaml.StringorInt `yaml:"mem_swappiness,omitempty"` + MemLimit yaml.MemStringorInt `yaml:"mem_limit,omitempty"` + MemSwapLimit yaml.MemStringorInt `yaml:"memswap_limit,omitempty"` + MemSwappiness yaml.MemStringorInt `yaml:"mem_swappiness,omitempty"` Name string `yaml:"name,omitempty"` Net string `yaml:"net,omitempty"` OomScoreAdj yaml.StringorInt `yaml:"oom_score_adj,omitempty"` @@ -58,7 +58,7 @@ type ServiceConfigV1 struct { Privileged bool `yaml:"privileged,omitempty"` Restart string `yaml:"restart,omitempty"` ReadOnly bool `yaml:"read_only,omitempty"` - ShmSize yaml.StringorInt `yaml:"shm_size,omitempty"` + ShmSize yaml.MemStringorInt `yaml:"shm_size,omitempty"` StdinOpen bool `yaml:"stdin_open,omitempty"` SecurityOpt []string `yaml:"security_opt,omitempty"` StopSignal string `yaml:"stop_signal,omitempty"` @@ -115,9 +115,9 @@ type ServiceConfig struct { Links yaml.MaporColonSlice `yaml:"links,omitempty"` Logging Log `yaml:"logging,omitempty"` MacAddress string `yaml:"mac_address,omitempty"` - MemLimit yaml.StringorInt `yaml:"mem_limit,omitempty"` - MemSwapLimit yaml.StringorInt `yaml:"memswap_limit,omitempty"` - MemSwappiness yaml.StringorInt `yaml:"mem_swappiness,omitempty"` + MemLimit yaml.MemStringorInt `yaml:"mem_limit,omitempty"` + MemSwapLimit yaml.MemStringorInt `yaml:"memswap_limit,omitempty"` + MemSwappiness yaml.MemStringorInt `yaml:"mem_swappiness,omitempty"` NetworkMode string `yaml:"network_mode,omitempty"` Networks *yaml.Networks `yaml:"networks,omitempty"` OomScoreAdj yaml.StringorInt `yaml:"oom_score_adj,omitempty"` @@ -125,7 +125,7 @@ type ServiceConfig struct { Ports []string `yaml:"ports,omitempty"` Privileged bool `yaml:"privileged,omitempty"` SecurityOpt []string `yaml:"security_opt,omitempty"` - ShmSize yaml.StringorInt `yaml:"shm_size,omitempty"` + ShmSize yaml.MemStringorInt `yaml:"shm_size,omitempty"` StopSignal string `yaml:"stop_signal,omitempty"` Tmpfs yaml.Stringorslice `yaml:"tmpfs,omitempty"` VolumeDriver string `yaml:"volume_driver,omitempty"` diff --git a/docker/service/convert_test.go b/docker/service/convert_test.go index e2b3bb464..1f1835bc5 100644 --- a/docker/service/convert_test.go +++ b/docker/service/convert_test.go @@ -130,7 +130,7 @@ func TestIsolation(t *testing.T) { func TestMemSwappiness(t *testing.T) { ctx := &ctx.Context{} sc := &config.ServiceConfig{ - MemSwappiness: yaml.StringorInt(10), + MemSwappiness: yaml.MemStringorInt(10), } _, hostCfg, err := Convert(sc, ctx.Context, nil) assert.Nil(t, err) diff --git a/project/project_test.go b/project/project_test.go index 73b356520..3ae8add39 100644 --- a/project/project_test.go +++ b/project/project_test.go @@ -201,7 +201,8 @@ func TestParseWithMultipleComposeFiles(t *testing.T) { configThree := []byte(` multiple: image: busybox - mem_limit: 40000000 + mem_limit: "40m" + memswap_limit: 40000000 ports: - 10000`) @@ -243,5 +244,6 @@ func TestParseWithMultipleComposeFiles(t *testing.T) { assert.Equal(t, "busybox", multipleConfig.Image) assert.Equal(t, "multi", multipleConfig.ContainerName) assert.Equal(t, []string{"8000", "9000", "10000"}, multipleConfig.Ports) - assert.Equal(t, yaml.StringorInt(40000000), multipleConfig.MemLimit) + assert.Equal(t, yaml.MemStringorInt(41943040), multipleConfig.MemLimit) + assert.Equal(t, yaml.MemStringorInt(40000000), multipleConfig.MemSwapLimit) } diff --git a/yaml/types_yaml.go b/yaml/types_yaml.go index b3c1126cf..5e75e5eca 100644 --- a/yaml/types_yaml.go +++ b/yaml/types_yaml.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/docker/docker/api/types/strslice" + "github.com/docker/go-units" ) // StringorInt represents a string or an integer. @@ -23,6 +24,7 @@ func (s *StringorInt) UnmarshalYAML(unmarshal func(interface{}) error) error { var stringType string if err := unmarshal(&stringType); err == nil { intType, err := strconv.ParseInt(stringType, 10, 64) + if err != nil { return err } @@ -33,6 +35,32 @@ func (s *StringorInt) UnmarshalYAML(unmarshal func(interface{}) error) error { return errors.New("Failed to unmarshal StringorInt") } +// MemStringorInt represents a string or an integer +// the String supports notations like 10m for then Megabyte of memory +type MemStringorInt int64 + +// UnmarshalYAML implements the Unmarshaller interface. +func (s *MemStringorInt) UnmarshalYAML(unmarshal func(interface{}) error) error { + var intType int64 + if err := unmarshal(&intType); err == nil { + *s = MemStringorInt(intType) + return nil + } + + var stringType string + if err := unmarshal(&stringType); err == nil { + intType, err := units.RAMInBytes(stringType) + + if err != nil { + return err + } + *s = MemStringorInt(intType) + return nil + } + + return errors.New("Failed to unmarshal MemStringorInt") +} + // Stringorslice represents // Using engine-api Strslice and augment it with YAML marshalling stuff. a string or an array of strings. type Stringorslice strslice.StrSlice