Skip to content

Commit

Permalink
fix COMPOSE_PROJECT_NAME
Browse files Browse the repository at this point in the history
  • Loading branch information
lionello committed Jun 25, 2024
1 parent b940a9c commit 5b18e61
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 26 deletions.
26 changes: 11 additions & 15 deletions src/pkg/cli/client/byoc/baseclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package byoc
import (
"context"
"errors"
"fmt"
"os"
"slices"
"strings"
"sync"

Expand All @@ -16,6 +14,7 @@ import (
"github.com/DefangLabs/defang/src/pkg/types"
defangv1 "github.com/DefangLabs/defang/src/protos/io/defang/v1"
"github.com/compose-spec/compose-go/v2/consts"
"github.com/compose-spec/compose-go/v2/loader"
compose "github.com/compose-spec/compose-go/v2/types"
)

Expand Down Expand Up @@ -99,16 +98,23 @@ func (b *ByocBaseClient) LoadProject(ctx context.Context) (*compose.Project, err
}

func (b *ByocBaseClient) LoadProjectName(ctx context.Context) (string, error) {

proj, err := b.loadProjOnce()
if err == nil {
b.PulumiProject = proj.Name
return proj.Name, nil
}
if !errors.Is(err, types.ErrComposeFileNotFound) {
return "", err
}

// Get the project name from the environment (since it overrides the compose file anyway)
if projectName, ok := os.LookupEnv(consts.ComposeProjectName); ok {
if projectName != loader.NormalizeProjectName(projectName) {
return "", loader.InvalidProjectNameErr(projectName)
}
b.PulumiProject = projectName
return projectName, nil
}

// Get the list of projects from remote
projectNames, err := b.bootstrapLister.BootstrapList(ctx)
if err != nil {
Expand All @@ -119,24 +125,14 @@ func (b *ByocBaseClient) LoadProjectName(ctx context.Context) (string, error) {
}

if len(projectNames) == 0 {
return "", errors.New("no projects found")
return "", types.ErrComposeFileNotFound
}
if len(projectNames) == 1 {
term.Debug("Using default project: ", projectNames[0])
b.PulumiProject = projectNames[0]
return projectNames[0], nil
}

// When there are multiple projects, take a hint from COMPOSE_PROJECT_NAME environment variable if set
if projectName, ok := os.LookupEnv(consts.ComposeProjectName); ok {
if !slices.Contains(projectNames, projectName) {
return "", fmt.Errorf("project %q specified by COMPOSE_PROJECT_NAME not found", projectName)
}
term.Debug("Using project from COMPOSE_PROJECT_NAME environment variable:", projectNames[0])
b.PulumiProject = projectName
return projectName, nil
}

return "", errors.New("multiple projects found; please go to the correct project directory where the compose file is or set COMPOSE_PROJECT_NAME")
}

Expand Down
37 changes: 37 additions & 0 deletions src/pkg/cli/client/byoc/baseclient_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package byoc

import (
"context"
"testing"

"github.com/DefangLabs/defang/src/pkg/cli/client"
"github.com/DefangLabs/defang/src/pkg/cli/compose"
"github.com/compose-spec/compose-go/v2/loader"
)

type dummyLister struct{}

func (dummyLister) BootstrapList(context.Context) ([]string, error) {
return nil, nil
}

func TestLoadProjectName(t *testing.T) {
t.Run("no compose file but COMPOSE_PROJECT_NAME set", func(t *testing.T) {
t.Setenv("COMPOSE_PROJECT_NAME", "asdf")
client := NewByocBaseClient(context.Background(), client.GrpcClient{Loader: compose.Loader{}}, "project", dummyLister{})
_, err := client.LoadProjectName(context.Background())
if err != nil {
t.Fatalf("LoadProjectName() failed: %v", err)
}
})

t.Run("invalied COMPOSE_PROJECT_NAME", func(t *testing.T) {
t.Setenv("COMPOSE_PROJECT_NAME", "as df")
client := NewByocBaseClient(context.Background(), client.GrpcClient{Loader: compose.Loader{}}, "project", dummyLister{})
_, err := client.LoadProjectName(context.Background())
expected := loader.InvalidProjectNameErr("as df")
if err.Error() != expected.Error() {
t.Fatalf("LoadProjectName() failed: expected %v, got: %v", expected, err)
}
})
}
14 changes: 5 additions & 9 deletions src/pkg/cli/compose/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/DefangLabs/defang/src/pkg/term"
"github.com/DefangLabs/defang/src/pkg/types"
"github.com/compose-spec/compose-go/v2/cli"
"github.com/compose-spec/compose-go/v2/consts"
compose "github.com/compose-spec/compose-go/v2/types"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
Expand All @@ -24,7 +25,7 @@ func (c Loader) LoadCompose(ctx context.Context) (*compose.Project, error) {
if err != nil {
return nil, err
}
term.Debug("Loading compose file", composeFilePath)
term.Debugf("Loading compose file %q", composeFilePath)
workDir := filepath.Dir(composeFilePath)

// Compose-go uses the logrus logger, so we need to configure it to be more like our own logger
Expand All @@ -35,11 +36,6 @@ func (c Loader) LoadCompose(ctx context.Context) (*compose.Project, error) {
return nil, err
}

// HACK: We do not want to include all the os environment variables, only COMPOSE_PROJECT_NAME
if envProjName, ok := os.LookupEnv("COMPOSE_PROJECT_NAME"); ok {
projOpts.Environment["COMPOSE_PROJECT_NAME"] = envProjName
}

project, err := projOpts.LoadProject(ctx)
if err != nil {
return nil, err
Expand Down Expand Up @@ -94,10 +90,10 @@ func getDefaultProjectOptions(workingDir string, extraOpts ...cli.ProjectOptions
// read dot env file to populate project environment
cli.WithDotEnv,
// get compose file path set by COMPOSE_FILE
cli.WithConfigFileEnv,
// cli.WithConfigFileEnv, not used as we ignore os.Environment
// if none was selected, get default compose.yaml file from current dir or parent folder
cli.WithDefaultConfigPath,
// cli.WithName(o.ProjectName)
// cli.WithDefaultConfigPath, NO: this ends up picking the "first" when more than one file is found
cli.WithName(os.Getenv(consts.ComposeProjectName)), // HACK: We do not want to include all the os environment variables, only COMPOSE_PROJECT_NAME

// Calling the 2 functions below the 2nd time as the loaded env in first call modifies the behavior of the 2nd call
// .. and then, a project directory != PWD maybe has been set so let's load .env file
Expand Down
6 changes: 4 additions & 2 deletions src/pkg/types/error.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package types

import "errors"
import (
"github.com/compose-spec/compose-go/v2/errdefs"
)

var ErrComposeFileNotFound = errors.New("no compose file found")
var ErrComposeFileNotFound = errdefs.ErrNotFound

0 comments on commit 5b18e61

Please sign in to comment.