fix: validate COMPOSE_FILE
See coop-cloud/organising#468. See coop-cloud/organising#376.
This commit is contained in:
parent
422c642949
commit
c646263e9e
@ -437,27 +437,56 @@ func GetAppStatuses(apps []App, MachineReadable bool) (map[string]map[string]str
|
|||||||
return statuses, nil
|
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
|
// 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
|
// don't already have an app) which should be merged into a composetypes.Config
|
||||||
// while respecting the COMPOSE_FILE env var.
|
// while respecting the COMPOSE_FILE env var.
|
||||||
func GetComposeFiles(recipe string, appEnv AppEnv) ([]string, error) {
|
func GetComposeFiles(recipe string, appEnv AppEnv) ([]string, error) {
|
||||||
var composeFiles []string
|
var composeFiles []string
|
||||||
|
|
||||||
if _, ok := appEnv["COMPOSE_FILE"]; !ok {
|
composeFileEnvVar, ok := appEnv["COMPOSE_FILE"]
|
||||||
logrus.Debug("no COMPOSE_FILE detected, loading compose.yml")
|
if !ok {
|
||||||
path := fmt.Sprintf("%s/%s/compose.yml", RECIPES_DIR, recipe)
|
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)
|
composeFiles = append(composeFiles, path)
|
||||||
return composeFiles, nil
|
return composeFiles, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
composeFileEnvVar := appEnv["COMPOSE_FILE"]
|
if !strings.Contains(composeFileEnvVar, ":") {
|
||||||
envVars := strings.Split(composeFileEnvVar, ":")
|
path := fmt.Sprintf("%s/%s/%s", RECIPES_DIR, recipe, composeFileEnvVar)
|
||||||
logrus.Debugf("COMPOSE_FILE detected (%s), loading %s", composeFileEnvVar, strings.Join(envVars, ", "))
|
if err := ensurePathExists(path); err != nil {
|
||||||
for _, file := range strings.Split(composeFileEnvVar, ":") {
|
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)
|
path := fmt.Sprintf("%s/%s/%s", RECIPES_DIR, recipe, file)
|
||||||
|
if err := ensurePathExists(path); err != nil {
|
||||||
|
return composeFiles, err
|
||||||
|
}
|
||||||
composeFiles = append(composeFiles, path)
|
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)
|
logrus.Debugf("retrieved %s configs for %s", strings.Join(composeFiles, ", "), recipe)
|
||||||
|
|
||||||
return composeFiles, nil
|
return composeFiles, nil
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
package config_test
|
package config_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"coopcloud.tech/abra/pkg/catalogue"
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"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) {
|
func TestNewApp(t *testing.T) {
|
||||||
app, err := config.NewApp(ExpectedAppEnv, AppName, ExpectedAppFile)
|
app, err := config.NewApp(ExpectedAppEnv, AppName, ExpectedAppFile)
|
||||||
if err != nil {
|
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)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -311,3 +311,20 @@ teardown(){
|
|||||||
|
|
||||||
_undeploy_app
|
_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
|
||||||
|
}
|
||||||
|
@ -26,19 +26,6 @@ teardown(){
|
|||||||
fi
|
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(){
|
setup(){
|
||||||
load "$PWD/tests/integration/helpers/common"
|
load "$PWD/tests/integration/helpers/common"
|
||||||
_common_setup
|
_common_setup
|
||||||
|
@ -40,3 +40,16 @@ _rm_app() {
|
|||||||
run $ABRA app remove "$TEST_APP_DOMAIN" --no-input
|
run $ABRA app remove "$TEST_APP_DOMAIN" --no-input
|
||||||
fi
|
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"
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user