Repository: compose-spec/compose-go
Pull request #84 (2020-11-26 11:41:31)

Adding compose files passed as cmd options in project struct 
Used to set runtime labels

Note: docker-compose runtime labels include filenames as specified by users in the command line, or default compose names, not absolute filenames.

Signed-off-by: Guillaume Tardif <guillaume.tardif@docker.com>


Patch:
diff --git a/cli/options.go b/cli/options.go
index 3817109..dfecf98 100644
--- a/cli/options.go
+++ b/cli/options.go
@@ -152,7 +152,7 @@ func (o ProjectOptions) GetWorkingDir() (string, error) {
 
 // ProjectFromOptions load a compose project based on command line options
 func ProjectFromOptions(options *ProjectOptions) (*types.Project, error) {
-	configPaths, err := getConfigPathsFromOptions(options)
+	configPaths, specifiedComposeFiles, err := getConfigPathsFromOptions(options)
 	if err != nil {
 		return nil, err
 	}
@@ -183,21 +183,27 @@ func ProjectFromOptions(options *ProjectOptions) (*types.Project, error) {
 	}
 	options.loadOptions = append(options.loadOptions, nameLoadOpt)
 
-	return loader.Load(types.ConfigDetails{
+	project, err := loader.Load(types.ConfigDetails{
 		ConfigFiles: configs,
 		WorkingDir:  workingDir,
 		Environment: options.Environment,
 	}, options.loadOptions...)
+	if err != nil {
+		return nil, err
+	}
+
+	project.ComposeFiles = specifiedComposeFiles
+	return project, nil
 }
 
 // getConfigPathsFromOptions retrieves the config files for project based on project options
-func getConfigPathsFromOptions(options *ProjectOptions) ([]string, error) {
+func getConfigPathsFromOptions(options *ProjectOptions) ([]string, []string, error) {
 	paths := []string{}
 	pwd := options.WorkingDir
 	if pwd == "" {
 		wd, err := os.Getwd()
 		if err != nil {
-			return nil, err
+			return nil, nil, err
 		}
 		pwd = wd
 	}
@@ -212,11 +218,11 @@ func getConfigPathsFromOptions(options *ProjectOptions) ([]string, error) {
 				f = filepath.Join(pwd, f)
 			}
 			if _, err := os.Stat(f); err != nil {
-				return nil, err
+				return nil, nil, err
 			}
 			paths = append(paths, f)
 		}
-		return paths, nil
+		return paths, options.ConfigPaths, nil
 	}
 
 	sep := os.Getenv(ComposeFileSeparator)
@@ -225,7 +231,7 @@ func getConfigPathsFromOptions(options *ProjectOptions) ([]string, error) {
 	}
 	f := os.Getenv(ComposeFilePath)
 	if f != "" {
-		return strings.Split(f, sep), nil
+		return strings.Split(f, sep), strings.Split(f, sep), nil
 	}
 
 	for {
@@ -242,11 +248,11 @@ func getConfigPathsFromOptions(options *ProjectOptions) ([]string, error) {
 				logrus.Warnf("Found multiple config files with supported names: %s", strings.Join(candidates, ", "))
 				logrus.Warnf("Using %s", winner)
 			}
-			return []string{winner}, nil
+			return []string{winner}, []string{winner}, nil
 		}
 		parent := filepath.Dir(pwd)
 		if parent == pwd {
-			return nil, errors.Wrap(errdefs.ErrNotFound, "can't find a suitable configuration file in this directory or any parent")
+			return nil, nil, errors.Wrap(errdefs.ErrNotFound, "can't find a suitable configuration file in this directory or any parent")
 		}
 		pwd = parent
 	}
diff --git a/types/project.go b/types/project.go
index 740cd08..b41c301 100644
--- a/types/project.go
+++ b/types/project.go
@@ -25,14 +25,15 @@ import (
 
 // Project is the result of loading a set of compose files
 type Project struct {
-	Name       string
-	WorkingDir string
-	Services   Services               `json:"services"`
-	Networks   Networks               `yaml:",omitempty" json:"networks,omitempty"`
-	Volumes    Volumes                `yaml:",omitempty" json:"volumes,omitempty"`
-	Secrets    Secrets                `yaml:",omitempty" json:"secrets,omitempty"`
-	Configs    Configs                `yaml:",omitempty" json:"configs,omitempty"`
-	Extensions map[string]interface{} `yaml:",inline" json:"-"`
+	Name         string
+	WorkingDir   string
+	Services     Services               `json:"services"`
+	Networks     Networks               `yaml:",omitempty" json:"networks,omitempty"`
+	Volumes      Volumes                `yaml:",omitempty" json:"volumes,omitempty"`
+	Secrets      Secrets                `yaml:",omitempty" json:"secrets,omitempty"`
+	Configs      Configs                `yaml:",omitempty" json:"configs,omitempty"`
+	Extensions   map[string]interface{} `yaml:",inline" json:"-"`
+	ComposeFiles []string               `yaml:",omitempty" json:"composefiles,omitempty"`
 }
 
 // ServiceNames return names for all services in this Compose config


Test patch:
diff --git a/cli/options_test.go b/cli/options_test.go
index 9459307..6d7656e 100644
--- a/cli/options_test.go
+++ b/cli/options_test.go
@@ -18,6 +18,7 @@ package cli
 
 import (
 	"os"
+	"path/filepath"
 	"testing"
 
 	"gotest.tools/v3/assert"
@@ -64,6 +65,25 @@ func TestProjectFromSetOfFiles(t *testing.T) {
 	assert.Equal(t, service.Image, "haproxy")
 }
 
+func TestProjectComposefilesFromSetOfFiles(t *testing.T) {
+	opts, err := NewProjectOptions([]string{}, WithWorkingDirectory("testdata/simple/"), WithName("my_project"))
+	assert.NilError(t, err)
+	p, err := ProjectFromOptions(opts)
+	assert.NilError(t, err)
+	assert.DeepEqual(t, p.ComposeFiles, []string{filepath.Join("testdata", "simple", "compose.yaml")})
+}
+
+func TestProjectComposefilesFromWorkingDir(t *testing.T) {
+	opts, err := NewProjectOptions([]string{
+		"testdata/simple/compose.yaml",
+		"testdata/simple/compose-with-overrides.yaml",
+	}, WithName("my_project"))
+	assert.NilError(t, err)
+	p, err := ProjectFromOptions(opts)
+	assert.NilError(t, err)
+	assert.DeepEqual(t, p.ComposeFiles, []string{"testdata/simple/compose.yaml", "testdata/simple/compose-with-overrides.yaml"})
+}
+
 func TestProjectWithDotEnv(t *testing.T) {
 	opts, err := NewProjectOptions([]string{
 		"testdata/simple/compose-with-variables.yaml",