integreate new modifiers
continuous-integration/drone/pr Build is failing Details

This commit is contained in:
p4u1 2023-11-29 20:02:19 +01:00
parent 87ba622517
commit be89cdb39c
5 changed files with 86 additions and 32 deletions

View File

@ -108,7 +108,7 @@ var appNewCommand = cli.Command{
}
envSamplePath := path.Join(config.RECIPES_DIR, recipe.Name, ".env.sample")
secretsConfig, err := secret.ReadSecretsConfig(envSamplePath, composeFiles, recipe.Name)
secretsConfig, modifiers, err := secret.ReadSecretsConfig(envSamplePath, composeFiles, recipe.Name)
if err != nil {
return err
}
@ -122,7 +122,7 @@ var appNewCommand = cli.Command{
logrus.Fatal(err)
}
secrets, err = createSecrets(cl, secretsConfig, sanitisedAppName)
secrets, err = createSecrets(cl, secretsConfig, modifiers, sanitisedAppName)
if err != nil {
logrus.Fatal(err)
}
@ -168,14 +168,14 @@ var appNewCommand = cli.Command{
type AppSecrets map[string]string
// createSecrets creates all secrets for a new app.
func createSecrets(cl *dockerClient.Client, secretsConfig map[string]string, sanitisedAppName string) (AppSecrets, error) {
func createSecrets(cl *dockerClient.Client, secretsConfig map[string]string, modifiers map[string]map[string]string, sanitisedAppName string) (AppSecrets, error) {
// NOTE(d1): trim to match app.StackName() implementation
if len(sanitisedAppName) > 45 {
logrus.Debugf("trimming %s to %s to avoid runtime limits", sanitisedAppName, sanitisedAppName[:45])
sanitisedAppName = sanitisedAppName[:45]
}
secrets, err := secret.GenerateSecrets(cl, secretsConfig, sanitisedAppName, internal.NewAppServer)
secrets, err := secret.GenerateSecrets(cl, secretsConfig, modifiers, sanitisedAppName, internal.NewAppServer)
if err != nil {
return nil, err
}

View File

@ -87,7 +87,7 @@ var appSecretGenerateCommand = cli.Command{
logrus.Fatal(err)
}
secretsConfig, err := secret.ReadSecretsConfig(app.Path, composeFiles, app.Recipe)
secretsConfig, secretModifiers, err := secret.ReadSecretsConfig(app.Path, composeFiles, app.Recipe)
if err != nil {
logrus.Fatal(err)
}
@ -116,7 +116,7 @@ var appSecretGenerateCommand = cli.Command{
logrus.Fatal(err)
}
secretVals, err := secret.GenerateSecrets(cl, secretsToCreate, app.StackName(), app.Server)
secretVals, err := secret.GenerateSecrets(cl, secretsToCreate, secretModifiers, app.StackName(), app.Server)
if err != nil {
logrus.Fatal(err)
}
@ -276,7 +276,7 @@ Example:
logrus.Fatal(err)
}
secretsConfig, err := secret.ReadSecretsConfig(app.Path, composeFiles, app.Recipe)
secretsConfig, _, err := secret.ReadSecretsConfig(app.Path, composeFiles, app.Recipe)
if err != nil {
logrus.Fatal(err)
}

View File

@ -12,7 +12,7 @@ import (
"sort"
"strings"
"github.com/Autonomic-Cooperative/godotenv"
"coopcloud.tech/abra/pkg/godotenv"
"github.com/sirupsen/logrus"
)
@ -74,7 +74,7 @@ func ContainsEnvVarModifier(envVar string) bool {
func ReadEnv(filePath string, opts ReadEnvOptions) (AppEnv, error) {
var envVars AppEnv
envVars, err := godotenv.Read(filePath)
envVars, _, err := godotenv.Read(filePath)
if err != nil {
return nil, err
}
@ -94,6 +94,20 @@ func ReadEnv(filePath string, opts ReadEnvOptions) (AppEnv, error) {
return envVars, nil
}
// ReadEnv loads an app envivornment into a map.
func ReadEnvWithModifiers(filePath string, opts ReadEnvOptions) (AppEnv, map[string]map[string]string, error) {
var envVars AppEnv
envVars, mods, err := godotenv.Read(filePath)
if err != nil {
return nil, mods, err
}
logrus.Debugf("read %s from %s", envVars, filePath)
return envVars, mods, nil
}
// ReadServerNames retrieves all server names.
func ReadServerNames() ([]string, error) {
serverNames, err := GetAllFoldersInDirectory(SERVERS_DIR)

View File

@ -13,15 +13,21 @@ import (
"coopcloud.tech/abra/pkg/recipe"
)
var TestFolder = os.ExpandEnv("$PWD/../../tests/resources/test_folder")
var ValidAbraConf = os.ExpandEnv("$PWD/../../tests/resources/valid_abra_config")
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"}
var TFiles = []string{"bar.env", "foo.env"}
var (
TFolders = []string{"folder1", "folder2"}
TFiles = []string{"bar.env", "foo.env"}
)
var AppName = "ecloud"
var ServerName = "evil.corp"
var (
AppName = "ecloud"
ServerName = "evil.corp"
)
var ExpectedAppEnv = config.AppEnv{
"DOMAIN": "ecloud.evil.corp",
@ -263,12 +269,19 @@ func TestEnvVarModifiersIncluded(t *testing.T) {
}
envSamplePath := path.Join(config.RECIPES_DIR, r.Name, ".env.sample")
envSample, err := config.ReadEnv(envSamplePath, config.ReadEnvOptions{IncludeModifiers: true})
envSample, modifiers, err := config.ReadEnvWithModifiers(envSamplePath, config.ReadEnvOptions{IncludeModifiers: true})
if err != nil {
t.Fatal(err)
}
if !strings.Contains(envSample["SECRET_TEST_PASS_TWO_VERSION"], "length") {
t.Fatal("comment from env var SECRET_TEST_PASS_TWO_VERSION should not be removed")
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"])
}
}
}

View File

@ -6,6 +6,7 @@ package secret
import (
"context"
"fmt"
"log"
"slices"
"strconv"
"strings"
@ -35,7 +36,6 @@ func GeneratePasswords(count, length uint) ([]string, error) {
length,
passgen.AlphabetDefault,
)
if err != nil {
return nil, err
}
@ -54,7 +54,6 @@ func GeneratePassphrases(count uint) ([]string, error) {
passgen.PassphraseCasingDefault,
passgen.WordListDefault,
)
if err != nil {
return nil, err
}
@ -69,18 +68,19 @@ func GeneratePassphrases(count uint) ([]string, error) {
// and some times you don't (as the caller). We need to be able to handle the
// "app new" case where we pass in the .env.sample and the "secret generate"
// case where the app is created.
func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName string) (map[string]string, error) {
func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName string) (map[string]string, map[string]map[string]string, error) {
secretConfigs := make(map[string]string)
secretModifiers := make(map[string]map[string]string)
appEnv, err := config.ReadEnv(appEnvPath, config.ReadEnvOptions{IncludeModifiers: true})
appEnv, appModifiers, err := config.ReadEnvWithModifiers(appEnvPath, config.ReadEnvOptions{IncludeModifiers: true})
if err != nil {
return secretConfigs, err
return secretConfigs, nil, err
}
opts := stack.Deploy{Composefiles: composeFiles}
config, err := loader.LoadComposefile(opts, appEnv)
if err != nil {
return secretConfigs, err
return secretConfigs, appModifiers, err
}
var enabledSecrets []string
@ -92,12 +92,12 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName stri
if len(enabledSecrets) == 0 {
logrus.Debugf("not generating app secrets, none enabled in recipe config")
return secretConfigs, nil
return secretConfigs, appModifiers, nil
}
for secretId, secretConfig := range config.Secrets {
if string(secretConfig.Name[len(secretConfig.Name)-1]) == "_" {
return secretConfigs, fmt.Errorf("missing version for secret? (%s)", secretId)
return secretConfigs, appModifiers, fmt.Errorf("missing version for secret? (%s)", secretId)
}
if !(slices.Contains(enabledSecrets, secretId)) {
@ -108,9 +108,31 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName stri
lastIdx := strings.LastIndex(secretConfig.Name, "_")
secretVersion := secretConfig.Name[lastIdx+1:]
secretConfigs[secretId] = secretVersion
// THIS IS SOOOO HACKY
for k, v := range appModifiers {
if strings.Contains(k, strings.ToUpper(secretId)) {
secretModifiers[secretId] = v
}
}
}
return secretConfigs, nil
return secretConfigs, secretModifiers, nil
}
func ParseSecretValueUsingModifiers(secret string, modifiers map[string]string) (secretValue, error) {
length := 0
if modifiers != nil {
lengthRaw, ok := modifiers["length"]
if ok {
var err error
length, err = strconv.Atoi(lengthRaw)
if err != nil {
return secretValue{}, err
}
}
}
return secretValue{Version: secret, Length: length}, nil
}
func ParseSecretValue(secret string) (secretValue, error) {
@ -138,7 +160,7 @@ func ParseSecretValue(secret string) (secretValue, error) {
}
// GenerateSecrets generates secrets locally and sends them to a remote server for storage.
func GenerateSecrets(cl *dockerClient.Client, secretsFromConfig map[string]string, appName, server string) (map[string]string, error) {
func GenerateSecrets(cl *dockerClient.Client, secretsFromConfig map[string]string, modifiersFromConfig map[string]map[string]string, appName, server string) (map[string]string, error) {
secrets := make(map[string]string)
var mutex sync.Mutex
@ -146,11 +168,16 @@ func GenerateSecrets(cl *dockerClient.Client, secretsFromConfig map[string]strin
ch := make(chan error, len(secretsFromConfig))
for n, v := range secretsFromConfig {
wg.Add(1)
mods := make(map[string]string)
if modifiersFromConfig != nil {
mods = modifiersFromConfig[n]
}
log.Println(n)
go func(secretName, secretValue string) {
go func(secretName, secretValue string, modifiers map[string]string) {
defer wg.Done()
parsedSecretValue, err := ParseSecretValue(secretValue)
parsedSecretValue, err := ParseSecretValueUsingModifiers(secretValue, modifiers)
if err != nil {
ch <- err
return
@ -201,7 +228,7 @@ func GenerateSecrets(cl *dockerClient.Client, secretsFromConfig map[string]strin
secrets[secretName] = passphrases[0]
}
ch <- nil
}(n, v)
}(n, v, mods)
}
wg.Wait()
@ -237,7 +264,7 @@ func PollSecretsStatus(cl *dockerClient.Client, app config.App) (secretStatuses,
return secStats, err
}
secretsConfig, err := ReadSecretsConfig(app.Path, composeFiles, app.Recipe)
secretsConfig, _, err := ReadSecretsConfig(app.Path, composeFiles, app.Recipe)
if err != nil {
return secStats, err
}