Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2681ed1

Browse files
committed
mutualize code from injectSecrets / injectConfigs
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent ee75be3 commit 2681ed1

File tree

2 files changed

+113
-87
lines changed

2 files changed

+113
-87
lines changed

pkg/compose/secrets.go

Lines changed: 102 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -29,121 +29,139 @@ import (
2929
"github.com/docker/docker/api/types/container"
3030
)
3131

32+
type mountType string
33+
34+
const (
35+
secretMount mountType = "secret"
36+
configMount mountType = "config"
37+
)
38+
3239
func (s *composeService) injectSecrets(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
33-
var ctrConfig *container.Config
34-
for _, config := range service.Secrets {
35-
file := project.Secrets[config.Source]
36-
if file.Environment == "" {
37-
continue
38-
}
40+
return s.injectFileReferences(ctx, project, service, id, secretMount)
41+
}
3942

40-
if service.ReadOnly {
41-
return fmt.Errorf("cannot create secret %q in read-only service %s: `file` is the sole supported option", file.Name, service.Name)
42-
}
43+
func (s *composeService) injectConfigs(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
44+
return s.injectFileReferences(ctx, project, service, id, configMount)
45+
}
4346

44-
if config.Target == "" {
45-
config.Target = "/run/secrets/" + config.Source
46-
} else if !isAbsTarget(config.Target) {
47-
config.Target = "/run/secrets/" + config.Target
48-
}
47+
func (s *composeService) injectFileReferences(ctx context.Context, project *types.Project, service types.ServiceConfig, id string, mountType mountType) error {
48+
mounts, sources := s.getFilesAndMap(project, service, mountType)
49+
var ctrConfig *container.Config
4950

50-
content := file.Content
51+
for _, mount := range mounts {
52+
content, err := s.resolveFileContent(project, sources[mount.Source], mountType)
53+
if err != nil {
54+
return err
55+
}
5156
if content == "" {
52-
env, ok := project.Environment[file.Environment]
53-
if !ok {
54-
return fmt.Errorf("environment variable %q required by secret %q is not set", file.Environment, file.Name)
55-
}
56-
content = env
57+
continue
5758
}
5859

59-
if config.UID == "" && config.GID == "" {
60-
if ctrConfig == nil {
61-
ctr, err := s.apiClient().ContainerInspect(ctx, id)
62-
if err != nil {
63-
return err
64-
}
65-
ctrConfig = ctr.Config
66-
}
67-
68-
parts := strings.Split(ctrConfig.User, ":")
69-
if len(parts) > 0 {
70-
config.UID = parts[0]
71-
}
72-
if len(parts) > 1 {
73-
config.GID = parts[1]
74-
}
60+
if service.ReadOnly {
61+
return fmt.Errorf("cannot create %s %q in read-only service %s: `file` is the sole supported option", mountType, sources[mount.Source].Name, service.Name)
7562
}
7663

77-
b, err := createTar(content, types.FileReferenceConfig(config))
64+
s.setDefaultTarget(&mount, mountType)
65+
66+
ctrConfig, err = s.setFileOwnership(ctx, id, &mount, ctrConfig)
7867
if err != nil {
7968
return err
8069
}
8170

82-
err = s.apiClient().CopyToContainer(ctx, id, "/", &b, container.CopyToContainerOptions{
83-
CopyUIDGID: config.UID != "" || config.GID != "",
84-
})
85-
if err != nil {
71+
if err := s.copyFileToContainer(ctx, id, content, mount); err != nil {
8672
return err
8773
}
8874
}
8975
return nil
9076
}
9177

92-
func (s *composeService) injectConfigs(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
93-
var ctrConfig *container.Config
94-
for _, config := range service.Configs {
95-
file := project.Configs[config.Source]
96-
content := file.Content
97-
if file.Environment != "" {
98-
env, ok := project.Environment[file.Environment]
99-
if !ok {
100-
return fmt.Errorf("environment variable %q required by config %q is not set", file.Environment, file.Name)
101-
}
102-
content = env
78+
func (s *composeService) getFilesAndMap(project *types.Project, service types.ServiceConfig, mountType mountType) ([]types.FileReferenceConfig, map[string]types.FileObjectConfig) {
79+
var files []types.FileReferenceConfig
80+
var fileMap map[string]types.FileObjectConfig
81+
82+
switch mountType {
83+
case secretMount:
84+
files = make([]types.FileReferenceConfig, len(service.Secrets))
85+
for i, config := range service.Secrets {
86+
files[i] = types.FileReferenceConfig(config)
10387
}
104-
if content == "" {
105-
continue
88+
fileMap = make(map[string]types.FileObjectConfig)
89+
for k, v := range project.Secrets {
90+
fileMap[k] = types.FileObjectConfig(v)
10691
}
107-
108-
if service.ReadOnly {
109-
return fmt.Errorf("cannot create config %q in read-only service %s: `file` is the sole supported option", file.Name, service.Name)
92+
case configMount:
93+
files = make([]types.FileReferenceConfig, len(service.Configs))
94+
for i, config := range service.Configs {
95+
files[i] = types.FileReferenceConfig(config)
11096
}
111-
112-
if config.Target == "" {
113-
config.Target = "/" + config.Source
97+
fileMap = make(map[string]types.FileObjectConfig)
98+
for k, v := range project.Configs {
99+
fileMap[k] = types.FileObjectConfig(v)
114100
}
101+
}
102+
return files, fileMap
103+
}
115104

116-
if config.UID == "" && config.GID == "" {
117-
if ctrConfig == nil {
118-
ctr, err := s.apiClient().ContainerInspect(ctx, id)
119-
if err != nil {
120-
return err
121-
}
122-
ctrConfig = ctr.Config
123-
}
124-
125-
parts := strings.Split(ctrConfig.User, ":")
126-
if len(parts) > 0 {
127-
config.UID = parts[0]
128-
}
129-
if len(parts) > 1 {
130-
config.GID = parts[1]
131-
}
105+
func (s *composeService) resolveFileContent(project *types.Project, source types.FileObjectConfig, mountType mountType) (string, error) {
106+
if source.Content != "" {
107+
// inlined, or already resolved by include
108+
return source.Content, nil
109+
}
110+
if source.Environment != "" {
111+
env, ok := project.Environment[source.Environment]
112+
if !ok {
113+
return "", fmt.Errorf("environment variable %q required by %s %q is not set", source.Environment, mountType, source.Name)
132114
}
115+
return env, nil
116+
}
117+
return "", nil
118+
}
133119

134-
b, err := createTar(content, types.FileReferenceConfig(config))
135-
if err != nil {
136-
return err
120+
func (s *composeService) setDefaultTarget(file *types.FileReferenceConfig, mountType mountType) {
121+
if file.Target == "" {
122+
if mountType == secretMount {
123+
file.Target = "/run/secrets/" + file.Source
124+
} else {
125+
file.Target = "/" + file.Source
137126
}
127+
} else if mountType == secretMount && !isAbsTarget(file.Target) {
128+
file.Target = "/run/secrets/" + file.Target
129+
}
130+
}
138131

139-
err = s.apiClient().CopyToContainer(ctx, id, "/", &b, container.CopyToContainerOptions{
140-
CopyUIDGID: config.UID != "" || config.GID != "",
141-
})
132+
func (s *composeService) setFileOwnership(ctx context.Context, id string, file *types.FileReferenceConfig, ctrConfig *container.Config) (*container.Config, error) {
133+
if file.UID != "" || file.GID != "" {
134+
return ctrConfig, nil
135+
}
136+
137+
if ctrConfig == nil {
138+
ctr, err := s.apiClient().ContainerInspect(ctx, id)
142139
if err != nil {
143-
return err
140+
return nil, err
144141
}
142+
ctrConfig = ctr.Config
145143
}
146-
return nil
144+
145+
parts := strings.Split(ctrConfig.User, ":")
146+
if len(parts) > 0 {
147+
file.UID = parts[0]
148+
}
149+
if len(parts) > 1 {
150+
file.GID = parts[1]
151+
}
152+
153+
return ctrConfig, nil
154+
}
155+
156+
func (s *composeService) copyFileToContainer(ctx context.Context, id, content string, file types.FileReferenceConfig) error {
157+
b, err := createTar(content, file)
158+
if err != nil {
159+
return err
160+
}
161+
162+
return s.apiClient().CopyToContainer(ctx, id, "/", &b, container.CopyToContainerOptions{
163+
CopyUIDGID: true,
164+
})
147165
}
148166

149167
func createTar(env string, config types.FileReferenceConfig) (bytes.Buffer, error) {

pkg/e2e/secrets_test.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package e2e
1818

1919
import (
20+
"strings"
2021
"testing"
2122

2223
"gotest.tools/v3/icmd"
@@ -41,20 +42,27 @@ func TestSecretFromEnv(t *testing.T) {
4142
res.Assert(t, icmd.Expected{Out: "-r--r----- 1 1005 1005"})
4243
})
4344
t.Run("secret uid from user", func(t *testing.T) {
44-
res := icmd.RunCmd(c.NewDockerComposeCmd(t, "-f", "./fixtures/env-secret/compose.yaml", "run", "bar", "ls", "-al", "/var/run/secrets/bar"),
45+
res := c.RunDockerCmd(t, "version", "--format", "{{ .Server.Version }}")
46+
if strings.HasPrefix(res.Stdout(), "27.") {
47+
t.Skip("USER uid:gid is not supported")
48+
}
49+
res = icmd.RunCmd(c.NewDockerComposeCmd(t, "-f", "./fixtures/env-secret/compose.yaml", "run", "bar", "ls", "-al", "/var/run/secrets/bar"),
4550
func(cmd *icmd.Cmd) {
4651
cmd.Env = append(cmd.Env, "SECRET=BAR")
4752
})
4853
res.Assert(t, icmd.Expected{Out: "-r--r--r-- 1 1005 root"})
4954
})
5055
t.Run("secret uid:gid from user", func(t *testing.T) {
51-
res := icmd.RunCmd(c.NewDockerComposeCmd(t, "-f", "./fixtures/env-secret/compose.yaml", "run", "zot", "ls", "-al", "/var/run/secrets/bar"),
56+
res := c.RunDockerCmd(t, "version", "--format", "{{ .Server.Version }}")
57+
if strings.HasPrefix(res.Stdout(), "27.") {
58+
t.Skip("USER uid:gid is not supported")
59+
}
60+
res = icmd.RunCmd(c.NewDockerComposeCmd(t, "-f", "./fixtures/env-secret/compose.yaml", "run", "zot", "ls", "-al", "/var/run/secrets/bar"),
5261
func(cmd *icmd.Cmd) {
5362
cmd.Env = append(cmd.Env, "SECRET=BAR")
5463
})
5564
res.Assert(t, icmd.Expected{Out: "-r--r--r-- 1 1005 1005"})
5665
})
57-
5866
}
5967

6068
func TestSecretFromInclude(t *testing.T) {

0 commit comments

Comments
 (0)