Skip to content

Commit a4da4da

Browse files
authored
Merge pull request #371 from ndeloof/extends
remove `extends` from model after service has been extended
2 parents 5713643 + ed19dca commit a4da4da

File tree

5 files changed

+24
-38
lines changed

5 files changed

+24
-38
lines changed

loader/loader.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -589,16 +589,17 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
589589
}
590590

591591
if serviceConfig.Extends != nil && !opts.SkipExtends {
592-
baseServiceName := *serviceConfig.Extends["service"]
592+
baseServiceName := serviceConfig.Extends.Service
593593
var baseService *types.ServiceConfig
594-
if file := serviceConfig.Extends["file"]; file == nil {
594+
file := serviceConfig.Extends.File
595+
if file == "" {
595596
baseService, err = loadServiceWithExtends(filename, baseServiceName, servicesDict, workingDir, lookupEnv, opts, ct)
596597
if err != nil {
597598
return nil, err
598599
}
599600
} else {
600601
// Resolve the path to the imported file, and load it.
601-
baseFilePath := absPath(workingDir, *file)
602+
baseFilePath := absPath(workingDir, file)
602603

603604
b, err := os.ReadFile(baseFilePath)
604605
if err != nil {
@@ -617,10 +618,10 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
617618
}
618619

619620
// Make paths relative to the importing Compose file. Note that we
620-
// make the paths relative to `*file` rather than `baseFilePath` so
621-
// that the resulting paths won't be absolute if `*file` isn't an
621+
// make the paths relative to `file` rather than `baseFilePath` so
622+
// that the resulting paths won't be absolute if `file` isn't an
622623
// absolute path.
623-
baseFileParent := filepath.Dir(*file)
624+
baseFileParent := filepath.Dir(file)
624625
if baseService.Build != nil {
625626
baseService.Build.Context = resolveBuildContextPath(baseFileParent, baseService.Build.Context)
626627
}
@@ -641,6 +642,7 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter
641642
if err != nil {
642643
return nil, err
643644
}
645+
serviceConfig.Extends = nil
644646
}
645647

646648
return serviceConfig, nil
@@ -1048,14 +1050,15 @@ var transformDependsOnConfig TransformerFunc = func(data interface{}) (interface
10481050
}
10491051
}
10501052

1051-
var transformExtendsConfig TransformerFunc = func(data interface{}) (interface{}, error) {
1052-
switch data.(type) {
1053+
var transformExtendsConfig TransformerFunc = func(value interface{}) (interface{}, error) {
1054+
switch value.(type) {
10531055
case string:
1054-
data = map[string]interface{}{
1055-
"service": data,
1056-
}
1056+
return map[string]interface{}{"service": value}, nil
1057+
case map[string]interface{}:
1058+
return value, nil
1059+
default:
1060+
return value, errors.Errorf("invalid type %T for extends", value)
10571061
}
1058-
return transformMappingOrListFunc("=", true)(data)
10591062
}
10601063

10611064
var transformServiceVolumeConfig TransformerFunc = func(data interface{}) (interface{}, error) {

loader/loader_test.go

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,19 +1934,10 @@ func TestLoadWithExtends(t *testing.T) {
19341934

19351935
expectedEnvFilePath := filepath.Join(extendsDir, "extra.env")
19361936

1937-
expectedExtendsPath := filepath.Join(
1938-
extendsDir,
1939-
"compose-test-extends-imported.yaml",
1940-
)
1941-
19421937
expServices := types.Services{
19431938
{
19441939
Name: "importer",
19451940
Image: "nginx",
1946-
Extends: types.ExtendsConfig{
1947-
"file": &expectedExtendsPath,
1948-
"service": strPtr("imported"),
1949-
},
19501941
Environment: types.MappingWithEquals{
19511942
"SOURCE": strPtr("extends"),
19521943
},
@@ -1979,24 +1970,13 @@ func TestLoadWithExtendsWithContextUrl(t *testing.T) {
19791970
actual, err := Load(configDetails)
19801971
assert.NilError(t, err)
19811972

1982-
expectedExtendsPath, err := filepath.Abs(
1983-
filepath.Join(
1984-
"testdata",
1985-
"compose-test-extends-with-context-url-imported.yaml",
1986-
),
1987-
)
1988-
assert.NilError(t, err)
19891973
expServices := types.Services{
19901974
{
19911975
Name: "importer-with-https-url",
19921976
Build: &types.BuildConfig{
19931977
Context: "https://github.com/docker/compose.git",
19941978
Dockerfile: "Dockerfile",
19951979
},
1996-
Extends: types.ExtendsConfig{
1997-
"file": &expectedExtendsPath,
1998-
"service": strPtr("imported-with-https-url"),
1999-
},
20001980
Environment: types.MappingWithEquals{},
20011981
Networks: map[string]*types.ServiceNetworkConfig{"default": nil},
20021982
Scale: 1,
@@ -2304,6 +2284,7 @@ volumes:
23042284

23052285
func TestLoadServiceExtension(t *testing.T) {
23062286
dict := `
2287+
name: test
23072288
services:
23082289
extension: # this name should be allowed
23092290
image: web

loader/normalize.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,8 @@ func Normalize(project *types.Project, resolvePaths bool) error {
9191
}
9292
s.Environment = s.Environment.Resolve(fn)
9393

94-
if extendFile := s.Extends["file"]; extendFile != nil && *extendFile != "" {
95-
p := absPath(project.WorkingDir, *extendFile)
96-
s.Extends["file"] = &p
94+
if s.Extends != nil && s.Extends.File != "" {
95+
s.Extends.File = absPath(project.WorkingDir, s.Extends.File)
9796
}
9897

9998
for _, link := range s.Links {

loader/testdata/subdir/compose-test-extends-imported.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ services:
22
imported:
33
image: nginx
44
env_file:
5-
- extra.env
5+
- ./extra.env # expected to be loaded relative to this file, not the extending one
66
volumes:
77
- /opt/data:/var/lib/mysql

types/types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ type ServiceConfig struct {
132132
Environment MappingWithEquals `yaml:",omitempty" json:"environment,omitempty"`
133133
EnvFile StringList `mapstructure:"env_file" yaml:"env_file,omitempty" json:"env_file,omitempty"`
134134
Expose StringOrNumberList `yaml:",omitempty" json:"expose,omitempty"`
135-
Extends ExtendsConfig `yaml:"extends,omitempty" json:"extends,omitempty"`
135+
Extends *ExtendsConfig `yaml:"extends,omitempty" json:"extends,omitempty"`
136136
ExternalLinks []string `mapstructure:"external_links" yaml:"external_links,omitempty" json:"external_links,omitempty"`
137137
ExtraHosts HostsList `mapstructure:"extra_hosts" yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"`
138138
GroupAdd []string `mapstructure:"group_add" yaml:"group_add,omitempty" json:"group_add,omitempty"`
@@ -1008,7 +1008,10 @@ type ServiceDependency struct {
10081008
Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"`
10091009
}
10101010

1011-
type ExtendsConfig MappingWithEquals
1011+
type ExtendsConfig struct {
1012+
File string `yaml:",omitempty" json:"file,omitempty"`
1013+
Service string `yaml:",omitempty" json:"service,omitempty"`
1014+
}
10121015

10131016
// SecretConfig for a secret
10141017
type SecretConfig FileObjectConfig

0 commit comments

Comments
 (0)