Skip to content

Commit 8fc8d6f

Browse files
committed
Manage secrets|configs.mode as an octal string||number
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 84b7d5a commit 8fc8d6f

File tree

5 files changed

+99
-51
lines changed

5 files changed

+99
-51
lines changed

loader/full-struct_test.go

+21-21
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func services(workingDir, homeDir string) types.Services {
7272
Target: "my_secret",
7373
UID: "103",
7474
GID: "103",
75-
Mode: uint32Ptr(0o440),
75+
Mode: ptr(types.FileMode(0o440)),
7676
},
7777
},
7878
Tags: []string{"foo:v1.0.0", "docker.io/username/foo:my-other-tag", "full_example_project_name:1.0.0"},
@@ -91,7 +91,7 @@ func services(workingDir, homeDir string) types.Services {
9191
Target: "/my_config",
9292
UID: "103",
9393
GID: "103",
94-
Mode: uint32Ptr(0o440),
94+
Mode: ptr(types.FileMode(0o440)),
9595
},
9696
},
9797
ContainerName: "my-web-container",
@@ -101,18 +101,18 @@ func services(workingDir, homeDir string) types.Services {
101101
},
102102
Deploy: &types.DeployConfig{
103103
Mode: "replicated",
104-
Replicas: intPtr(6),
104+
Replicas: ptr(6),
105105
Labels: map[string]string{"FOO": "BAR"},
106106
RollbackConfig: &types.UpdateConfig{
107-
Parallelism: uint64Ptr(3),
107+
Parallelism: ptr(uint64(3)),
108108
Delay: types.Duration(10 * time.Second),
109109
FailureAction: "continue",
110110
Monitor: types.Duration(60 * time.Second),
111111
MaxFailureRatio: 0.3,
112112
Order: "start-first",
113113
},
114114
UpdateConfig: &types.UpdateConfig{
115-
Parallelism: uint64Ptr(3),
115+
Parallelism: ptr(uint64(3)),
116116
Delay: types.Duration(10 * time.Second),
117117
FailureAction: "continue",
118118
Monitor: types.Duration(60 * time.Second),
@@ -145,9 +145,9 @@ func services(workingDir, homeDir string) types.Services {
145145
},
146146
RestartPolicy: &types.RestartPolicy{
147147
Condition: types.RestartPolicyOnFailure,
148-
Delay: durationPtr(5 * time.Second),
149-
MaxAttempts: uint64Ptr(3),
150-
Window: durationPtr(2 * time.Minute),
148+
Delay: ptr(types.Duration(5 * time.Second)),
149+
MaxAttempts: ptr(uint64(3)),
150+
Window: ptr(types.Duration(2 * time.Minute)),
151151
},
152152
Placement: types.Placement{
153153
Constraints: []string{"node=foo"},
@@ -206,11 +206,11 @@ func services(workingDir, homeDir string) types.Services {
206206
},
207207
HealthCheck: &types.HealthCheckConfig{
208208
Test: types.HealthCheckTest([]string{"CMD-SHELL", "echo \"hello world\""}),
209-
Interval: durationPtr(10 * time.Second),
210-
Timeout: durationPtr(1 * time.Second),
211-
Retries: uint64Ptr(5),
212-
StartPeriod: durationPtr(15 * time.Second),
213-
StartInterval: durationPtr(5 * time.Second),
209+
Interval: ptr(types.Duration(10 * time.Second)),
210+
Timeout: ptr(types.Duration(1 * time.Second)),
211+
Retries: ptr(uint64(5)),
212+
StartPeriod: ptr(types.Duration(15 * time.Second)),
213+
StartInterval: ptr(types.Duration(5 * time.Second)),
214214
},
215215
Hostname: "foo",
216216
Image: "redis",
@@ -417,7 +417,7 @@ func services(workingDir, homeDir string) types.Services {
417417
Target: "my_secret",
418418
UID: "103",
419419
GID: "103",
420-
Mode: uint32Ptr(0o440),
420+
Mode: ptr(types.FileMode(0o440)),
421421
},
422422
},
423423
SecurityOpt: []string{
@@ -427,7 +427,7 @@ func services(workingDir, homeDir string) types.Services {
427427
StdinOpen: true,
428428
StopSignal: "SIGUSR1",
429429
StorageOpt: map[string]string{"size": "20G"},
430-
StopGracePeriod: durationPtr(20 * time.Second),
430+
StopGracePeriod: ptr(types.Duration(20 * time.Second)),
431431
Sysctls: map[string]string{
432432
"net.core.somaxconn": "1024",
433433
"net.ipv4.tcp_syncookies": "0",
@@ -648,7 +648,7 @@ services:
648648
target: my_secret
649649
uid: "103"
650650
gid: "103"
651-
mode: 288
651+
mode: "0440"
652652
tags:
653653
- foo:v1.0.0
654654
- docker.io/username/foo:my-other-tag
@@ -674,7 +674,7 @@ services:
674674
target: /my_config
675675
uid: "103"
676676
gid: "103"
677-
mode: 288
677+
mode: "0440"
678678
container_name: my-web-container
679679
depends_on:
680680
db:
@@ -918,7 +918,7 @@ services:
918918
target: my_secret
919919
uid: "103"
920920
gid: "103"
921-
mode: 288
921+
mode: "0440"
922922
security_opt:
923923
- label=level:s0:c100,c200
924924
- label=type:svirt_apache_t
@@ -1219,7 +1219,7 @@ func fullExampleJSON(workingDir, homeDir string) string {
12191219
"target": "my_secret",
12201220
"uid": "103",
12211221
"gid": "103",
1222-
"mode": 288
1222+
"mode": "0440"
12231223
}
12241224
],
12251225
"tags": [
@@ -1256,7 +1256,7 @@ func fullExampleJSON(workingDir, homeDir string) string {
12561256
"target": "/my_config",
12571257
"uid": "103",
12581258
"gid": "103",
1259-
"mode": 288
1259+
"mode": "0440"
12601260
}
12611261
],
12621262
"container_name": "my-web-container",
@@ -1598,7 +1598,7 @@ func fullExampleJSON(workingDir, homeDir string) string {
15981598
"target": "my_secret",
15991599
"uid": "103",
16001600
"gid": "103",
1601-
"mode": 288
1601+
"mode": "0440"
16021602
}
16031603
],
16041604
"security_opt": [

loader/interpolate.go

-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ var interpolateTypeCastMapping = map[tree.Path]interp.Cast{
5353
servicePath("privileged"): toBoolean,
5454
servicePath("read_only"): toBoolean,
5555
servicePath("scale"): toInt,
56-
servicePath("secrets", tree.PathMatchList, "mode"): toInt,
5756
servicePath("stdin_open"): toBoolean,
5857
servicePath("tty"): toBoolean,
5958
servicePath("ulimits", tree.PathMatchAll): toInt,

loader/loader_test.go

+39-22
Original file line numberDiff line numberDiff line change
@@ -835,32 +835,32 @@ networks:
835835
Configs: []types.ServiceConfigObjConfig{
836836
{
837837
Source: "appconfig",
838-
Mode: uint32Ptr(555),
838+
Mode: ptr(types.FileMode(555)),
839839
},
840840
},
841841
Secrets: []types.ServiceSecretConfig{
842842
{
843843
Source: "super",
844844
Target: "/run/secrets/super",
845-
Mode: uint32Ptr(555),
845+
Mode: ptr(types.FileMode(555)),
846846
},
847847
},
848848
HealthCheck: &types.HealthCheckConfig{
849-
Retries: uint64Ptr(555),
849+
Retries: ptr(uint64(555)),
850850
Disable: true,
851851
},
852852
Deploy: &types.DeployConfig{
853-
Replicas: intPtr(555),
853+
Replicas: ptr(555),
854854
UpdateConfig: &types.UpdateConfig{
855-
Parallelism: uint64Ptr(555),
855+
Parallelism: ptr(uint64(555)),
856856
MaxFailureRatio: 3.14,
857857
},
858858
RollbackConfig: &types.UpdateConfig{
859-
Parallelism: uint64Ptr(555),
859+
Parallelism: ptr(uint64(555)),
860860
MaxFailureRatio: 3.14,
861861
},
862862
RestartPolicy: &types.RestartPolicy{
863-
MaxAttempts: uint64Ptr(555),
863+
MaxAttempts: ptr(uint64(555)),
864864
},
865865
Placement: types.Placement{
866866
MaxReplicas: 555,
@@ -1167,21 +1167,8 @@ services:
11671167
assert.Equal(t, *foo.Scale, 2)
11681168
}
11691169

1170-
func durationPtr(value time.Duration) *types.Duration {
1171-
result := types.Duration(value)
1172-
return &result
1173-
}
1174-
1175-
func intPtr(value int) *int {
1176-
return &value
1177-
}
1178-
1179-
func uint64Ptr(value uint64) *uint64 {
1180-
return &value
1181-
}
1182-
1183-
func uint32Ptr(value uint32) *uint32 {
1184-
return &value
1170+
func ptr[T any](t T) *T {
1171+
return &t
11851172
}
11861173

11871174
func TestFullExample(t *testing.T) {
@@ -3750,3 +3737,33 @@ services:
37503737
assert.Equal(t, len(p.Services["test"].Gpus), 1)
37513738
assert.Equal(t, p.Services["test"].Gpus[0].Count, types.DeviceCount(-1))
37523739
}
3740+
3741+
func TestFileModeNumber(t *testing.T) {
3742+
p, err := loadYAML(`
3743+
name: load-file-mode
3744+
services:
3745+
test:
3746+
secrets:
3747+
- source: server-certificate
3748+
target: server.cert
3749+
mode: 0o440
3750+
`)
3751+
assert.NilError(t, err)
3752+
assert.Equal(t, len(p.Services["test"].Secrets), 1)
3753+
assert.Equal(t, *p.Services["test"].Secrets[0].Mode, types.FileMode(0o440))
3754+
}
3755+
3756+
func TestFileModeString(t *testing.T) {
3757+
p, err := loadYAML(`
3758+
name: load-file-mode
3759+
services:
3760+
test:
3761+
secrets:
3762+
- source: server-certificate
3763+
target: server.cert
3764+
mode: "0440"
3765+
`)
3766+
assert.NilError(t, err)
3767+
assert.Equal(t, len(p.Services["test"].Secrets), 1)
3768+
assert.Equal(t, *p.Services["test"].Secrets[0].Mode, types.FileMode(0o440))
3769+
}

types/derived.gen.go

+3-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

types/types.go

+36-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"encoding/json"
2121
"fmt"
2222
"sort"
23+
"strconv"
2324
"strings"
2425

2526
"github.com/docker/go-connections/nat"
@@ -604,17 +605,47 @@ type ServiceVolumeTmpfs struct {
604605
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
605606
}
606607

608+
type FileMode int64
609+
607610
// FileReferenceConfig for a reference to a swarm file object
608611
type FileReferenceConfig struct {
609-
Source string `yaml:"source,omitempty" json:"source,omitempty"`
610-
Target string `yaml:"target,omitempty" json:"target,omitempty"`
611-
UID string `yaml:"uid,omitempty" json:"uid,omitempty"`
612-
GID string `yaml:"gid,omitempty" json:"gid,omitempty"`
613-
Mode *uint32 `yaml:"mode,omitempty" json:"mode,omitempty"`
612+
Source string `yaml:"source,omitempty" json:"source,omitempty"`
613+
Target string `yaml:"target,omitempty" json:"target,omitempty"`
614+
UID string `yaml:"uid,omitempty" json:"uid,omitempty"`
615+
GID string `yaml:"gid,omitempty" json:"gid,omitempty"`
616+
Mode *FileMode `yaml:"mode,omitempty" json:"mode,omitempty"`
614617

615618
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
616619
}
617620

621+
func (f *FileMode) DecodeMapstructure(value interface{}) error {
622+
switch v := value.(type) {
623+
case *FileMode:
624+
return nil
625+
case string:
626+
i, err := strconv.ParseInt(v, 8, 64)
627+
if err != nil {
628+
return err
629+
}
630+
*f = FileMode(i)
631+
case int:
632+
*f = FileMode(v)
633+
default:
634+
return fmt.Errorf("unexpected value type %T for mode", value)
635+
}
636+
return nil
637+
}
638+
639+
// MarshalYAML makes FileMode implement yaml.Marshaller
640+
func (f *FileMode) MarshalYAML() (interface{}, error) {
641+
return fmt.Sprintf("0%o", int64(*f)), nil
642+
}
643+
644+
// MarshalJSON makes FileMode implement json.Marshaller
645+
func (f *FileMode) MarshalJSON() ([]byte, error) {
646+
return []byte(fmt.Sprintf("\"0%o\"", int64(*f))), nil
647+
}
648+
618649
// ServiceConfigObjConfig is the config obj configuration for a service
619650
type ServiceConfigObjConfig FileReferenceConfig
620651

0 commit comments

Comments
 (0)