forked from toolshed/abra
refactor!: cobra migrate
This commit is contained in:
@ -2,7 +2,6 @@ package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
@ -17,57 +16,45 @@ import (
|
||||
"coopcloud.tech/abra/pkg/secret"
|
||||
"github.com/docker/docker/api/types"
|
||||
dockerClient "github.com/docker/docker/client"
|
||||
"github.com/urfave/cli/v3"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
allSecrets bool
|
||||
allSecretsFlag = &cli.BoolFlag{
|
||||
Name: "all",
|
||||
Aliases: []string{"a"},
|
||||
Destination: &allSecrets,
|
||||
Usage: "Generate all secrets",
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
rmAllSecrets bool
|
||||
rmAllSecretsFlag = &cli.BoolFlag{
|
||||
Name: "all",
|
||||
Aliases: []string{"a"},
|
||||
Destination: &rmAllSecrets,
|
||||
Usage: "Remove all secrets",
|
||||
}
|
||||
)
|
||||
|
||||
var appSecretGenerateCommand = cli.Command{
|
||||
Name: "generate",
|
||||
Aliases: []string{"g"},
|
||||
Usage: "Generate secrets",
|
||||
UsageText: "abra app secret generate <domain> <secret> <version> [options]",
|
||||
Flags: []cli.Flag{
|
||||
allSecretsFlag,
|
||||
internal.PassFlag,
|
||||
internal.MachineReadableFlag,
|
||||
internal.ChaosFlag,
|
||||
var AppSecretGenerateCommand = &cobra.Command{
|
||||
Use: "generate <app> [[secret] [version] | --all] [flags]",
|
||||
Aliases: []string{"g"},
|
||||
Short: "Generate secrets",
|
||||
Args: cobra.RangeArgs(1, 3),
|
||||
ValidArgsFunction: func(
|
||||
cmd *cobra.Command,
|
||||
args []string,
|
||||
toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
switch l := len(args); l {
|
||||
case 0:
|
||||
return autocomplete.AppNameComplete()
|
||||
case 1:
|
||||
app, err := appPkg.Get(args[0])
|
||||
if err != nil {
|
||||
log.Debugf("autocomplete failed: %s", err)
|
||||
return nil, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
return autocomplete.SecretComplete(app.Recipe.Name)
|
||||
default:
|
||||
return nil, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
ShellComplete: autocomplete.AppNameComplete,
|
||||
HideHelp: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
app := internal.ValidateApp(cmd)
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
app := internal.ValidateApp(args)
|
||||
|
||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if cmd.Args().Len() == 1 && !allSecrets {
|
||||
err := errors.New("missing arguments <secret>/<version> or '--all'")
|
||||
internal.ShowSubcommandHelpAndError(cmd, err)
|
||||
if len(args) == 1 && !generateAllSecrets {
|
||||
log.Fatal("missing arguments [secret]/[version] or '--all'")
|
||||
}
|
||||
|
||||
if cmd.Args().Get(1) != "" && allSecrets {
|
||||
err := errors.New("cannot use '<secret> <version>' and '--all' together")
|
||||
internal.ShowSubcommandHelpAndError(cmd, err)
|
||||
if len(args) > 1 && generateAllSecrets {
|
||||
log.Fatal("cannot use '[secret] [version]' and '--all' together")
|
||||
}
|
||||
|
||||
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
|
||||
@ -80,9 +67,9 @@ var appSecretGenerateCommand = cli.Command{
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if !allSecrets {
|
||||
secretName := cmd.Args().Get(1)
|
||||
secretVersion := cmd.Args().Get(2)
|
||||
if !generateAllSecrets {
|
||||
secretName := args[1]
|
||||
secretVersion := args[2]
|
||||
s, ok := secrets[secretName]
|
||||
if !ok {
|
||||
log.Fatalf("%s doesn't exist in the env config?", secretName)
|
||||
@ -103,7 +90,7 @@ var appSecretGenerateCommand = cli.Command{
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if internal.Pass {
|
||||
if storeInPass {
|
||||
for name, data := range secretVals {
|
||||
if err := secret.PassInsertSecret(data, name, app.Name, app.Server); err != nil {
|
||||
log.Fatal(err)
|
||||
@ -137,7 +124,7 @@ var appSecretGenerateCommand = cli.Command{
|
||||
log.Fatal("unable to render to JSON: %s", err)
|
||||
}
|
||||
fmt.Println(out)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
@ -147,50 +134,54 @@ var appSecretGenerateCommand = cli.Command{
|
||||
formatter.BoldStyle.Render("NOT"),
|
||||
formatter.BoldStyle.Render("NOW"),
|
||||
)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var appSecretInsertCommand = cli.Command{
|
||||
Name: "insert",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "Insert secret",
|
||||
UsageText: "abra app secret insert <domain> <secret> <version> <data> [options]",
|
||||
Flags: []cli.Flag{
|
||||
internal.PassFlag,
|
||||
internal.FileFlag,
|
||||
internal.TrimFlag,
|
||||
internal.ChaosFlag,
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
ShellComplete: autocomplete.AppNameComplete,
|
||||
HideHelpCommand: true,
|
||||
Description: `This command inserts a secret into an app environment.
|
||||
var AppSecretInsertCommand = &cobra.Command{
|
||||
Use: "insert <app> <secret> <version> <data> [flags]",
|
||||
Aliases: []string{"i"},
|
||||
Short: "Insert secret",
|
||||
Long: `This command inserts a secret into an app environment.
|
||||
|
||||
This can be useful when you want to manually generate secrets for an app
|
||||
environment. Typically, you can let Abra generate them for you on app creation
|
||||
(see "abra app new --secrets" for more).`,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
app := internal.ValidateApp(cmd)
|
||||
(see "abra app new --secrets/-S" for more).`,
|
||||
Args: cobra.MinimumNArgs(4),
|
||||
ValidArgsFunction: func(
|
||||
cmd *cobra.Command,
|
||||
args []string,
|
||||
toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
switch l := len(args); l {
|
||||
case 0:
|
||||
return autocomplete.AppNameComplete()
|
||||
case 1:
|
||||
app, err := appPkg.Get(args[0])
|
||||
if err != nil {
|
||||
log.Debugf("autocomplete failed: %s", err)
|
||||
return nil, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
return autocomplete.SecretComplete(app.Recipe.Name)
|
||||
default:
|
||||
return nil, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
app := internal.ValidateApp(args)
|
||||
|
||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if cmd.Args().Len() != 4 {
|
||||
internal.ShowSubcommandHelpAndError(cmd, errors.New("missing arguments?"))
|
||||
}
|
||||
|
||||
cl, err := client.New(app.Server)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
name := cmd.Args().Get(1)
|
||||
version := cmd.Args().Get(2)
|
||||
data := cmd.Args().Get(3)
|
||||
name := args[1]
|
||||
version := args[2]
|
||||
data := args[3]
|
||||
|
||||
if internal.File {
|
||||
if insertFromFile {
|
||||
raw, err := os.ReadFile(data)
|
||||
if err != nil {
|
||||
log.Fatalf("reading secret from file: %s", err)
|
||||
@ -198,7 +189,7 @@ environment. Typically, you can let Abra generate them for you on app creation
|
||||
data = string(raw)
|
||||
}
|
||||
|
||||
if internal.Trim {
|
||||
if trimInput {
|
||||
data = strings.TrimSpace(data)
|
||||
}
|
||||
|
||||
@ -209,13 +200,11 @@ environment. Typically, you can let Abra generate them for you on app creation
|
||||
|
||||
log.Infof("%s successfully stored on server", secretName)
|
||||
|
||||
if internal.Pass {
|
||||
if storeInPass {
|
||||
if err := secret.PassInsertSecret(data, name, app.Name, app.Server); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@ -227,7 +216,7 @@ func secretRm(cl *dockerClient.Client, app appPkg.App, secretName, parsed string
|
||||
|
||||
log.Infof("deleted %s successfully from server", secretName)
|
||||
|
||||
if internal.PassRemove {
|
||||
if removeFromPass {
|
||||
if err := secret.PassRmSecret(parsed, app.StackName(), app.Server); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -238,29 +227,35 @@ func secretRm(cl *dockerClient.Client, app appPkg.App, secretName, parsed string
|
||||
return nil
|
||||
}
|
||||
|
||||
var appSecretRmCommand = cli.Command{
|
||||
Name: "remove",
|
||||
Aliases: []string{"rm"},
|
||||
Usage: "Remove a secret",
|
||||
UsageText: "abra app remove <domainabra app remove <domain> [options]",
|
||||
Flags: []cli.Flag{
|
||||
internal.NoInputFlag,
|
||||
rmAllSecretsFlag,
|
||||
internal.PassRemoveFlag,
|
||||
internal.OfflineFlag,
|
||||
internal.ChaosFlag,
|
||||
var AppSecretRmCommand = &cobra.Command{
|
||||
Use: "remove <app> [[secret] | --all] [flags]",
|
||||
Aliases: []string{"rm"},
|
||||
Short: "Remove a secret",
|
||||
Args: cobra.RangeArgs(1, 2),
|
||||
ValidArgsFunction: func(
|
||||
cmd *cobra.Command,
|
||||
args []string,
|
||||
toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
switch l := len(args); l {
|
||||
case 0:
|
||||
return autocomplete.AppNameComplete()
|
||||
case 1:
|
||||
if !rmAllSecrets {
|
||||
app, err := appPkg.Get(args[0])
|
||||
if err != nil {
|
||||
log.Debugf("autocomplete failed: %s", err)
|
||||
return nil, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
return autocomplete.SecretComplete(app.Recipe.Name)
|
||||
}
|
||||
return nil, cobra.ShellCompDirectiveDefault
|
||||
default:
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
ShellComplete: autocomplete.AppNameComplete,
|
||||
Description: `
|
||||
This command removes app secrets.
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
app := internal.ValidateApp(args)
|
||||
|
||||
Example:
|
||||
|
||||
abra app secret remove myapp db_pass`,
|
||||
HideHelp: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
app := internal.ValidateApp(cmd)
|
||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -275,12 +270,12 @@ Example:
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if cmd.Args().Get(1) != "" && rmAllSecrets {
|
||||
internal.ShowSubcommandHelpAndError(cmd, errors.New("cannot use '<secret-name>' and '--all' together"))
|
||||
if len(args) == 2 && rmAllSecrets {
|
||||
log.Fatal("cannot use [secret] and --all/-a together")
|
||||
}
|
||||
|
||||
if cmd.Args().Get(1) == "" && !rmAllSecrets {
|
||||
internal.ShowSubcommandHelpAndError(cmd, errors.New("no secret(s) specified?"))
|
||||
if len(args) != 2 && !rmAllSecrets {
|
||||
log.Fatal("no secret(s) specified?")
|
||||
}
|
||||
|
||||
cl, err := client.New(app.Server)
|
||||
@ -303,8 +298,12 @@ Example:
|
||||
remoteSecretNames[cont.Spec.Annotations.Name] = true
|
||||
}
|
||||
|
||||
var secretToRm string
|
||||
if len(args) == 2 {
|
||||
secretToRm = args[1]
|
||||
}
|
||||
|
||||
match := false
|
||||
secretToRm := cmd.Args().Get(1)
|
||||
for secretName, val := range secrets {
|
||||
secretRemoteName := fmt.Sprintf("%s_%s_%s", app.StackName(), secretName, val.Version)
|
||||
if _, ok := remoteSecretNames[secretRemoteName]; ok {
|
||||
@ -314,7 +313,7 @@ Example:
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
return
|
||||
}
|
||||
} else {
|
||||
match = true
|
||||
@ -333,26 +332,23 @@ Example:
|
||||
if !match {
|
||||
log.Fatal("no secrets to remove?")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var appSecretLsCommand = cli.Command{
|
||||
Name: "list",
|
||||
var AppSecretLsCommand = &cobra.Command{
|
||||
Use: "list <app>",
|
||||
Aliases: []string{"ls"},
|
||||
Flags: []cli.Flag{
|
||||
internal.OfflineFlag,
|
||||
internal.ChaosFlag,
|
||||
internal.MachineReadableFlag,
|
||||
Short: "List all secrets",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
ValidArgsFunction: func(
|
||||
cmd *cobra.Command,
|
||||
args []string,
|
||||
toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return autocomplete.AppNameComplete()
|
||||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Usage: "List all secrets",
|
||||
UsageText: "abra app secret list [options]",
|
||||
HideHelp: true,
|
||||
ShellComplete: autocomplete.AppNameComplete,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
app := internal.ValidateApp(cmd)
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
app := internal.ValidateApp(args)
|
||||
|
||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -395,28 +391,126 @@ var appSecretLsCommand = cli.Command{
|
||||
log.Fatal("unable to render to JSON: %s", err)
|
||||
}
|
||||
fmt.Println(out)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
log.Warnf("no secrets stored for %s", app.Name)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var appSecretCommand = cli.Command{
|
||||
Name: "secret",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Manage app secrets",
|
||||
UsageText: "abra app secret [command] [arguments] [options]",
|
||||
Commands: []*cli.Command{
|
||||
&appSecretGenerateCommand,
|
||||
&appSecretInsertCommand,
|
||||
&appSecretRmCommand,
|
||||
&appSecretLsCommand,
|
||||
},
|
||||
var AppSecretCommand = &cobra.Command{
|
||||
Use: "secret [cmd] [args] [flags]",
|
||||
Aliases: []string{"s"},
|
||||
Short: "Manage app secrets",
|
||||
}
|
||||
|
||||
var (
|
||||
storeInPass bool
|
||||
insertFromFile bool
|
||||
trimInput bool
|
||||
rmAllSecrets bool
|
||||
generateAllSecrets bool
|
||||
removeFromPass bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
AppSecretGenerateCommand.Flags().BoolVarP(
|
||||
&internal.MachineReadable,
|
||||
"machine",
|
||||
"m",
|
||||
false,
|
||||
"print machine-readable output",
|
||||
)
|
||||
|
||||
AppSecretGenerateCommand.Flags().BoolVarP(
|
||||
&storeInPass,
|
||||
"pass",
|
||||
"p",
|
||||
false,
|
||||
"store generated secrets in a local pass store",
|
||||
)
|
||||
|
||||
AppSecretGenerateCommand.Flags().BoolVarP(
|
||||
&internal.Chaos,
|
||||
"chaos",
|
||||
"C",
|
||||
false,
|
||||
"ignore uncommitted recipes changes",
|
||||
)
|
||||
|
||||
AppSecretInsertCommand.Flags().BoolVarP(
|
||||
&storeInPass,
|
||||
"pass",
|
||||
"p",
|
||||
false,
|
||||
"store generated secrets in a local pass store",
|
||||
)
|
||||
|
||||
AppSecretInsertCommand.Flags().BoolVarP(
|
||||
&insertFromFile,
|
||||
"file",
|
||||
"f",
|
||||
false,
|
||||
"treat input as a file",
|
||||
)
|
||||
|
||||
AppSecretInsertCommand.Flags().BoolVarP(
|
||||
&trimInput,
|
||||
"trim",
|
||||
"t",
|
||||
false,
|
||||
"trim input",
|
||||
)
|
||||
|
||||
AppSecretInsertCommand.Flags().BoolVarP(
|
||||
&internal.Chaos,
|
||||
"chaos",
|
||||
"C",
|
||||
false,
|
||||
"ignore uncommitted recipes changes",
|
||||
)
|
||||
|
||||
AppSecretRmCommand.Flags().BoolVarP(
|
||||
&rmAllSecrets,
|
||||
"all",
|
||||
"a",
|
||||
false,
|
||||
"remove all secrets",
|
||||
)
|
||||
|
||||
AppSecretRmCommand.Flags().BoolVarP(
|
||||
&removeFromPass,
|
||||
"pass",
|
||||
"p",
|
||||
false,
|
||||
"remove generated secrets from a local pass store",
|
||||
)
|
||||
|
||||
AppSecretRmCommand.Flags().BoolVarP(
|
||||
&internal.Chaos,
|
||||
"chaos",
|
||||
"C",
|
||||
false,
|
||||
"ignore uncommitted recipes changes",
|
||||
)
|
||||
|
||||
AppSecretLsCommand.Flags().BoolVarP(
|
||||
&internal.Chaos,
|
||||
"chaos",
|
||||
"C",
|
||||
false,
|
||||
"ignore uncommitted recipes changes",
|
||||
)
|
||||
|
||||
AppSecretLsCommand.Flags().BoolVarP(
|
||||
&internal.MachineReadable,
|
||||
"machine",
|
||||
"m",
|
||||
false,
|
||||
"print machine-readable output",
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user