forked from toolshed/abra
.chglog
.gitea
cli
app
app.go
backup.go
check.go
config.go
cp.go
deploy.go
list.go
logs.go
new.go
ps.go
remove.go
restore.go
rollback.go
run.go
secret.go
undeploy.go
version.go
volume.go
catalogue
formatter
internal
recipe
server
cli.go
upgrade.go
version.go
cmd
pkg
scripts
tests
.drone.yml
.envrc.sample
.gitignore
.goreleaser.yml
Makefile
README.md
go.mod
go.sum
261 lines
6.5 KiB
Go
261 lines
6.5 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
|
|
abraFormatter "coopcloud.tech/abra/cli/formatter"
|
|
"coopcloud.tech/abra/cli/internal"
|
|
"coopcloud.tech/abra/pkg/client"
|
|
"coopcloud.tech/abra/pkg/config"
|
|
"coopcloud.tech/abra/pkg/secret"
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/filters"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
var allSecrets bool
|
|
var allSecretsFlag = &cli.BoolFlag{
|
|
Name: "all",
|
|
Aliases: []string{"A"},
|
|
Value: false,
|
|
Destination: &allSecrets,
|
|
Usage: "Generate all secrets",
|
|
}
|
|
|
|
var appSecretGenerateCommand = &cli.Command{
|
|
Name: "generate",
|
|
Aliases: []string{"g"},
|
|
Usage: "Generate secrets",
|
|
ArgsUsage: "<secret> <version>",
|
|
Flags: []cli.Flag{allSecretsFlag, internal.PassFlag},
|
|
Action: func(c *cli.Context) error {
|
|
app := internal.ValidateApp(c)
|
|
|
|
if c.Args().Len() == 1 && !allSecrets {
|
|
err := errors.New("missing arguments <secret>/<version> or '--all'")
|
|
internal.ShowSubcommandHelpAndError(c, err)
|
|
}
|
|
|
|
if c.Args().Get(1) != "" && allSecrets {
|
|
err := errors.New("cannot use '<secret> <version>' and '--all' together")
|
|
internal.ShowSubcommandHelpAndError(c, err)
|
|
}
|
|
|
|
secretsToCreate := make(map[string]string)
|
|
secretEnvVars := secret.ReadSecretEnvVars(app.Env)
|
|
if allSecrets {
|
|
secretsToCreate = secretEnvVars
|
|
} else {
|
|
secretName := c.Args().Get(1)
|
|
secretVersion := c.Args().Get(2)
|
|
matches := false
|
|
for sec := range secretEnvVars {
|
|
parsed := secret.ParseSecretEnvVarName(sec)
|
|
if secretName == parsed {
|
|
secretsToCreate[sec] = secretVersion
|
|
}
|
|
}
|
|
if !matches {
|
|
logrus.Fatalf("'%s' doesn't exist in the env config?", secretName)
|
|
}
|
|
}
|
|
|
|
secretVals, err := secret.GenerateSecrets(secretsToCreate, app.StackName(), app.Server)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if internal.Pass {
|
|
for name, data := range secretVals {
|
|
if err := secret.PassInsertSecret(data, name, app.StackName(), app.Server); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(secretVals) == 0 {
|
|
logrus.Warn("no secrets generated")
|
|
os.Exit(1)
|
|
}
|
|
|
|
tableCol := []string{"name", "value"}
|
|
table := abraFormatter.CreateTable(tableCol)
|
|
for name, val := range secretVals {
|
|
table.Append([]string{name, val})
|
|
}
|
|
table.Render()
|
|
logrus.Warn("generated secrets are not shown again, please take note of them *now*")
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var appSecretInsertCommand = &cli.Command{
|
|
Name: "insert",
|
|
Aliases: []string{"i"},
|
|
Usage: "Insert secret",
|
|
Flags: []cli.Flag{internal.PassFlag},
|
|
ArgsUsage: "<secret> <version> <data>",
|
|
Action: func(c *cli.Context) error {
|
|
app := internal.ValidateApp(c)
|
|
|
|
if c.Args().Len() != 4 {
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("missing arguments?"))
|
|
}
|
|
|
|
name := c.Args().Get(1)
|
|
version := c.Args().Get(2)
|
|
data := c.Args().Get(3)
|
|
|
|
secretName := fmt.Sprintf("%s_%s_%s", app.StackName(), name, version)
|
|
if err := client.StoreSecret(secretName, data, app.Server); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
if internal.Pass {
|
|
if err := secret.PassInsertSecret(data, name, app.StackName(), app.Server); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var appSecretRmCommand = &cli.Command{
|
|
Name: "remove",
|
|
Usage: "Remove a secret",
|
|
Aliases: []string{"rm"},
|
|
Flags: []cli.Flag{allSecretsFlag, internal.PassFlag},
|
|
ArgsUsage: "<secret>",
|
|
Action: func(c *cli.Context) error {
|
|
app := internal.ValidateApp(c)
|
|
|
|
if c.Args().Get(1) != "" && allSecrets {
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("cannot use '<secret>' and '--all' together"))
|
|
}
|
|
|
|
if c.Args().Get(1) == "" && !allSecrets {
|
|
internal.ShowSubcommandHelpAndError(c, errors.New("no secret(s) specified?"))
|
|
}
|
|
|
|
cl, err := client.New(app.Server)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
filters := filters.NewArgs()
|
|
filters.Add("name", app.StackName())
|
|
secretList, err := cl.SecretList(c.Context, types.SecretListOptions{Filters: filters})
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
secretToRm := c.Args().Get(1)
|
|
for _, cont := range secretList {
|
|
secretName := cont.Spec.Annotations.Name
|
|
parsed := secret.ParseGeneratedSecretName(secretName, app)
|
|
if allSecrets {
|
|
if err := cl.SecretRemove(c.Context, secretName); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
if internal.Pass {
|
|
if err := secret.PassRmSecret(parsed, app.StackName(), app.Server); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
} else {
|
|
if parsed == secretToRm {
|
|
if err := cl.SecretRemove(c.Context, secretName); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
if internal.Pass {
|
|
if err := secret.PassRmSecret(parsed, app.StackName(), app.Server); err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var appSecretLsCommand = &cli.Command{
|
|
Name: "list",
|
|
Usage: "List all secrets",
|
|
Aliases: []string{"ls"},
|
|
Action: func(c *cli.Context) error {
|
|
app := internal.ValidateApp(c)
|
|
secrets := secret.ReadSecretEnvVars(app.Env)
|
|
|
|
tableCol := []string{"Name", "Version", "Generated Name", "Created On Server"}
|
|
table := abraFormatter.CreateTable(tableCol)
|
|
|
|
cl, err := client.New(app.Server)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
filters := filters.NewArgs()
|
|
filters.Add("name", app.StackName())
|
|
secretList, err := cl.SecretList(c.Context, types.SecretListOptions{Filters: filters})
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
remoteSecretNames := make(map[string]bool)
|
|
for _, cont := range secretList {
|
|
remoteSecretNames[cont.Spec.Annotations.Name] = true
|
|
}
|
|
|
|
for sec := range secrets {
|
|
createdRemote := false
|
|
secretName := secret.ParseSecretEnvVarName(sec)
|
|
secVal, err := secret.ParseSecretEnvVarValue(secrets[sec])
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
secretRemoteName := fmt.Sprintf("%s_%s_%s", app.StackName(), secretName, secVal.Version)
|
|
if _, ok := remoteSecretNames[secretRemoteName]; ok {
|
|
createdRemote = true
|
|
}
|
|
tableRow := []string{secretName, secVal.Version, secretRemoteName, strconv.FormatBool(createdRemote)}
|
|
table.Append(tableRow)
|
|
}
|
|
|
|
table.Render()
|
|
return nil
|
|
},
|
|
BashComplete: func(c *cli.Context) {
|
|
appNames, err := config.GetAppNames()
|
|
if err != nil {
|
|
logrus.Warn(err)
|
|
}
|
|
if c.NArg() > 0 {
|
|
return
|
|
}
|
|
for _, a := range appNames {
|
|
fmt.Println(a)
|
|
}
|
|
},
|
|
}
|
|
|
|
var appSecretCommand = &cli.Command{
|
|
Name: "secret",
|
|
Aliases: []string{"s"},
|
|
Usage: "Manage app secrets",
|
|
ArgsUsage: "<command>",
|
|
Subcommands: []*cli.Command{
|
|
appSecretGenerateCommand,
|
|
appSecretInsertCommand,
|
|
appSecretRmCommand,
|
|
appSecretLsCommand,
|
|
},
|
|
}
|