diff --git a/pkg/config/app.go b/pkg/config/app.go index a6166e2e..7082db79 100644 --- a/pkg/config/app.go +++ b/pkg/config/app.go @@ -437,27 +437,56 @@ func GetAppStatuses(apps []App, MachineReadable bool) (map[string]map[string]str return statuses, nil } +// ensurePathExists ensures that a path exists. +func ensurePathExists(path string) error { + if _, err := os.Stat(path); err != nil && os.IsNotExist(err) { + return err + } + return nil +} + // GetComposeFiles gets the list of compose files for an app (or recipe if you // don't already have an app) which should be merged into a composetypes.Config // while respecting the COMPOSE_FILE env var. func GetComposeFiles(recipe string, appEnv AppEnv) ([]string, error) { var composeFiles []string - if _, ok := appEnv["COMPOSE_FILE"]; !ok { - logrus.Debug("no COMPOSE_FILE detected, loading compose.yml") + composeFileEnvVar, ok := appEnv["COMPOSE_FILE"] + if !ok { path := fmt.Sprintf("%s/%s/compose.yml", RECIPES_DIR, recipe) + if err := ensurePathExists(path); err != nil { + return composeFiles, err + } + logrus.Debugf("no COMPOSE_FILE detected, loading default: %s", path) composeFiles = append(composeFiles, path) return composeFiles, nil } - composeFileEnvVar := appEnv["COMPOSE_FILE"] - envVars := strings.Split(composeFileEnvVar, ":") - logrus.Debugf("COMPOSE_FILE detected (%s), loading %s", composeFileEnvVar, strings.Join(envVars, ", ")) - for _, file := range strings.Split(composeFileEnvVar, ":") { + if !strings.Contains(composeFileEnvVar, ":") { + path := fmt.Sprintf("%s/%s/%s", RECIPES_DIR, recipe, composeFileEnvVar) + if err := ensurePathExists(path); err != nil { + return composeFiles, err + } + logrus.Debugf("COMPOSE_FILE detected, loading %s", path) + composeFiles = append(composeFiles, path) + return composeFiles, nil + } + + numComposeFiles := strings.Count(composeFileEnvVar, ":") + 1 + envVars := strings.SplitN(composeFileEnvVar, ":", numComposeFiles) + if len(envVars) != numComposeFiles { + return composeFiles, fmt.Errorf("COMPOSE_FILE (=\"%s\") parsing failed?", composeFileEnvVar) + } + + for _, file := range envVars { path := fmt.Sprintf("%s/%s/%s", RECIPES_DIR, recipe, file) + if err := ensurePathExists(path); err != nil { + return composeFiles, err + } composeFiles = append(composeFiles, path) } + logrus.Debugf("COMPOSE_FILE detected (%s), loading %s", composeFileEnvVar, strings.Join(envVars, ", ")) logrus.Debugf("retrieved %s configs for %s", strings.Join(composeFiles, ", "), recipe) return composeFiles, nil diff --git a/pkg/config/app_test.go b/pkg/config/app_test.go index 5403ca59..dbf91c05 100644 --- a/pkg/config/app_test.go +++ b/pkg/config/app_test.go @@ -1,12 +1,22 @@ package config_test import ( + "fmt" "reflect" "testing" + "coopcloud.tech/abra/pkg/catalogue" "coopcloud.tech/abra/pkg/config" + "coopcloud.tech/abra/pkg/recipe" + "github.com/stretchr/testify/assert" ) +func setup(t *testing.T) { + if err := catalogue.EnsureCatalogue(); err != nil { + t.Fatal(err) + } +} + func TestNewApp(t *testing.T) { app, err := config.NewApp(ExpectedAppEnv, AppName, ExpectedAppFile) if err != nil { @@ -36,3 +46,74 @@ func TestGetApp(t *testing.T) { t.Fatalf("did not get expected app type. Expected: %s; Got: %s", app, ExpectedApp) } } + +func TestGetComposeFiles(t *testing.T) { + setup(t) + + offline := true + r, err := recipe.Get("abra-integration-test-recipe", offline) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + appEnv map[string]string + composeFiles []string + }{ + { + map[string]string{}, + []string{ + fmt.Sprintf("%s/%s/compose.yml", config.RECIPES_DIR, r.Name), + }, + }, + { + map[string]string{"COMPOSE_FILE": "compose.yml"}, + []string{ + fmt.Sprintf("%s/%s/compose.yml", config.RECIPES_DIR, r.Name), + }, + }, + { + map[string]string{"COMPOSE_FILE": "compose.extra_secret.yml"}, + []string{ + fmt.Sprintf("%s/%s/compose.extra_secret.yml", config.RECIPES_DIR, r.Name), + }, + }, + { + map[string]string{"COMPOSE_FILE": "compose.yml:compose.extra_secret.yml"}, + []string{ + fmt.Sprintf("%s/%s/compose.yml", config.RECIPES_DIR, r.Name), + fmt.Sprintf("%s/%s/compose.extra_secret.yml", config.RECIPES_DIR, r.Name), + }, + }, + } + + for _, test := range tests { + composeFiles, err := config.GetComposeFiles(r.Name, test.appEnv) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, composeFiles, test.composeFiles) + } +} + +func TestGetComposeFilesError(t *testing.T) { + setup(t) + + offline := true + r, err := recipe.Get("abra-integration-test-recipe", offline) + if err != nil { + t.Fatal(err) + } + + tests := []struct{ appEnv map[string]string }{ + {map[string]string{"COMPOSE_FILE": "compose.yml::compose.foo.yml"}}, + {map[string]string{"COMPOSE_FILE": "doesnt.exist.yml"}}, + } + + for _, test := range tests { + _, err := config.GetComposeFiles(r.Name, test.appEnv) + if err == nil { + t.Fatalf("should have failed: %v", test.appEnv) + } + } +} diff --git a/tests/integration/app_deploy.bats b/tests/integration/app_deploy.bats index 3f81d225..071c2728 100644 --- a/tests/integration/app_deploy.bats +++ b/tests/integration/app_deploy.bats @@ -311,3 +311,20 @@ teardown(){ _undeploy_app } + +# bats test_tags=slow +@test "COMPOSE_FILE with \$COMPOSE_FILE override works" { + run sed -i 's/#COMPOSE_FILE="$COMPOSE_FILE:compose.extra_env.yml"/COMPOSE_FILE="$COMPOSE_FILE:compose.extra_env.yml"/g' \ + "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" + assert_success + + # NOTE(d1): --chaos used to bypass versions and access compose.extra_env.yml + run $ABRA app deploy "$TEST_APP_DOMAIN" \ + --no-input --no-converge-checks --chaos + assert_success + assert_output --partial "compose.yml" + assert_output --partial "compose.extra_env.yml" + + _undeploy_app + _reset_app +} diff --git a/tests/integration/app_secret.bats b/tests/integration/app_secret.bats index 23451ad8..bd847a14 100644 --- a/tests/integration/app_secret.bats +++ b/tests/integration/app_secret.bats @@ -26,19 +26,6 @@ teardown(){ fi } -_reset_app(){ - run rm -rf "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" - assert_success - assert_not_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" - - run $ABRA app new "$TEST_RECIPE" \ - --no-input \ - --server "$TEST_SERVER" \ - --domain "$TEST_APP_DOMAIN" \ - assert_success - assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" -} - setup(){ load "$PWD/tests/integration/helpers/common" _common_setup diff --git a/tests/integration/helpers/app.bash b/tests/integration/helpers/app.bash index 17dbbc2f..ee3e30f6 100644 --- a/tests/integration/helpers/app.bash +++ b/tests/integration/helpers/app.bash @@ -40,3 +40,16 @@ _rm_app() { run $ABRA app remove "$TEST_APP_DOMAIN" --no-input fi } + +_reset_app(){ + run rm -rf "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" + assert_success + assert_not_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" + + run $ABRA app new "$TEST_RECIPE" \ + --no-input \ + --server "$TEST_SERVER" \ + --domain "$TEST_APP_DOMAIN" \ + assert_success + assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" +}