WIP another pass on the app new command
This commit is contained in:
parent
e728bcd7ac
commit
5771f6c158
58
cli/app.go
58
cli/app.go
@ -5,26 +5,28 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path"
|
"path"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/catalogue"
|
"coopcloud.tech/abra/catalogue"
|
||||||
"coopcloud.tech/abra/client"
|
"coopcloud.tech/abra/client"
|
||||||
"coopcloud.tech/abra/config"
|
"coopcloud.tech/abra/config"
|
||||||
|
"coopcloud.tech/abra/secret"
|
||||||
|
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/docker/cli/cli/command/formatter"
|
"github.com/docker/cli/cli/command/formatter"
|
||||||
"github.com/docker/cli/cli/command/idresolver"
|
"github.com/docker/cli/cli/command/idresolver"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/schultz-is/passgen"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appNewCommand = &cli.Command{
|
var appNewCommand = &cli.Command{
|
||||||
Name: "new",
|
Name: "new",
|
||||||
Usage: "Create a new app of <type>",
|
Usage: "Create a new app",
|
||||||
Description: `
|
Description: `
|
||||||
This command takes a recipe and uses it to cook up a new app. This app
|
This command takes a recipe and uses it to cook up a new app. This app
|
||||||
configuration is stored in your ~/.abra directory under the appropriate server.
|
configuration is stored in your ~/.abra directory under the appropriate server.
|
||||||
@ -82,7 +84,7 @@ locally in a pass store (see passwordstore.org for more).
|
|||||||
servers := appFiles.GetServers()
|
servers := appFiles.GetServers()
|
||||||
if Server == "" {
|
if Server == "" {
|
||||||
prompt := &survey.Select{
|
prompt := &survey.Select{
|
||||||
Message: "Select server to create this app for:",
|
Message: "Select app server:",
|
||||||
Options: servers,
|
Options: servers,
|
||||||
}
|
}
|
||||||
if err := survey.AskOne(prompt, &Server); err != nil {
|
if err := survey.AskOne(prompt, &Server); err != nil {
|
||||||
@ -92,7 +94,7 @@ locally in a pass store (see passwordstore.org for more).
|
|||||||
|
|
||||||
if Domain == "" {
|
if Domain == "" {
|
||||||
prompt := &survey.Input{
|
prompt := &survey.Input{
|
||||||
Message: "Specify domain for this app:",
|
Message: "Specify app domain",
|
||||||
}
|
}
|
||||||
if err := survey.AskOne(prompt, &Domain); err != nil {
|
if err := survey.AskOne(prompt, &Domain); err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
@ -126,15 +128,57 @@ locally in a pass store (see passwordstore.org for more).
|
|||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate secrets if asked to do so
|
|
||||||
if Secrets {
|
if Secrets {
|
||||||
|
appEnv, err := config.ReadEnv(appEnvPath)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var secretEnvVars []string
|
||||||
|
for envVar := range appEnv {
|
||||||
|
regex := regexp.MustCompile(`^SECRET.*VERSION.*`)
|
||||||
|
secretEnvVar := regex.Find([]byte(envVar))
|
||||||
|
secretEnvVars = append(secretEnvVars, string(secretEnvVar))
|
||||||
|
}
|
||||||
|
|
||||||
|
var length int
|
||||||
|
var secretValue string
|
||||||
|
var secrets map[string]string
|
||||||
|
for _, secretEnvVar := range secretEnvVars {
|
||||||
|
withoutPrefix := strings.TrimPrefix(secretEnvVar, "SECRET_")
|
||||||
|
regex := regexp.MustCompile(`_VERSION=.*`)
|
||||||
|
secretName := string(regex.Find([]byte(withoutPrefix)))
|
||||||
|
|
||||||
|
if strings.Contains(secretEnvVar, "length") {
|
||||||
|
regex := regexp.MustCompile(`s/.*[^0-9]\([0-9]\+\)[^0-9]*$/\1/`)
|
||||||
|
match := regex.Find([]byte(secretEnvVar))
|
||||||
|
length, err = strconv.Atoi(string(match))
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
passwords, err := secret.GeneratePasswords(1, uint(length))
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
secretValue = passwords[0]
|
||||||
|
secrets[secretEnvVar] = secretValue
|
||||||
|
} else {
|
||||||
|
passphrases, err := secret.GeneratePassphrases(1)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
|
secretValue = passphrases[0]
|
||||||
|
secrets[secretEnvVar] = secretValue
|
||||||
|
}
|
||||||
|
go client.StoreSecret(secretName, secretValue, Server)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save them in a pass store if asked to do so
|
// TODO: save them in a pass store if asked to do so
|
||||||
if Pass {
|
if Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output some instructions on how to deploy this thing
|
// TODO: Output some instructions on how to deploy this thing
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
5
client/secret.go
Normal file
5
client/secret.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
func StoreSecret(secretName, secretValue, server string) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -203,7 +203,7 @@ func GetAppStatuses(appFiles AppFiles) (map[string]string, error) {
|
|||||||
// TODO: maybe better names than read and get
|
// TODO: maybe better names than read and get
|
||||||
|
|
||||||
func readAppFile(appFile AppFile, name AppName) (App, error) {
|
func readAppFile(appFile AppFile, name AppName) (App, error) {
|
||||||
env, err := readEnv(appFile.Path)
|
env, err := ReadEnv(appFile.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return App{}, fmt.Errorf("env file for '%s' couldn't be read: %s", name, err.Error())
|
return App{}, fmt.Errorf("env file for '%s' couldn't be read: %s", name, err.Error())
|
||||||
}
|
}
|
||||||
@ -214,7 +214,7 @@ func readAppFile(appFile AppFile, name AppName) (App, error) {
|
|||||||
return app, nil
|
return app, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readEnv(filePath string) (AppEnv, error) {
|
func ReadEnv(filePath string) (AppEnv, error) {
|
||||||
var envFile AppEnv
|
var envFile AppEnv
|
||||||
envFile, err := godotenv.Read(filePath)
|
envFile, err := godotenv.Read(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user