mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
volumes: error when using relative volumes sources in compose (#353)
Signed-off-by: Miek Gieben <miek@miek.nl> Co-authored-by: Pasha Sviderski <me@psviderski.name>
This commit is contained in:
co-authored by
Pasha Sviderski
parent
73d515bb40
commit
cffa03007b
@@ -22,6 +22,7 @@ var registerComposeOverrides sync.Once
|
||||
func LoadProject(ctx context.Context, paths []string, opts ...composecli.ProjectOptionsFn) (*types.Project, error) {
|
||||
registerComposeOverrides.Do(func() {
|
||||
transform.RegisterDefaultValue("services.*.deploy.update_config", setUpdateConfigDefaults)
|
||||
transform.RegisterDefaultValue("services.*.volumes.*.source", checkRelativeVolumeMount)
|
||||
})
|
||||
|
||||
defaultOpts := []composecli.ProjectOptionsFn{
|
||||
@@ -119,3 +120,20 @@ func setUpdateConfigDefaults(data any, _ tree.Path, _ bool) (any, error) {
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// checkRelativeVolumeMount check if a volume mount uses a relative path.
|
||||
func checkRelativeVolumeMount(data any, _ tree.Path, _ bool) (any, error) {
|
||||
source, ok := data.(string)
|
||||
if !ok || filepath.IsAbs(source) {
|
||||
return data, nil
|
||||
}
|
||||
// Only check actual paths, not volumes _names_
|
||||
if strings.HasPrefix(source, ".") || strings.HasPrefix(source, "~") {
|
||||
// uc run also warns against this
|
||||
return nil, fmt.Errorf("invalid volume mount: bind mount source '%s' is relative. If you intended to pass a host "+
|
||||
"directory or file, use absolute path, or configs might be better suited for this use case. "+
|
||||
"See https://uncloud.run/docs/concepts/configs", source)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ REDIS_URL=redis://localhost:6379
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoadProject_Unsupported checks that unsupported features lead to warnings.
|
||||
// TestLoadProject_Unsupported checks that unsupported features lead to warnings or errors.
|
||||
func TestLoadProject_Unsupported(t *testing.T) {
|
||||
// captureStderr runs fn while capturing stderr output and returns what was written.
|
||||
captureStderr := func(t *testing.T, fn func()) string {
|
||||
@@ -214,6 +214,7 @@ func TestLoadProject_Unsupported(t *testing.T) {
|
||||
composeYAML string
|
||||
warnCount int
|
||||
warnContains []string
|
||||
shouldErr bool
|
||||
}{
|
||||
{
|
||||
name: "unsupported dns",
|
||||
@@ -296,12 +297,40 @@ networks:
|
||||
`,
|
||||
warnCount: 0,
|
||||
},
|
||||
{
|
||||
name: "relative volume sources",
|
||||
composeYAML: `services:
|
||||
app:
|
||||
image: myapp:latest
|
||||
volumes:
|
||||
- ./mypath/conf:/conf:ro
|
||||
- data:/var/lib/data
|
||||
|
||||
volumes:
|
||||
data:
|
||||
`,
|
||||
shouldErr: true,
|
||||
},
|
||||
{
|
||||
name: "home-relative volume source",
|
||||
composeYAML: `services:
|
||||
app:
|
||||
image: myapp:latest
|
||||
volumes:
|
||||
- ~/conf:/conf:ro
|
||||
`,
|
||||
shouldErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stderr := captureStderr(t, func() {
|
||||
_, err := LoadProjectFromContent(context.Background(), tt.composeYAML)
|
||||
if tt.shouldErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user