diff --git a/pkg/compose/create.go b/pkg/compose/create.go index 4c3e1099b..7b9d65262 100644 --- a/pkg/compose/create.go +++ b/pkg/compose/create.go @@ -288,6 +288,12 @@ func (s *composeService) getCreateConfigs(ctx context.Context, return createConfigs{}, err } + // CONFIGS and SECRETS + err = checkContainerConfigsSecrets(*p, service) + if err != nil { + return createConfigs{}, err + } + // NETWORKING links, err := s.getLinks(ctx, p.Name, service, number) if err != nil { @@ -915,128 +921,79 @@ func fillBindMounts(p types.Project, s types.ServiceConfig, m map[string]mount.M m[bindMount.Target] = bindMount } - secrets, err := buildContainerSecretMounts(p, s) - if err != nil { - return nil, err - } - for _, s := range secrets { - if _, found := m[s.Target]; found { - continue - } - m[s.Target] = s - } - - configs, err := buildContainerConfigMounts(p, s) - if err != nil { - return nil, err - } - for _, c := range configs { - if _, found := m[c.Target]; found { - continue - } - m[c.Target] = c - } return m, nil } -func buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) { - var mounts = map[string]mount.Mount{} +func checkContainerConfigsSecrets(p types.Project, s types.ServiceConfig) error { + err := checkContainerConfigs(p, s) + if err != nil { + return err + } - configsBaseDir := "/" + err = checkContainerSecrets(p, s) + if err != nil { + return err + } + + return nil +} + +func checkContainerConfigs(p types.Project, s types.ServiceConfig) error { for _, config := range s.Configs { - target := config.Target - if config.Target == "" { - target = configsBaseDir + config.Source - } else if !isAbsTarget(config.Target) { - target = configsBaseDir + config.Target - } - if config.UID != "" || config.GID != "" || config.Mode != nil { logrus.Warn("config `uid`, `gid` and `mode` are not supported, they will be ignored") } definedConfig := p.Configs[config.Source] if definedConfig.External { - return nil, fmt.Errorf("unsupported external config %s", definedConfig.Name) + return fmt.Errorf("unsupported external config %s", definedConfig.Name) } if definedConfig.Driver != "" { - return nil, errors.New("Docker Compose does not support configs.*.driver") + return errors.New("Docker Compose does not support configs.*.driver") } if definedConfig.TemplateDriver != "" { - return nil, errors.New("Docker Compose does not support configs.*.template_driver") + return errors.New("Docker Compose does not support configs.*.template_driver") } - if definedConfig.Environment != "" || definedConfig.Content != "" { + if definedConfig.File != "" { + _, err := os.Stat(definedConfig.File) + if err != nil { + return fmt.Errorf("error with source file of config %s: %s", definedConfig.Name, err.Error()) + } continue } - - bindMount, err := buildMount(p, types.ServiceVolumeConfig{ - Type: types.VolumeTypeBind, - Source: definedConfig.File, - Target: target, - ReadOnly: true, - }) - if err != nil { - return nil, err - } - mounts[target] = bindMount } - values := make([]mount.Mount, 0, len(mounts)) - for _, v := range mounts { - values = append(values, v) - } - return values, nil + return nil } -func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) { - var mounts = map[string]mount.Mount{} - - secretsDir := "/run/secrets/" +func checkContainerSecrets(p types.Project, s types.ServiceConfig) error { for _, secret := range s.Secrets { - target := secret.Target - if secret.Target == "" { - target = secretsDir + secret.Source - } else if !isAbsTarget(secret.Target) { - target = secretsDir + secret.Target - } - if secret.UID != "" || secret.GID != "" || secret.Mode != nil { logrus.Warn("secrets `uid`, `gid` and `mode` are not supported, they will be ignored") } definedSecret := p.Secrets[secret.Source] if definedSecret.External { - return nil, fmt.Errorf("unsupported external secret %s", definedSecret.Name) + return fmt.Errorf("unsupported external secret %s", definedSecret.Name) } if definedSecret.Driver != "" { - return nil, errors.New("Docker Compose does not support secrets.*.driver") + return errors.New("Docker Compose does not support secrets.*.driver") } if definedSecret.TemplateDriver != "" { - return nil, errors.New("Docker Compose does not support secrets.*.template_driver") + return errors.New("Docker Compose does not support secrets.*.template_driver") } - if definedSecret.Environment != "" { + if definedSecret.File != "" { + _, err := os.Stat(definedSecret.File) + if err != nil { + return fmt.Errorf("error with source file of secret %s: %s", definedSecret.Name, err.Error()) + } continue } - - mnt, err := buildMount(p, types.ServiceVolumeConfig{ - Type: types.VolumeTypeBind, - Source: definedSecret.File, - Target: target, - ReadOnly: true, - }) - if err != nil { - return nil, err - } - mounts[target] = mnt } - values := make([]mount.Mount, 0, len(mounts)) - for _, v := range mounts { - values = append(values, v) - } - return values, nil + return nil } func isAbsTarget(p string) bool { diff --git a/pkg/compose/secrets.go b/pkg/compose/secrets.go index 4ba49eed4..5b3e5ad66 100644 --- a/pkg/compose/secrets.go +++ b/pkg/compose/secrets.go @@ -21,6 +21,7 @@ import ( "bytes" "context" "fmt" + "os" "strconv" "time" @@ -31,7 +32,23 @@ import ( func (s *composeService) injectSecrets(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error { for _, config := range service.Secrets { file := project.Secrets[config.Source] - if file.Environment == "" { + content := file.Content + + if file.Environment != "" { + env, ok := project.Environment[file.Environment] + if !ok { + return fmt.Errorf("environment variable %q required by file %q is not set", file.Environment, file.Name) + } + content = env + } else if file.File != "" { + data, err := os.ReadFile(file.File) + if err != nil { + return err + } + content = string(data) + } + + if content == "" { continue } @@ -41,11 +58,7 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje config.Target = "/run/secrets/" + config.Target } - env, ok := project.Environment[file.Environment] - if !ok { - return fmt.Errorf("environment variable %q required by file %q is not set", file.Environment, file.Name) - } - b, err := createTar(env, types.FileReferenceConfig(config)) + b, err := createTar(content, types.FileReferenceConfig(config)) if err != nil { return err } @@ -64,13 +77,21 @@ func (s *composeService) injectConfigs(ctx context.Context, project *types.Proje for _, config := range service.Configs { file := project.Configs[config.Source] content := file.Content + if file.Environment != "" { env, ok := project.Environment[file.Environment] if !ok { return fmt.Errorf("environment variable %q required by file %q is not set", file.Environment, file.Name) } content = env + } else if file.File != "" { + data, err := os.ReadFile(file.File) + if err != nil { + return err + } + content = string(data) } + if content == "" { continue } diff --git a/pkg/e2e/volumes_test.go b/pkg/e2e/volumes_test.go index 2c9d47c25..7b679051b 100644 --- a/pkg/e2e/volumes_test.go +++ b/pkg/e2e/volumes_test.go @@ -52,7 +52,7 @@ func TestLocalComposeVolume(t *testing.T) { res := c.RunDockerCmd(t, "inspect", "compose-e2e-volume-nginx2-1", "--format", "{{ json .Mounts }}") output := res.Stdout() assert.Assert(t, strings.Contains(output, `"Destination":"/usr/src/app/node_modules","Driver":"local","Mode":"z","RW":true,"Propagation":""`), output) - assert.Assert(t, strings.Contains(output, `"Destination":"/myconfig","Mode":"","RW":false,"Propagation":"rprivate"`), output) + assert.Assert(t, !strings.Contains(output, `"Destination":"/myconfig","Mode":"","RW":false,"Propagation":"rprivate"`), output) }) t.Run("check config content", func(t *testing.T) {