Skip to content

Commit 958cb4f

Browse files
committed
normalize scale -> deploy.replicas, defaults to 1
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 81485a4 commit 958cb4f

File tree

9 files changed

+51
-8
lines changed

9 files changed

+51
-8
lines changed

compatibility/allowlist_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func TestAllowList(t *testing.T) {
3333
"services.network_mode",
3434
"services.privileged",
3535
"services.networks",
36+
"services.scale",
3637
},
3738
},
3839
}

loader/full-struct_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
358358
Privileged: true,
359359
ReadOnly: true,
360360
Restart: types.RestartPolicyAlways,
361+
Scale: 1,
361362
Secrets: []types.ServiceSecretConfig{
362363
{
363364
Source: "secret1",

loader/loader.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,9 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
514514
// LoadService produces a single ServiceConfig from a compose file Dict
515515
// the serviceDict is not validated if directly used. Use Load() to enable validation
516516
func LoadService(name string, serviceDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, resolvePaths bool) (*types.ServiceConfig, error) {
517-
serviceConfig := &types.ServiceConfig{}
517+
serviceConfig := &types.ServiceConfig{
518+
Scale: 1,
519+
}
518520
if err := Transform(serviceDict, serviceConfig); err != nil {
519521
return nil, err
520522
}

loader/loader_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ var sampleConfig = types.Config{
202202
Networks: map[string]*types.ServiceNetworkConfig{
203203
"with_me": nil,
204204
},
205+
Scale: 1,
205206
},
206207
{
207208
Name: "bar",
@@ -210,6 +211,7 @@ var sampleConfig = types.Config{
210211
Networks: map[string]*types.ServiceNetworkConfig{
211212
"with_ipam": nil,
212213
},
214+
Scale: 1,
213215
},
214216
},
215217
Networks: map[string]types.NetworkConfig{
@@ -689,6 +691,7 @@ networks:
689691
},
690692
Privileged: true,
691693
ReadOnly: true,
694+
Scale: 1,
692695
ShmSize: types.UnitBytes(2 * 1024 * 1024 * 1024),
693696
StdinOpen: true,
694697
Tty: true,
@@ -1440,6 +1443,7 @@ networks:
14401443
{
14411444
Name: "hello-world",
14421445
Image: "redis:alpine",
1446+
Scale: 1,
14431447
Networks: map[string]*types.ServiceNetworkConfig{
14441448
"network1": nil,
14451449
"network3": nil,
@@ -1602,6 +1606,7 @@ secrets:
16021606
Source: "config",
16031607
},
16041608
},
1609+
Scale: 1,
16051610
Secrets: []types.ServiceSecretConfig{
16061611
{
16071612
Source: "secret",
@@ -1667,6 +1672,7 @@ secrets:
16671672
Source: "config",
16681673
},
16691674
},
1675+
Scale: 1,
16701676
Secrets: []types.ServiceSecretConfig{
16711677
{
16721678
Source: "secret",
@@ -1741,6 +1747,7 @@ func TestLoadWithExtends(t *testing.T) {
17411747
},
17421748
Environment: types.MappingWithEquals{},
17431749
Networks: map[string]*types.ServiceNetworkConfig{"default": nil},
1750+
Scale: 1,
17441751
},
17451752
}
17461753
assert.Check(t, is.DeepEqual(expServices, actual.Services))

loader/merge_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ func TestLoadLogging(t *testing.T) {
215215
Name: "foo",
216216
Logging: tc.expected,
217217
Environment: types.MappingWithEquals{},
218+
Scale: 1,
218219
},
219220
},
220221
Networks: types.Networks{},
@@ -370,6 +371,7 @@ func TestLoadMultipleServicePorts(t *testing.T) {
370371
Name: "foo",
371372
Ports: tc.expected,
372373
Environment: types.MappingWithEquals{},
374+
Scale: 1,
373375
},
374376
},
375377
Networks: types.Networks{},
@@ -495,6 +497,7 @@ func TestLoadMultipleSecretsConfig(t *testing.T) {
495497
Name: "foo",
496498
Secrets: tc.expected,
497499
Environment: types.MappingWithEquals{},
500+
Scale: 1,
498501
},
499502
},
500503
Networks: types.Networks{},
@@ -620,6 +623,7 @@ func TestLoadMultipleConfigobjsConfig(t *testing.T) {
620623
Name: "foo",
621624
Configs: tc.expected,
622625
Environment: types.MappingWithEquals{},
626+
Scale: 1,
623627
},
624628
},
625629
Networks: types.Networks{},
@@ -735,6 +739,7 @@ func TestLoadMultipleUlimits(t *testing.T) {
735739
Name: "foo",
736740
Ulimits: tc.expected,
737741
Environment: types.MappingWithEquals{},
742+
Scale: 1,
738743
},
739744
},
740745
Networks: types.Networks{},
@@ -853,6 +858,7 @@ func TestLoadMultipleServiceNetworks(t *testing.T) {
853858
Name: "foo",
854859
Networks: tc.expected,
855860
Environment: types.MappingWithEquals{},
861+
Scale: 1,
856862
},
857863
},
858864
Networks: types.Networks{},
@@ -940,6 +946,7 @@ func TestLoadMultipleConfigs(t *testing.T) {
940946
Name: "bar",
941947
Image: "bar",
942948
Environment: types.MappingWithEquals{},
949+
Scale: 1,
943950
},
944951
{
945952
Name: "foo",
@@ -975,6 +982,7 @@ func TestLoadMultipleConfigs(t *testing.T) {
975982
},
976983
CapAdd: []string{"NET_ADMIN", "SYS_ADMIN"},
977984
Environment: types.MappingWithEquals{},
985+
Scale: 1,
978986
}},
979987
Networks: types.Networks{},
980988
Volumes: types.Volumes{},
@@ -1038,6 +1046,7 @@ func TestLoadMultipleNetworks(t *testing.T) {
10381046
Name: "foo",
10391047
Image: "baz",
10401048
Environment: types.MappingWithEquals{},
1049+
Scale: 1,
10411050
}},
10421051
Networks: map[string]types.NetworkConfig{
10431052
"hostnet": {

loader/normalize.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,22 @@ func normalize(project *types.Project, resolvePaths bool) error {
8484
}
8585
s.Environment = s.Environment.Resolve(fn)
8686

87-
err := relocateLogDriver(s)
87+
err := relocateLogDriver(&s)
8888
if err != nil {
8989
return err
9090
}
9191

92-
err = relocateLogOpt(s)
92+
err = relocateLogOpt(&s)
9393
if err != nil {
9494
return err
9595
}
9696

97-
err = relocateDockerfile(s)
97+
err = relocateDockerfile(&s)
98+
if err != nil {
99+
return err
100+
}
101+
102+
err = relocateScale(&s)
98103
if err != nil {
99104
return err
100105
}
@@ -107,6 +112,21 @@ func normalize(project *types.Project, resolvePaths bool) error {
107112
return nil
108113
}
109114

115+
func relocateScale(s *types.ServiceConfig) error {
116+
scale := uint64(s.Scale)
117+
if scale != 1 {
118+
logrus.Warn("`scale` is deprecated. Use the `deploy.replicas` element")
119+
if s.Deploy == nil {
120+
s.Deploy = &types.DeployConfig{}
121+
}
122+
if s.Deploy.Replicas != nil && *s.Deploy.Replicas != scale {
123+
return errors.Wrap(errdefs.ErrInvalid, "can't use both 'scale' (deprecated) and 'deploy.replicas'")
124+
}
125+
s.Deploy.Replicas = &scale
126+
}
127+
return nil
128+
}
129+
110130
func absComposeFiles(composeFiles []string) ([]string, error) {
111131
absComposeFiles := make([]string, len(composeFiles))
112132
for i, composeFile := range composeFiles {
@@ -193,7 +213,7 @@ func relocateExternalName(project *types.Project) error {
193213
return nil
194214
}
195215

196-
func relocateLogOpt(s types.ServiceConfig) error {
216+
func relocateLogOpt(s *types.ServiceConfig) error {
197217
if len(s.LogOpt) != 0 {
198218
logrus.Warn("`log_opts` is deprecated. Use the `logging` element")
199219
if s.Logging == nil {
@@ -210,7 +230,7 @@ func relocateLogOpt(s types.ServiceConfig) error {
210230
return nil
211231
}
212232

213-
func relocateLogDriver(s types.ServiceConfig) error {
233+
func relocateLogDriver(s *types.ServiceConfig) error {
214234
if s.LogDriver != "" {
215235
logrus.Warn("`log_driver` is deprecated. Use the `logging` element")
216236
if s.Logging == nil {
@@ -225,7 +245,7 @@ func relocateLogDriver(s types.ServiceConfig) error {
225245
return nil
226246
}
227247

228-
func relocateDockerfile(s types.ServiceConfig) error {
248+
func relocateDockerfile(s *types.ServiceConfig) error {
229249
if s.Dockerfile != "" {
230250
logrus.Warn("`dockerfile` is deprecated. Use the `build` element")
231251
if s.Build == nil {

loader/normalize_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func TestNormalizeNetworkNames(t *testing.T) {
5454
"ZOT": nil,
5555
},
5656
},
57+
Scale: 1,
5758
},
5859
},
5960
}

loader/with-version-struct_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func withVersionServices(workingDir, homeDir string) []types.ServiceConfig {
4242
"default": nil,
4343
},
4444
VolumesFrom: []string{"other"},
45+
Scale: 1,
4546
},
4647
{
4748
Name: "other",
@@ -52,6 +53,7 @@ func withVersionServices(workingDir, homeDir string) []types.ServiceConfig {
5253
Volumes: []types.ServiceVolumeConfig{
5354
{Target: "/data", Type: "volume", Volume: &types.ServiceVolumeVolume{}},
5455
},
56+
Scale: 1,
5557
},
5658
}
5759
}

types/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ type ServiceConfig struct {
152152
ReadOnly bool `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"`
153153
Restart string `yaml:",omitempty" json:"restart,omitempty"`
154154
Runtime string `yaml:",omitempty" json:"runtime,omitempty"`
155-
Scale int `yaml:",omitempty" json:"scale,omitempty"`
155+
Scale int `yaml:"-" json:"-"`
156156
Secrets []ServiceSecretConfig `yaml:",omitempty" json:"secrets,omitempty"`
157157
SecurityOpt []string `mapstructure:"security_opt" yaml:"security_opt,omitempty" json:"security_opt,omitempty"`
158158
ShmSize UnitBytes `mapstructure:"shm_size" yaml:"shm_size,omitempty" json:"shm_size,omitempty"`

0 commit comments

Comments
 (0)