Skip to content

Commit 0e8d665

Browse files
ndeloofglours
authored andcommitted
let resource loader compute a (possibly) relative path
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 466ad84 commit 0e8d665

File tree

6 files changed

+66
-11
lines changed

6 files changed

+66
-11
lines changed

loader/extends.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
"github.com/compose-spec/compose-go/v2/types"
2727
)
2828

29-
func ApplyExtends(ctx context.Context, dict map[string]any, workingdir string, opts *Options, tracker *cycleTracker, post ...PostProcessor) error {
29+
func ApplyExtends(ctx context.Context, dict map[string]any, opts *Options, tracker *cycleTracker, post ...PostProcessor) error {
3030
a, ok := dict["services"]
3131
if !ok {
3232
return nil
@@ -71,14 +71,15 @@ func ApplyExtends(ctx context.Context, dict map[string]any, workingdir string, o
7171
if err != nil {
7272
return err
7373
}
74-
relworkingdir := filepath.Dir(local)
75-
if !filepath.IsAbs(local) {
76-
relworkingdir, err = filepath.Rel(workingdir, relworkingdir)
77-
if err != nil {
78-
return err
79-
}
80-
}
74+
localdir := filepath.Dir(local)
75+
relworkingdir := loader.Dir(path)
76+
8177
extendsOpts := opts.clone()
78+
extendsOpts.ResourceLoaders = append([]ResourceLoader{}, opts.ResourceLoaders...)
79+
// replace localResourceLoader with a new flavour, using extended file base path
80+
extendsOpts.ResourceLoaders[len(opts.ResourceLoaders)-1] = localResourceLoader{
81+
WorkingDir: localdir,
82+
}
8283
extendsOpts.ResolvePaths = true
8384
extendsOpts.SkipNormalization = true
8485
extendsOpts.SkipConsistencyCheck = true

loader/extends_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,30 @@ services:
115115
assert.NilError(t, err)
116116
assert.Equal(t, p.Services["test"].Ulimits["nproc"].Single, 65535)
117117
}
118+
119+
func TestExtendsRelativePath(t *testing.T) {
120+
yaml := `
121+
name: test-extends-port
122+
services:
123+
test:
124+
extends:
125+
file: testdata/extends/base.yaml
126+
service: with-build
127+
`
128+
abs, err := filepath.Abs(".")
129+
assert.NilError(t, err)
130+
131+
p, err := LoadWithContext(context.Background(), types.ConfigDetails{
132+
ConfigFiles: []types.ConfigFile{
133+
{
134+
Content: []byte(yaml),
135+
Filename: "(inline)",
136+
},
137+
},
138+
WorkingDir: abs,
139+
}, func(options *Options) {
140+
options.ResolvePaths = false
141+
})
142+
assert.NilError(t, err)
143+
assert.Equal(t, p.Services["test"].Build.Context, filepath.Join("testdata", "extends"))
144+
}

loader/loader.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ type ResourceLoader interface {
8383
Accept(path string) bool
8484
// Load returns the path to a local copy of remote resource identified by `path`.
8585
Load(ctx context.Context, path string) (string, error)
86+
// Dir computes path to resource"s parent folder, made relative if possible
87+
Dir(path string) string
8688
}
8789

8890
type localResourceLoader struct {
@@ -105,6 +107,15 @@ func (l localResourceLoader) Load(_ context.Context, p string) (string, error) {
105107
return l.abs(p), nil
106108
}
107109

110+
func (l localResourceLoader) Dir(path string) string {
111+
path = l.abs(filepath.Dir(path))
112+
rel, err := filepath.Rel(l.WorkingDir, path)
113+
if err != nil {
114+
return path
115+
}
116+
return rel
117+
}
118+
108119
func (o *Options) clone() *Options {
109120
return &Options{
110121
SkipValidation: o.SkipValidation,
@@ -313,7 +324,7 @@ func loadYamlModel(ctx context.Context, config types.ConfigDetails, opts *Option
313324
fixEmptyNotNull(cfg)
314325

315326
if !opts.SkipExtends {
316-
err = ApplyExtends(fctx, cfg, config.WorkingDir, opts, ct, processors...)
327+
err = ApplyExtends(fctx, cfg, opts, ct, processors...)
317328
if err != nil {
318329
return err
319330
}

loader/loader_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2636,15 +2636,23 @@ func (c customLoader) Accept(s string) bool {
26362636
return strings.HasPrefix(s, c.prefix+":")
26372637
}
26382638

2639+
func (c customLoader) path(s string) string {
2640+
return filepath.Join("testdata", c.prefix, s[len(c.prefix)+1:])
2641+
}
2642+
26392643
func (c customLoader) Load(_ context.Context, s string) (string, error) {
2640-
path := filepath.Join("testdata", c.prefix, s[len(c.prefix)+1:])
2644+
path := c.path(s)
26412645
_, err := os.Stat(path)
26422646
if err != nil {
26432647
return "", err
26442648
}
26452649
return filepath.Abs(path)
26462650
}
26472651

2652+
func (c customLoader) Dir(s string) string {
2653+
return filepath.Dir(c.path(s))
2654+
}
2655+
26482656
func TestLoadWithRemoteResources(t *testing.T) {
26492657
config := buildConfigDetails(`
26502658
name: test-remote-resources

loader/testdata/extends/base.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ services:
1616
nofile:
1717
soft: 20000
1818
hard: 40000
19-
19+
20+
with-build:
21+
extends:
22+
file: sibling.yaml
23+
service: test
24+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
services:
2+
test:
3+
build: .

0 commit comments

Comments
 (0)