package internal import ( "fmt" "path" "coopcloud.tech/abra/pkg/app" "coopcloud.tech/abra/pkg/config" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/recipe" recipePkg "coopcloud.tech/abra/pkg/recipe" "coopcloud.tech/abra/pkg/secret" "coopcloud.tech/abra/pkg/ssh" "github.com/AlecAivazis/survey/v2" "github.com/olekukonko/tablewriter" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) // AppSecrets represents all app secrest type AppSecrets map[string]string // RecipeName is used for configuring recipe name programmatically var RecipeName string // createSecrets creates all secrets for a new app. func createSecrets(sanitisedAppName string) (AppSecrets, error) { appEnvPath := path.Join(config.ABRA_DIR, "servers", NewAppServer, fmt.Sprintf("%s.env", Domain)) appEnv, err := config.ReadEnv(appEnvPath) if err != nil { return nil, err } secretEnvVars := secret.ReadSecretEnvVars(appEnv) secrets, err := secret.GenerateSecrets(secretEnvVars, sanitisedAppName, NewAppServer) if err != nil { return nil, err } if Pass { for secretName := range secrets { secretValue := secrets[secretName] if err := secret.PassInsertSecret(secretValue, secretName, Domain, NewAppServer); err != nil { return nil, err } } } return secrets, nil } // ensureDomainFlag checks if the domain flag was used. if not, asks the user for it/ func ensureDomainFlag(recipe recipe.Recipe, server string) error { if Domain == "" && !NoInput { prompt := &survey.Input{ Message: "Specify app domain", Default: fmt.Sprintf("%s.%s", recipe.Name, server), } if err := survey.AskOne(prompt, &Domain); err != nil { return err } } if Domain == "" { return fmt.Errorf("no domain provided") } return nil } // promptForSecrets asks if we should generate secrets for a new app. func promptForSecrets(appName string) error { app, err := app.Get(appName) if err != nil { return err } secretEnvVars := secret.ReadSecretEnvVars(app.Env) if len(secretEnvVars) == 0 { logrus.Debugf("%s has no secrets to generate, skipping...", app.Recipe) return nil } if !Secrets && !NoInput { prompt := &survey.Confirm{ Message: "Generate app secrets?", } if err := survey.AskOne(prompt, &Secrets); err != nil { return err } } return nil } // ensureServerFlag checks if the server flag was used. if not, asks the user for it. func ensureServerFlag() error { servers, err := config.GetServers() if err != nil { return err } if NewAppServer == "" && !NoInput { prompt := &survey.Select{ Message: "Select app server:", Options: servers, } if err := survey.AskOne(prompt, &NewAppServer); err != nil { return err } } if NewAppServer == "" { return fmt.Errorf("no server provided") } return nil } // NewAction is the new app creation logic func NewAction(c *cli.Context) error { recipe := ValidateRecipeWithPrompt(c, false) if err := recipePkg.EnsureUpToDate(recipe.Name); err != nil { logrus.Fatal(err) } if err := ensureServerFlag(); err != nil { logrus.Fatal(err) } if err := ensureDomainFlag(recipe, NewAppServer); err != nil { logrus.Fatal(err) } if err := promptForSecrets(Domain); err != nil { logrus.Fatal(err) } sanitisedAppName := config.SanitiseAppName(Domain) logrus.Debugf("%s sanitised as %s for new app", Domain, sanitisedAppName) if err := config.TemplateAppEnvSample(recipe.Name, Domain, NewAppServer, Domain); err != nil { logrus.Fatal(err) } var secrets AppSecrets var secretTable *tablewriter.Table if Secrets { if err := ssh.EnsureHostKey(NewAppServer); err != nil { logrus.Fatal(err) } var err error secrets, err = createSecrets(sanitisedAppName) if err != nil { logrus.Fatal(err) } secretCols := []string{"Name", "Value"} secretTable = formatter.CreateTable(secretCols) for secret := range secrets { secretTable.Append([]string{secret, secrets[secret]}) } } if NewAppServer == "default" { NewAppServer = "local" } tableCol := []string{"server", "recipe", "domain"} table := formatter.CreateTable(tableCol) table.Append([]string{NewAppServer, recipe.Name, Domain}) fmt.Println("") fmt.Println(fmt.Sprintf("A new %s app has been created! Here is an overview:", recipe.Name)) fmt.Println("") table.Render() fmt.Println("") fmt.Println("You can configure this app by running the following:") fmt.Println(fmt.Sprintf("\n abra app config %s", Domain)) fmt.Println("") fmt.Println("You can deploy this app by running the following:") fmt.Println(fmt.Sprintf("\n abra app deploy %s", Domain)) fmt.Println("") if len(secrets) > 0 { fmt.Println("Here are your generated secrets:") fmt.Println("") secretTable.Render() fmt.Println("") logrus.Warn("generated secrets are not shown again, please take note of them *now*") } return nil }