All checks were successful
continuous-integration/drone/push Build is passing
This implements proper modifier support in the env file using this new fork of the godotenv library. The modifier implementation is quite basic for but can be improved later if needed. See this commit for the actual implementation. Because we are now using proper modifer parsing, it does not affect the parsing of value, so this is possible again: ``` MY_VAR="#foo" ``` Closes coop-cloud/organising#535
276 lines
6.3 KiB
Go
276 lines
6.3 KiB
Go
package config_test
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"reflect"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
|
|
"coopcloud.tech/abra/pkg/config"
|
|
"coopcloud.tech/abra/pkg/recipe"
|
|
)
|
|
|
|
var (
|
|
TestFolder = os.ExpandEnv("$PWD/../../tests/resources/test_folder")
|
|
ValidAbraConf = os.ExpandEnv("$PWD/../../tests/resources/valid_abra_config")
|
|
)
|
|
|
|
// make sure these are in alphabetical order
|
|
var (
|
|
TFolders = []string{"folder1", "folder2"}
|
|
TFiles = []string{"bar.env", "foo.env"}
|
|
)
|
|
|
|
var (
|
|
AppName = "ecloud"
|
|
ServerName = "evil.corp"
|
|
)
|
|
|
|
var ExpectedAppEnv = config.AppEnv{
|
|
"DOMAIN": "ecloud.evil.corp",
|
|
"RECIPE": "ecloud",
|
|
}
|
|
|
|
var ExpectedApp = config.App{
|
|
Name: AppName,
|
|
Recipe: ExpectedAppEnv["RECIPE"],
|
|
Domain: ExpectedAppEnv["DOMAIN"],
|
|
Env: ExpectedAppEnv,
|
|
Path: ExpectedAppFile.Path,
|
|
Server: ExpectedAppFile.Server,
|
|
}
|
|
|
|
var ExpectedAppFile = config.AppFile{
|
|
Path: path.Join(ValidAbraConf, "servers", ServerName, AppName+".env"),
|
|
Server: ServerName,
|
|
}
|
|
|
|
var ExpectedAppFiles = map[string]config.AppFile{
|
|
AppName: ExpectedAppFile,
|
|
}
|
|
|
|
func TestGetAllFoldersInDirectory(t *testing.T) {
|
|
folders, err := config.GetAllFoldersInDirectory(TestFolder)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(folders, TFolders) {
|
|
t.Fatalf("did not get expected folders. Expected: (%s), Got: (%s)", strings.Join(TFolders, ","), strings.Join(folders, ","))
|
|
}
|
|
}
|
|
|
|
func TestGetAllFilesInDirectory(t *testing.T) {
|
|
files, err := config.GetAllFilesInDirectory(TestFolder)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var fileNames []string
|
|
for _, file := range files {
|
|
fileNames = append(fileNames, file.Name())
|
|
}
|
|
if !reflect.DeepEqual(fileNames, TFiles) {
|
|
t.Fatalf("did not get expected files. Expected: (%s), Got: (%s)", strings.Join(TFiles, ","), strings.Join(fileNames, ","))
|
|
}
|
|
}
|
|
|
|
func TestReadEnv(t *testing.T) {
|
|
env, err := config.ReadEnv(ExpectedAppFile.Path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(env, ExpectedAppEnv) {
|
|
t.Fatalf(
|
|
"did not get expected application settings. Expected: DOMAIN=%s RECIPE=%s; Got: DOMAIN=%s RECIPE=%s",
|
|
ExpectedAppEnv["DOMAIN"],
|
|
ExpectedAppEnv["RECIPE"],
|
|
env["DOMAIN"],
|
|
env["RECIPE"],
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestReadAbraShEnvVars(t *testing.T) {
|
|
offline := true
|
|
r, err := recipe.Get("abra-test-recipe", offline)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, r.Name, "abra.sh")
|
|
abraShEnv, err := config.ReadAbraShEnvVars(abraShPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(abraShEnv) == 0 {
|
|
t.Error("at least one env var should be exported")
|
|
}
|
|
|
|
if _, ok := abraShEnv["INNER_FOO"]; ok {
|
|
t.Error("INNER_FOO should not be exported")
|
|
}
|
|
|
|
if _, ok := abraShEnv["INNER_BAZ"]; ok {
|
|
t.Error("INNER_BAZ should not be exported")
|
|
}
|
|
|
|
if _, ok := abraShEnv["OUTER_FOO"]; !ok {
|
|
t.Error("OUTER_FOO should be exported")
|
|
}
|
|
}
|
|
|
|
func TestReadAbraShCmdNames(t *testing.T) {
|
|
offline := true
|
|
r, err := recipe.Get("abra-test-recipe", offline)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, r.Name, "abra.sh")
|
|
cmdNames, err := config.ReadAbraShCmdNames(abraShPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(cmdNames) == 0 {
|
|
t.Error("at least one command name should be found")
|
|
}
|
|
|
|
expectedCmdNames := []string{"test_cmd", "test_cmd_args"}
|
|
for _, cmdName := range expectedCmdNames {
|
|
if !slices.Contains(cmdNames, cmdName) {
|
|
t.Fatalf("%s should have been found in %s", cmdName, abraShPath)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCheckEnv(t *testing.T) {
|
|
offline := true
|
|
r, err := recipe.Get("abra-test-recipe", offline)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample")
|
|
envSample, err := config.ReadEnv(envSamplePath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
app := config.App{
|
|
Name: "test-app",
|
|
Recipe: r.Name,
|
|
Domain: "example.com",
|
|
Env: envSample,
|
|
Path: "example.com.env",
|
|
Server: "example.com",
|
|
}
|
|
|
|
envVars, err := config.CheckEnv(app)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
for _, envVar := range envVars {
|
|
if !envVar.Present {
|
|
t.Fatalf("%s should be present", envVar.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCheckEnvError(t *testing.T) {
|
|
offline := true
|
|
r, err := recipe.Get("abra-test-recipe", offline)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample")
|
|
envSample, err := config.ReadEnv(envSamplePath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
delete(envSample, "DOMAIN")
|
|
|
|
app := config.App{
|
|
Name: "test-app",
|
|
Recipe: r.Name,
|
|
Domain: "example.com",
|
|
Env: envSample,
|
|
Path: "example.com.env",
|
|
Server: "example.com",
|
|
}
|
|
|
|
envVars, err := config.CheckEnv(app)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
for _, envVar := range envVars {
|
|
if envVar.Name == "DOMAIN" && envVar.Present {
|
|
t.Fatalf("%s should not be present", envVar.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEnvVarCommentsRemoved(t *testing.T) {
|
|
offline := true
|
|
r, err := recipe.Get("abra-test-recipe", offline)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample")
|
|
envSample, err := config.ReadEnv(envSamplePath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
envVar, exists := envSample["WITH_COMMENT"]
|
|
if !exists {
|
|
t.Fatal("WITH_COMMENT env var should be present in .env.sample")
|
|
}
|
|
|
|
if strings.Contains(envVar, "should be removed") {
|
|
t.Fatalf("comment from '%s' should be removed", envVar)
|
|
}
|
|
|
|
envVar, exists = envSample["SECRET_TEST_PASS_TWO_VERSION"]
|
|
if !exists {
|
|
t.Fatal("WITH_COMMENT env var should be present in .env.sample")
|
|
}
|
|
|
|
if strings.Contains(envVar, "length") {
|
|
t.Fatal("comment from env var SECRET_TEST_PASS_TWO_VERSION should have been removed")
|
|
}
|
|
}
|
|
|
|
func TestEnvVarModifiersIncluded(t *testing.T) {
|
|
offline := true
|
|
r, err := recipe.Get("abra-test-recipe", offline)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample")
|
|
envSample, modifiers, err := config.ReadEnvWithModifiers(envSamplePath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !strings.Contains(envSample["SECRET_TEST_PASS_TWO_VERSION"], "v1") {
|
|
t.Errorf("value should be 'v1', got: '%s'", envSample["SECRET_TEST_PASS_TWO_VERSION"])
|
|
}
|
|
if modifiers == nil || modifiers["SECRET_TEST_PASS_TWO_VERSION"] == nil {
|
|
t.Errorf("no modifiers included")
|
|
} else {
|
|
if modifiers["SECRET_TEST_PASS_TWO_VERSION"]["length"] != "10" {
|
|
t.Errorf("length modifier should be '10', got: '%s'", modifiers["SECRET_TEST_PASS_TWO_VERSION"]["length"])
|
|
}
|
|
}
|
|
}
|