mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
feat(secrets): initial support for 'x-command' and 'driver: exec' secrets, referenced as secret://name in environment (#403)
This commit is contained in:
@@ -23,6 +23,7 @@ func LoadProject(ctx context.Context, paths []string, opts ...composecli.Project
|
||||
registerComposeOverrides.Do(func() {
|
||||
transform.RegisterDefaultValue("services.*.deploy.update_config", setUpdateConfigDefaults)
|
||||
transform.RegisterDefaultValue("services.*.volumes.*.source", checkRelativeVolumeMount)
|
||||
transform.RegisterDefaultValue("secrets.*", expandSecretCommandExtension)
|
||||
})
|
||||
|
||||
defaultOpts := []composecli.ProjectOptionsFn{
|
||||
@@ -69,6 +70,11 @@ func LoadProject(ctx context.Context, paths []string, opts ...composecli.Project
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Validate secrets and clear the transient 'external' marker set on command secrets during loading.
|
||||
if err = validateSecrets(project); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, err = range validateServicesFeatures(project) {
|
||||
tui.PrintWarning(err.Error())
|
||||
}
|
||||
@@ -137,3 +143,46 @@ func checkRelativeVolumeMount(data any, _ tree.Path, _ bool) (any, error) {
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// expandSecretCommandExtension expands the 'x-command' secret shorthand to the long form 'driver: exec'. It also marks
|
||||
// driver-based secrets external so they pass compose-go's consistency check, which requires 'file' or 'environment'
|
||||
// for non-external secrets. User-defined external secrets are not allowed. validateSecrets clears the 'external' marker
|
||||
// after loading.
|
||||
func expandSecretCommandExtension(data any, p tree.Path, _ bool) (any, error) {
|
||||
secret, ok := data.(map[string]any)
|
||||
if !ok {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
name := p.Last()
|
||||
// We don't have a standalone secret entity in a cluster so external secrets don't make sense. Fail on any
|
||||
// user-defined external secrets here so that we can be sure only driver-based secrets will be marked as external.
|
||||
if ext, ok := secret["external"].(bool); ok && ext {
|
||||
return nil, fmt.Errorf("secret '%s': external secrets are not supported", name)
|
||||
}
|
||||
|
||||
if command, ok := secret[SecretCommandExtensionKey]; ok {
|
||||
cmd, ok := command.(string)
|
||||
if !ok || cmd == "" {
|
||||
return nil, fmt.Errorf("secret '%s': '%s' must be a non-empty string", name, SecretCommandExtensionKey)
|
||||
}
|
||||
if secret["driver"] != nil || secret["driver_opts"] != nil {
|
||||
return nil, fmt.Errorf("secret '%s': '%s' cannot be combined with 'driver' or 'driver_opts'",
|
||||
name, SecretCommandExtensionKey)
|
||||
}
|
||||
if secret["file"] != nil || secret["environment"] != nil {
|
||||
return nil, fmt.Errorf("secret '%s': '%s' cannot be combined with 'file' or 'environment'",
|
||||
name, SecretCommandExtensionKey)
|
||||
}
|
||||
|
||||
delete(secret, SecretCommandExtensionKey)
|
||||
secret["driver"] = secretExecDriver
|
||||
secret["driver_opts"] = map[string]string{"command": cmd}
|
||||
}
|
||||
|
||||
if secret["driver"] != nil && secret["file"] == nil && secret["environment"] == nil {
|
||||
secret["external"] = true
|
||||
}
|
||||
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user