forked from toolshed/abra
Compare commits
9 Commits
main
...
urfave-mig
Author | SHA1 | Date | |
---|---|---|---|
7ddfd22133 | |||
c3f0d15920 | |||
edb542c653 | |||
4580ea9dc8 | |||
878247e46d | |||
ef547aed25 | |||
2c9e13d3d4 | |||
ca37621ce3 | |||
16aeb441e7 |
@ -1,34 +1,35 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AppCommand = cli.Command{
|
var AppCommand = cli.Command{
|
||||||
Name: "app",
|
Name: "app",
|
||||||
Aliases: []string{"a"},
|
Aliases: []string{"a"},
|
||||||
Usage: "Manage apps",
|
Usage: "Manage apps",
|
||||||
ArgsUsage: "<domain>",
|
UsageText: "abra app [command] [options] [arguments]",
|
||||||
Subcommands: []cli.Command{
|
HideHelpCommand: true,
|
||||||
appBackupCommand,
|
Commands: []*cli.Command{
|
||||||
appCheckCommand,
|
&appBackupCommand,
|
||||||
appCmdCommand,
|
&appCheckCommand,
|
||||||
appConfigCommand,
|
&appCmdCommand,
|
||||||
appCpCommand,
|
&appConfigCommand,
|
||||||
appDeployCommand,
|
&appCpCommand,
|
||||||
appListCommand,
|
&appDeployCommand,
|
||||||
appLogsCommand,
|
&appListCommand,
|
||||||
appNewCommand,
|
&appLogsCommand,
|
||||||
appPsCommand,
|
&appNewCommand,
|
||||||
appRemoveCommand,
|
&appPsCommand,
|
||||||
appRestartCommand,
|
&appRemoveCommand,
|
||||||
appRestoreCommand,
|
&appRestartCommand,
|
||||||
appRollbackCommand,
|
&appRestoreCommand,
|
||||||
appRunCommand,
|
&appRollbackCommand,
|
||||||
appSecretCommand,
|
&appRunCommand,
|
||||||
appServicesCommand,
|
&appSecretCommand,
|
||||||
appUndeployCommand,
|
&appServicesCommand,
|
||||||
appUpgradeCommand,
|
&appUndeployCommand,
|
||||||
appVolumeCommand,
|
&appUpgradeCommand,
|
||||||
|
&appVolumeCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,36 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/client"
|
"coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var snapshot string
|
var snapshot string
|
||||||
var snapshotFlag = &cli.StringFlag{
|
var snapshotFlag = &cli.StringFlag{
|
||||||
Name: "snapshot, s",
|
Name: "snapshot",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Usage: "Lists specific snapshot",
|
Usage: "Lists specific snapshot",
|
||||||
Destination: &snapshot,
|
Destination: &snapshot,
|
||||||
}
|
}
|
||||||
|
|
||||||
var includePath string
|
var includePath string
|
||||||
var includePathFlag = &cli.StringFlag{
|
var includePathFlag = &cli.StringFlag{
|
||||||
Name: "path, p",
|
Name: "path",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Usage: "Include path",
|
Usage: "Include path",
|
||||||
Destination: &includePath,
|
Destination: &includePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
var resticRepo string
|
var resticRepo string
|
||||||
var resticRepoFlag = &cli.StringFlag{
|
var resticRepoFlag = &cli.StringFlag{
|
||||||
Name: "repo, r",
|
Name: "repo",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Usage: "Restic repository",
|
Usage: "Restic repository",
|
||||||
Destination: &resticRepo,
|
Destination: &resticRepo,
|
||||||
}
|
}
|
||||||
@ -35,16 +39,17 @@ var appBackupListCommand = cli.Command{
|
|||||||
Name: "list",
|
Name: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
snapshotFlag,
|
snapshotFlag,
|
||||||
includePathFlag,
|
includePathFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Usage: "List all backups",
|
Usage: "List all backups",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
HideHelpCommand: true,
|
||||||
app := internal.ValidateApp(c)
|
UsageText: "abra app backup list [options] <domain>",
|
||||||
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -82,16 +87,17 @@ var appBackupDownloadCommand = cli.Command{
|
|||||||
Name: "download",
|
Name: "download",
|
||||||
Aliases: []string{"d"},
|
Aliases: []string{"d"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
snapshotFlag,
|
snapshotFlag,
|
||||||
includePathFlag,
|
includePathFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Usage: "Download a backup",
|
Usage: "Download a backup",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
UsageText: "abra app backup download [options] <domain>",
|
||||||
Action: func(c *cli.Context) error {
|
HideHelpCommand: true,
|
||||||
app := internal.ValidateApp(c)
|
EnableShellCompletion: true,
|
||||||
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.EnsureExists(); err != nil {
|
if err := app.Recipe.EnsureExists(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -153,15 +159,16 @@ var appBackupCreateCommand = cli.Command{
|
|||||||
Name: "create",
|
Name: "create",
|
||||||
Aliases: []string{"c"},
|
Aliases: []string{"c"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
resticRepoFlag,
|
resticRepoFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Usage: "Create a new backup",
|
Usage: "Create a new backup",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
HideHelpCommand: true,
|
||||||
Action: func(c *cli.Context) error {
|
UsageText: "abra app backup create [options] <domain>",
|
||||||
app := internal.ValidateApp(c)
|
EnableShellCompletion: true,
|
||||||
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.EnsureExists(); err != nil {
|
if err := app.Recipe.EnsureExists(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -211,15 +218,16 @@ var appBackupSnapshotsCommand = cli.Command{
|
|||||||
Name: "snapshots",
|
Name: "snapshots",
|
||||||
Aliases: []string{"s"},
|
Aliases: []string{"s"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
snapshotFlag,
|
snapshotFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Usage: "List backup snapshots",
|
Usage: "List backup snapshots",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
UsageText: "abra app backup snapshots [options] <domain>",
|
||||||
Action: func(c *cli.Context) error {
|
HideHelpCommand: true,
|
||||||
app := internal.ValidateApp(c)
|
EnableShellCompletion: true,
|
||||||
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.EnsureExists(); err != nil {
|
if err := app.Recipe.EnsureExists(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -266,14 +274,15 @@ var appBackupSnapshotsCommand = cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var appBackupCommand = cli.Command{
|
var appBackupCommand = cli.Command{
|
||||||
Name: "backup",
|
Name: "backup",
|
||||||
Aliases: []string{"b"},
|
Aliases: []string{"b"},
|
||||||
Usage: "Manage app backups",
|
Usage: "Manage app backups",
|
||||||
ArgsUsage: "<domain>",
|
UsageText: "abra app backup [command] [options] [arguments]",
|
||||||
Subcommands: []cli.Command{
|
HideHelpCommand: true,
|
||||||
appBackupListCommand,
|
Commands: []*cli.Command{
|
||||||
appBackupSnapshotsCommand,
|
&appBackupListCommand,
|
||||||
appBackupDownloadCommand,
|
&appBackupSnapshotsCommand,
|
||||||
appBackupCreateCommand,
|
&appBackupDownloadCommand,
|
||||||
|
&appBackupCreateCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
appPkg "coopcloud.tech/abra/pkg/app"
|
appPkg "coopcloud.tech/abra/pkg/app"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appCheckCommand = cli.Command{
|
var appCheckCommand = cli.Command{
|
||||||
Name: "check",
|
Name: "check",
|
||||||
Aliases: []string{"chk"},
|
Aliases: []string{"chk"},
|
||||||
Usage: "Ensure an app is well configured",
|
Usage: "Ensure an app is well configured",
|
||||||
Description: `
|
Description: `Compare env vars in both the app ".env" and recipe ".env.sample" file.
|
||||||
This command compares env vars in both the app ".env" and recipe ".env.sample"
|
|
||||||
file.
|
|
||||||
|
|
||||||
The goal is to ensure that recipe ".env.sample" env vars are defined in your
|
The goal is to ensure that recipe ".env.sample" env vars are defined in your
|
||||||
app ".env" file. Only env var definitions in the ".env.sample" which are
|
app ".env" file. Only env var definitions in the ".env.sample" which are
|
||||||
@ -25,16 +25,17 @@ these env vars, then "check" will complain.
|
|||||||
Recipe maintainers may or may not provide defaults for env vars within their
|
Recipe maintainers may or may not provide defaults for env vars within their
|
||||||
recipes regardless of commenting or not (e.g. through the use of
|
recipes regardless of commenting or not (e.g. through the use of
|
||||||
${FOO:<default>} syntax). "check" does not confirm or deny this for you.`,
|
${FOO:<default>} syntax). "check" does not confirm or deny this for you.`,
|
||||||
ArgsUsage: "<domain>",
|
UsageText: "abra app check [options] <domain>",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
internal.OfflineFlag,
|
internal.OfflineFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -14,7 +15,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/client"
|
"coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appCmdCommand = cli.Command{
|
var appCmdCommand = cli.Command{
|
||||||
@ -26,47 +27,45 @@ var appCmdCommand = cli.Command{
|
|||||||
These commands are bash functions, defined in the abra.sh of the recipe itself.
|
These commands are bash functions, defined in the abra.sh of the recipe itself.
|
||||||
They can be run within the context of a service (e.g. app) or locally on your
|
They can be run within the context of a service (e.g. app) or locally on your
|
||||||
work station by passing "--local". Arguments can be passed into these functions
|
work station by passing "--local". Arguments can be passed into these functions
|
||||||
using the "-- <args>" syntax.
|
using the "-- <cmd-args>" syntax.
|
||||||
|
|
||||||
**WARNING**: options must be passed directly after the sub-command "cmd".
|
**WARNING**: [options] must be passed directly after the "cmd" sub-command.`,
|
||||||
|
UsageText: "abra app cmd [options] <domain> [<service>] <cmd> [-- <cmd-args>]",
|
||||||
EXAMPLE:
|
HideHelpCommand: true,
|
||||||
|
|
||||||
abra app cmd --local example.com app create_user -- me@example.com`,
|
|
||||||
ArgsUsage: "<domain> [<service>] <command> [-- <args>]",
|
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.LocalCmdFlag,
|
internal.LocalCmdFlag,
|
||||||
internal.RemoteUserFlag,
|
internal.RemoteUserFlag,
|
||||||
internal.TtyFlag,
|
internal.TtyFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Subcommands: []cli.Command{appCmdListCommand},
|
Commands: []*cli.Command{
|
||||||
BashComplete: func(ctx *cli.Context) {
|
&appCmdListCommand,
|
||||||
args := ctx.Args()
|
},
|
||||||
switch len(args) {
|
EnableShellCompletion: true,
|
||||||
|
ShellComplete: func(ctx context.Context, cmd *cli.Command) {
|
||||||
|
args := cmd.Args()
|
||||||
|
switch args.Len() {
|
||||||
case 0:
|
case 0:
|
||||||
autocomplete.AppNameComplete(ctx)
|
autocomplete.AppNameComplete(ctx, cmd)
|
||||||
case 1:
|
case 1:
|
||||||
autocomplete.ServiceNameComplete(args.Get(0))
|
autocomplete.ServiceNameComplete(args.Get(0))
|
||||||
case 2:
|
case 2:
|
||||||
cmdNameComplete(args.Get(0))
|
cmdNameComplete(args.Get(0))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
app := internal.ValidateApp(c)
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if internal.LocalCmd && internal.RemoteUser != "" {
|
if internal.LocalCmd && internal.RemoteUser != "" {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("cannot use --local & --user together"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("cannot use --local & --user together"))
|
||||||
}
|
}
|
||||||
|
|
||||||
hasCmdArgs, parsedCmdArgs := parseCmdArgs(c.Args(), internal.LocalCmd)
|
hasCmdArgs, parsedCmdArgs := parseCmdArgs(cmd.Args().Slice(), internal.LocalCmd)
|
||||||
|
|
||||||
if _, err := os.Stat(app.Recipe.AbraShPath); err != nil {
|
if _, err := os.Stat(app.Recipe.AbraShPath); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
@ -76,11 +75,11 @@ EXAMPLE:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if internal.LocalCmd {
|
if internal.LocalCmd {
|
||||||
if !(len(c.Args()) >= 2) {
|
if !(cmd.Args().Len() >= 2) {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("missing arguments"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("missing arguments"))
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdName := c.Args().Get(1)
|
cmdName := cmd.Args().Get(1)
|
||||||
if err := internal.EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil {
|
if err := internal.EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -112,13 +111,13 @@ EXAMPLE:
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !(len(c.Args()) >= 3) {
|
if !(cmd.Args().Len() >= 3) {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("missing arguments"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("missing arguments"))
|
||||||
}
|
}
|
||||||
|
|
||||||
targetServiceName := c.Args().Get(1)
|
targetServiceName := cmd.Args().Get(1)
|
||||||
|
|
||||||
cmdName := c.Args().Get(2)
|
cmdName := cmd.Args().Get(2)
|
||||||
if err := internal.EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil {
|
if err := internal.EnsureCommand(app.Recipe.AbraShPath, app.Recipe.Name, cmdName); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -195,19 +194,19 @@ func cmdNameComplete(appName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var appCmdListCommand = cli.Command{
|
var appCmdListCommand = cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
Usage: "List all available commands",
|
Usage: "List all available commands",
|
||||||
ArgsUsage: "<domain>",
|
UsageText: "abra app cmd ls [options] <domain>",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
},
|
},
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Before: internal.SubCommandBefore,
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
Action: func(c *cli.Context) error {
|
Before: internal.SubCommandBefore,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.EnsureExists(); err != nil {
|
if err := app.Recipe.EnsureExists(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -10,24 +11,23 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appConfigCommand = cli.Command{
|
var appConfigCommand = cli.Command{
|
||||||
Name: "config",
|
Name: "config",
|
||||||
Aliases: []string{"cfg"},
|
Aliases: []string{"cfg"},
|
||||||
Usage: "Edit app config",
|
Usage: "Edit app config",
|
||||||
ArgsUsage: "<domain>",
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
UsageText: "abra app config [options] <domain>",
|
||||||
internal.DebugFlag,
|
Before: internal.SubCommandBefore,
|
||||||
},
|
EnableShellCompletion: true,
|
||||||
Before: internal.SubCommandBefore,
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
Action: func(c *cli.Context) error {
|
appName := cmd.Args().First()
|
||||||
appName := c.Args().First()
|
|
||||||
|
|
||||||
if appName == "" {
|
if appName == "" {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("no app provided"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("no app provided"))
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := appPkg.LoadAppFiles("")
|
files, err := appPkg.LoadAppFiles("")
|
||||||
@ -51,11 +51,11 @@ var appConfigCommand = cli.Command{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(ed, appFile.Path)
|
c := exec.Command(ed, appFile.Path)
|
||||||
cmd.Stdin = os.Stdin
|
c.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
c.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
c.Stderr = os.Stderr
|
||||||
if err := cmd.Run(); err != nil {
|
if err := c.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,21 +22,17 @@ import (
|
|||||||
dockerClient "github.com/docker/docker/client"
|
dockerClient "github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appCpCommand = cli.Command{
|
var appCpCommand = cli.Command{
|
||||||
Name: "cp",
|
Name: "cp",
|
||||||
Aliases: []string{"c"},
|
Aliases: []string{"c"},
|
||||||
ArgsUsage: "<domain> <src> <dst>",
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
UsageText: "abra app cp [options] <domain> <src> <dst>",
|
||||||
internal.DebugFlag,
|
Before: internal.SubCommandBefore,
|
||||||
internal.NoInputFlag,
|
Usage: "Copy files to/from a deployed app service",
|
||||||
},
|
Description: `Copy files to and from any app service file system.
|
||||||
Before: internal.SubCommandBefore,
|
|
||||||
Usage: "Copy files to/from a deployed app service",
|
|
||||||
Description: `
|
|
||||||
Copy files to and from any app service file system.
|
|
||||||
|
|
||||||
If you want to copy a myfile.txt to the root of the app service:
|
If you want to copy a myfile.txt to the root of the app service:
|
||||||
|
|
||||||
@ -44,18 +40,17 @@ If you want to copy a myfile.txt to the root of the app service:
|
|||||||
|
|
||||||
And if you want to copy that file back to your current working directory locally:
|
And if you want to copy that file back to your current working directory locally:
|
||||||
|
|
||||||
abra app cp <domain> app:/myfile.txt .
|
abra app cp <domain> app:/myfile.txt`,
|
||||||
`,
|
EnableShellCompletion: true,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
app := internal.ValidateApp(c)
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
src := c.Args().Get(1)
|
src := cmd.Args().Get(1)
|
||||||
dst := c.Args().Get(2)
|
dst := cmd.Args().Get(2)
|
||||||
if src == "" {
|
if src == "" {
|
||||||
log.Fatal("missing <src> argument")
|
log.Fatal("missing <src> argument")
|
||||||
}
|
}
|
||||||
|
@ -15,22 +15,21 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/lint"
|
"coopcloud.tech/abra/pkg/lint"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/upstream/stack"
|
"coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appDeployCommand = cli.Command{
|
var appDeployCommand = cli.Command{
|
||||||
Name: "deploy",
|
Name: "deploy",
|
||||||
Aliases: []string{"d"},
|
Aliases: []string{"d"},
|
||||||
Usage: "Deploy an app",
|
Usage: "Deploy an app",
|
||||||
ArgsUsage: "<domain> [<version>]",
|
ArgsUsage: "<domain> [<version>]",
|
||||||
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra app deploy [options] <domain> [<version>]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.ForceFlag,
|
internal.ForceFlag,
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
internal.NoDomainChecksFlag,
|
internal.NoDomainChecksFlag,
|
||||||
internal.DontWaitConvergeFlag,
|
internal.DontWaitConvergeFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `Deploy an app.
|
Description: `Deploy an app.
|
||||||
@ -38,22 +37,18 @@ var appDeployCommand = cli.Command{
|
|||||||
This command supports chaos operations. Use "--chaos" to deploy your recipe
|
This command supports chaos operations. Use "--chaos" to deploy your recipe
|
||||||
checkout as-is. Recipe commit hashes are also supported values for
|
checkout as-is. Recipe commit hashes are also supported values for
|
||||||
"[<version>]". Please note, "upgrade"/"rollback" do not support chaos
|
"[<version>]". Please note, "upgrade"/"rollback" do not support chaos
|
||||||
operations.
|
operations.`,
|
||||||
|
EnableShellCompletion: true,
|
||||||
EXAMPLE:
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
abra app deploy foo.example.com
|
app := internal.ValidateApp(cmd)
|
||||||
abra app deploy foo.example.com 1.2.3+3.2.1
|
|
||||||
abra app deploy foo.example.com 1e83340e`,
|
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
app := internal.ValidateApp(c)
|
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
specificVersion := c.Args().Get(1)
|
specificVersion := cmd.Args().Get(1)
|
||||||
if specificVersion == "" {
|
if specificVersion == "" {
|
||||||
specificVersion = app.Recipe.Version
|
specificVersion = app.Recipe.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
if specificVersion != "" && internal.Chaos {
|
if specificVersion != "" && internal.Chaos {
|
||||||
log.Fatal("cannot use <version> and --chaos together")
|
log.Fatal("cannot use <version> and --chaos together")
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@ -12,13 +13,14 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/tagcmp"
|
"coopcloud.tech/tagcmp"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
status bool
|
status bool
|
||||||
statusFlag = &cli.BoolFlag{
|
statusFlag = &cli.BoolFlag{
|
||||||
Name: "status, S",
|
Name: "status",
|
||||||
|
Aliases: []string{"S"},
|
||||||
Usage: "Show app deployment status",
|
Usage: "Show app deployment status",
|
||||||
Destination: &status,
|
Destination: &status,
|
||||||
}
|
}
|
||||||
@ -27,7 +29,8 @@ var (
|
|||||||
var (
|
var (
|
||||||
recipeFilter string
|
recipeFilter string
|
||||||
recipeFlag = &cli.StringFlag{
|
recipeFlag = &cli.StringFlag{
|
||||||
Name: "recipe, r",
|
Name: "recipe",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Show apps of a specific recipe",
|
Usage: "Show apps of a specific recipe",
|
||||||
Destination: &recipeFilter,
|
Destination: &recipeFilter,
|
||||||
@ -37,7 +40,8 @@ var (
|
|||||||
var (
|
var (
|
||||||
listAppServer string
|
listAppServer string
|
||||||
listAppServerFlag = &cli.StringFlag{
|
listAppServerFlag = &cli.StringFlag{
|
||||||
Name: "server, s",
|
Name: "server",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Show apps of a specific server",
|
Usage: "Show apps of a specific server",
|
||||||
Destination: &listAppServer,
|
Destination: &listAppServer,
|
||||||
@ -67,26 +71,24 @@ type serverStatus struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var appListCommand = cli.Command{
|
var appListCommand = cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
Usage: "List all managed apps",
|
Usage: "List all managed apps",
|
||||||
Description: `
|
HideHelpCommand: true,
|
||||||
Read the local file system listing of apps and servers (e.g. ~/.abra/) to
|
UsageText: "abra app list [options]",
|
||||||
generate a report of all your apps.
|
Description: `Generate a report of all managed apps.
|
||||||
|
|
||||||
By passing the "--status/-S" flag, you can query all your servers for the
|
By passing the "--status/-S" flag, you can query all your servers for the
|
||||||
actual live deployment status. Depending on how many servers you manage, this
|
actual live deployment status. Depending on how many servers you manage, this
|
||||||
can take some time.`,
|
can take some time.`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
statusFlag,
|
statusFlag,
|
||||||
listAppServerFlag,
|
listAppServerFlag,
|
||||||
recipeFlag,
|
recipeFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
appFiles, err := appPkg.LoadAppFiles(listAppServer)
|
appFiles, err := appPkg.LoadAppFiles(listAppServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -19,23 +19,24 @@ import (
|
|||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
dockerClient "github.com/docker/docker/client"
|
dockerClient "github.com/docker/docker/client"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appLogsCommand = cli.Command{
|
var appLogsCommand = cli.Command{
|
||||||
Name: "logs",
|
Name: "logs",
|
||||||
Aliases: []string{"l"},
|
Aliases: []string{"l"},
|
||||||
ArgsUsage: "<domain> [<service>]",
|
Usage: "Tail app logs",
|
||||||
Usage: "Tail app logs",
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra app logs [options] <domain> [<service>]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.StdErrOnlyFlag,
|
internal.StdErrOnlyFlag,
|
||||||
internal.SinceLogsFlag,
|
internal.SinceLogsFlag,
|
||||||
internal.DebugFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
if err := app.Recipe.EnsureExists(); err != nil {
|
if err := app.Recipe.EnsureExists(); err != nil {
|
||||||
@ -56,7 +57,7 @@ var appLogsCommand = cli.Command{
|
|||||||
log.Fatalf("%s is not deployed?", app.Name)
|
log.Fatalf("%s is not deployed?", app.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceName := c.Args().Get(1)
|
serviceName := cmd.Args().Get(1)
|
||||||
serviceNames := []string{}
|
serviceNames := []string{}
|
||||||
if serviceName != "" {
|
if serviceName != "" {
|
||||||
serviceNames = []string{serviceName}
|
serviceNames = []string{serviceName}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
@ -15,12 +16,13 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/secret"
|
"coopcloud.tech/abra/pkg/secret"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
dockerClient "github.com/docker/docker/client"
|
dockerClient "github.com/docker/docker/client"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appNewDescription = `
|
var appNewDescription = `Creates a new app from a default recipe.
|
||||||
Creates a new app from a default recipe. This new app configuration is stored
|
|
||||||
in your $ABRA_DIR directory under the appropriate server.
|
This new app configuration is stored in your $ABRA_DIR directory under the
|
||||||
|
appropriate server.
|
||||||
|
|
||||||
This command does not deploy your app for you. You will need to run "abra app
|
This command does not deploy your app for you. You will need to run "abra app
|
||||||
deploy <domain>" to do so.
|
deploy <domain>" to do so.
|
||||||
@ -43,28 +45,27 @@ var appNewCommand = cli.Command{
|
|||||||
Usage: "Create a new app",
|
Usage: "Create a new app",
|
||||||
Description: appNewDescription,
|
Description: appNewDescription,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.NewAppServerFlag,
|
internal.NewAppServerFlag,
|
||||||
internal.DomainFlag,
|
internal.DomainFlag,
|
||||||
internal.PassFlag,
|
internal.PassFlag,
|
||||||
internal.SecretsFlag,
|
internal.SecretsFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
ArgsUsage: "[<recipe>] [<version>]",
|
HideHelpCommand: true,
|
||||||
BashComplete: func(ctx *cli.Context) {
|
UsageText: "abra app new [options] [<recipe>] [<version>]",
|
||||||
args := ctx.Args()
|
EnableShellCompletion: true,
|
||||||
switch len(args) {
|
ShellComplete: func(ctx context.Context, cmd *cli.Command) {
|
||||||
|
args := cmd.Args()
|
||||||
|
switch args.Len() {
|
||||||
case 0:
|
case 0:
|
||||||
autocomplete.RecipeNameComplete(ctx)
|
autocomplete.RecipeNameComplete(ctx, cmd)
|
||||||
case 1:
|
case 1:
|
||||||
autocomplete.RecipeVersionComplete(ctx.Args().Get(0))
|
autocomplete.RecipeVersionComplete(cmd.Args().Get(0))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
recipe := internal.ValidateRecipe(c)
|
recipe := internal.ValidateRecipe(cmd)
|
||||||
|
|
||||||
if !internal.Chaos {
|
if !internal.Chaos {
|
||||||
if err := recipe.EnsureIsClean(); err != nil {
|
if err := recipe.EnsureIsClean(); err != nil {
|
||||||
@ -75,7 +76,7 @@ var appNewCommand = cli.Command{
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.Args().Get(1) == "" {
|
if cmd.Args().Get(1) == "" {
|
||||||
var version string
|
var version string
|
||||||
|
|
||||||
recipeVersions, err := recipe.GetRecipeVersions()
|
recipeVersions, err := recipe.GetRecipeVersions()
|
||||||
@ -100,7 +101,7 @@ var appNewCommand = cli.Command{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if _, err := recipe.EnsureVersion(c.Args().Get(1)); err != nil {
|
if _, err := recipe.EnsureVersion(cmd.Args().Get(1)); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,23 +17,24 @@ import (
|
|||||||
containerTypes "github.com/docker/docker/api/types/container"
|
containerTypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
dockerClient "github.com/docker/docker/client"
|
dockerClient "github.com/docker/docker/client"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appPsCommand = cli.Command{
|
var appPsCommand = cli.Command{
|
||||||
Name: "ps",
|
Name: "ps",
|
||||||
Aliases: []string{"p"},
|
Aliases: []string{"p"},
|
||||||
Usage: "Check app status",
|
Usage: "Check app status",
|
||||||
ArgsUsage: "<domain>",
|
HideHelpCommand: true,
|
||||||
Description: "Show status of a deployed app.",
|
UsageText: "abra app ps [options] <domain>",
|
||||||
|
Description: "Show status of a deployed app.",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
internal.DebugFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
if err := app.Recipe.Ensure(false, false); err != nil {
|
if err := app.Recipe.Ensure(false, false); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -12,16 +12,16 @@ import (
|
|||||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appRemoveCommand = cli.Command{
|
var appRemoveCommand = cli.Command{
|
||||||
Name: "remove",
|
Name: "remove",
|
||||||
Aliases: []string{"rm"},
|
Aliases: []string{"rm"},
|
||||||
ArgsUsage: "<domain>",
|
HideHelpCommand: true,
|
||||||
Usage: "Remove all app data, locally and remotely",
|
UsageText: "abra app remove [options] <domain>",
|
||||||
Description: `
|
Usage: "Remove all app data, locally and remotely",
|
||||||
This command removes everything related to an app which is already undeployed.
|
Description: `Remove everything related to an app which is already undeployed.
|
||||||
|
|
||||||
By default, it will prompt for confirmation before proceeding. All secrets,
|
By default, it will prompt for confirmation before proceeding. All secrets,
|
||||||
volumes and the local app env file will be deleted.
|
volumes and the local app env file will be deleted.
|
||||||
@ -39,14 +39,12 @@ To delete everything without prompt, use the "--force/-f" or the "--no-input/n"
|
|||||||
flag.`,
|
flag.`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.ForceFlag,
|
internal.ForceFlag,
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Before: internal.SubCommandBefore,
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
Action: func(c *cli.Context) error {
|
Before: internal.SubCommandBefore,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if !internal.Force && !internal.NoInput {
|
if !internal.Force && !internal.NoInput {
|
||||||
response := false
|
response := false
|
||||||
|
@ -12,41 +12,36 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
upstream "coopcloud.tech/abra/pkg/upstream/service"
|
upstream "coopcloud.tech/abra/pkg/upstream/service"
|
||||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appRestartCommand = cli.Command{
|
var appRestartCommand = cli.Command{
|
||||||
Name: "restart",
|
Name: "restart",
|
||||||
Aliases: []string{"re"},
|
Aliases: []string{"re"},
|
||||||
Usage: "Restart an app",
|
Usage: "Restart an app",
|
||||||
ArgsUsage: "<domain> [<service>]",
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra app restart [options] <domain> [<service>]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.AllServicesFlag,
|
internal.AllServicesFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `
|
Description: `This command restarts services within a deployed app.
|
||||||
This command restarts services within a deployed app.
|
|
||||||
|
|
||||||
Run "abra app ps <domain>" to see a list of service names.
|
Run "abra app ps <domain>" to see a list of service names.
|
||||||
|
|
||||||
Pass "--all-services/-a" to restart all services.
|
Pass "--all-services/-a" to restart all services.`,
|
||||||
|
EnableShellCompletion: true,
|
||||||
EXAMPLE:
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
abra app restart example.com app`,
|
app := internal.ValidateApp(cmd)
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
app := internal.ValidateApp(c)
|
|
||||||
if err := app.Recipe.Ensure(false, false); err != nil {
|
if err := app.Recipe.Ensure(false, false); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceName := c.Args().Get(1)
|
serviceName := cmd.Args().Get(1)
|
||||||
if serviceName == "" && !internal.AllServices {
|
if serviceName == "" && !internal.AllServices {
|
||||||
err := errors.New("missing <service>")
|
err := errors.New("missing <service>")
|
||||||
internal.ShowSubcommandHelpAndError(c, err)
|
internal.ShowSubcommandHelpAndError(cmd, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if serviceName != "" && internal.AllServices {
|
if serviceName != "" && internal.AllServices {
|
||||||
|
@ -1,36 +1,38 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/client"
|
"coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var targetPath string
|
var targetPath string
|
||||||
var targetPathFlag = &cli.StringFlag{
|
var targetPathFlag = &cli.StringFlag{
|
||||||
Name: "target, t",
|
Name: "target",
|
||||||
|
Aliases: []string{"t"},
|
||||||
Usage: "Target path",
|
Usage: "Target path",
|
||||||
Destination: &targetPath,
|
Destination: &targetPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
var appRestoreCommand = cli.Command{
|
var appRestoreCommand = cli.Command{
|
||||||
Name: "restore",
|
Name: "restore",
|
||||||
Aliases: []string{"rs"},
|
Aliases: []string{"rs"},
|
||||||
Usage: "Restore an app backup",
|
Usage: "Restore an app backup",
|
||||||
ArgsUsage: "<domain> <service>",
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra app restore [options] <domain> <service>",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
targetPathFlag,
|
targetPathFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -15,39 +15,32 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/client"
|
"coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appRollbackCommand = cli.Command{
|
var appRollbackCommand = cli.Command{
|
||||||
Name: "rollback",
|
Name: "rollback",
|
||||||
Aliases: []string{"rl"},
|
Aliases: []string{"rl"},
|
||||||
Usage: "Roll an app back to a previous version",
|
Usage: "Roll an app back to a previous version",
|
||||||
ArgsUsage: "<domain> [<version>]",
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra app rollback [options] <domain> [<version>]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.ForceFlag,
|
internal.ForceFlag,
|
||||||
internal.NoDomainChecksFlag,
|
internal.NoDomainChecksFlag,
|
||||||
internal.DontWaitConvergeFlag,
|
internal.DontWaitConvergeFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `
|
Description: `This command rolls an app back to a previous version.
|
||||||
This command rolls an app back to a previous version.
|
|
||||||
|
|
||||||
Unlike "deploy", chaos operations are not supported here. Only recipe versions
|
Unlike "deploy", chaos operations are not supported here. Only recipe versions
|
||||||
are supported values for "[<version>]".
|
are supported values for "[<version>]".
|
||||||
|
|
||||||
A rollback can be destructive, please ensure you have a copy of your app data
|
A rollback can be destructive, please ensure you have a copy of your app data
|
||||||
beforehand.
|
beforehand.`,
|
||||||
|
EnableShellCompletion: true,
|
||||||
EXAMPLE:
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
abra app rollback foo.example.com
|
app := internal.ValidateApp(cmd)
|
||||||
abra app rollback foo.example.com 1.2.3+3.2.1`,
|
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
app := internal.ValidateApp(c)
|
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
@ -85,10 +78,11 @@ EXAMPLE:
|
|||||||
log.Warnf("failed to determine deployed version of %s", app.Name)
|
log.Warnf("failed to determine deployed version of %s", app.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
specificVersion := c.Args().Get(1)
|
specificVersion := cmd.Args().Get(1)
|
||||||
if specificVersion == "" {
|
if specificVersion == "" {
|
||||||
specificVersion = app.Recipe.Version
|
specificVersion = app.Recipe.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
if specificVersion != "" {
|
if specificVersion != "" {
|
||||||
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -14,19 +14,21 @@ import (
|
|||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var user string
|
var user string
|
||||||
var userFlag = &cli.StringFlag{
|
var userFlag = &cli.StringFlag{
|
||||||
Name: "user, u",
|
Name: "user",
|
||||||
|
Aliases: []string{"u"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Destination: &user,
|
Destination: &user,
|
||||||
}
|
}
|
||||||
|
|
||||||
var noTTY bool
|
var noTTY bool
|
||||||
var noTTYFlag = &cli.BoolFlag{
|
var noTTYFlag = &cli.BoolFlag{
|
||||||
Name: "no-tty, t",
|
Name: "no-tty",
|
||||||
|
Aliases: []string{"t"},
|
||||||
Destination: &noTTY,
|
Destination: &noTTY,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,23 +36,24 @@ var appRunCommand = cli.Command{
|
|||||||
Name: "run",
|
Name: "run",
|
||||||
Aliases: []string{"r"},
|
Aliases: []string{"r"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
noTTYFlag,
|
noTTYFlag,
|
||||||
userFlag,
|
userFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
ArgsUsage: "<domain> <service> <args>...",
|
UsageText: "abra app run [options] <domain> <service> <args>",
|
||||||
Usage: "Run a command in a service container",
|
Usage: "Run a command in an app service",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
HideHelpCommand: true,
|
||||||
Action: func(c *cli.Context) error {
|
EnableShellCompletion: true,
|
||||||
app := internal.ValidateApp(c)
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
if len(c.Args()) < 2 {
|
if cmd.Args().Len() < 2 {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("no <service> provided?"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("no <service> provided?"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.Args()) < 3 {
|
if cmd.Args().Len() < 3 {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("no <args> provided?"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("no <args> provided?"))
|
||||||
}
|
}
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
cl, err := client.New(app.Server)
|
||||||
@ -58,7 +61,7 @@ var appRunCommand = cli.Command{
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceName := c.Args().Get(1)
|
serviceName := cmd.Args().Get(1)
|
||||||
stackAndServiceName := fmt.Sprintf("^%s_%s", app.StackName(), serviceName)
|
stackAndServiceName := fmt.Sprintf("^%s_%s", app.StackName(), serviceName)
|
||||||
filters := filters.NewArgs()
|
filters := filters.NewArgs()
|
||||||
filters.Add("name", stackAndServiceName)
|
filters.Add("name", stackAndServiceName)
|
||||||
@ -68,12 +71,12 @@ var appRunCommand = cli.Command{
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := c.Args()[2:]
|
c := cmd.Args().Slice()[2:]
|
||||||
execCreateOpts := types.ExecConfig{
|
execCreateOpts := types.ExecConfig{
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
AttachStdin: true,
|
AttachStdin: true,
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
Cmd: cmd,
|
Cmd: c,
|
||||||
Detach: false,
|
Detach: false,
|
||||||
Tty: true,
|
Tty: true,
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,14 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/secret"
|
"coopcloud.tech/abra/pkg/secret"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
dockerClient "github.com/docker/docker/client"
|
dockerClient "github.com/docker/docker/client"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
allSecrets bool
|
allSecrets bool
|
||||||
allSecretsFlag = &cli.BoolFlag{
|
allSecretsFlag = &cli.BoolFlag{
|
||||||
Name: "all, a",
|
Name: "all",
|
||||||
|
Aliases: []string{"a"},
|
||||||
Destination: &allSecrets,
|
Destination: &allSecrets,
|
||||||
Usage: "Generate all secrets",
|
Usage: "Generate all secrets",
|
||||||
}
|
}
|
||||||
@ -32,41 +33,42 @@ var (
|
|||||||
var (
|
var (
|
||||||
rmAllSecrets bool
|
rmAllSecrets bool
|
||||||
rmAllSecretsFlag = &cli.BoolFlag{
|
rmAllSecretsFlag = &cli.BoolFlag{
|
||||||
Name: "all, a",
|
Name: "all",
|
||||||
|
Aliases: []string{"a"},
|
||||||
Destination: &rmAllSecrets,
|
Destination: &rmAllSecrets,
|
||||||
Usage: "Remove all secrets",
|
Usage: "Remove all secrets",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var appSecretGenerateCommand = cli.Command{
|
var appSecretGenerateCommand = cli.Command{
|
||||||
Name: "generate",
|
Name: "generate",
|
||||||
Aliases: []string{"g"},
|
Aliases: []string{"g"},
|
||||||
Usage: "Generate secrets",
|
Usage: "Generate secrets",
|
||||||
ArgsUsage: "<domain> <secret> <version>",
|
UsageText: "abra app secret generate [options] <domain> <secret> <version>",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
allSecretsFlag,
|
allSecretsFlag,
|
||||||
internal.PassFlag,
|
internal.PassFlag,
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.Args()) == 1 && !allSecrets {
|
if cmd.Args().Len() == 1 && !allSecrets {
|
||||||
err := errors.New("missing arguments <secret>/<version> or '--all'")
|
err := errors.New("missing arguments <secret>/<version> or '--all'")
|
||||||
internal.ShowSubcommandHelpAndError(c, err)
|
internal.ShowSubcommandHelpAndError(cmd, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Args().Get(1) != "" && allSecrets {
|
if cmd.Args().Get(1) != "" && allSecrets {
|
||||||
err := errors.New("cannot use '<secret> <version>' and '--all' together")
|
err := errors.New("cannot use '<secret> <version>' and '--all' together")
|
||||||
internal.ShowSubcommandHelpAndError(c, err)
|
internal.ShowSubcommandHelpAndError(cmd, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
|
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
|
||||||
@ -80,8 +82,8 @@ var appSecretGenerateCommand = cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !allSecrets {
|
if !allSecrets {
|
||||||
secretName := c.Args().Get(1)
|
secretName := cmd.Args().Get(1)
|
||||||
secretVersion := c.Args().Get(2)
|
secretVersion := cmd.Args().Get(2)
|
||||||
s, ok := secrets[secretName]
|
s, ok := secrets[secretName]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Fatalf("%s doesn't exist in the env config?", secretName)
|
log.Fatalf("%s doesn't exist in the env config?", secretName)
|
||||||
@ -142,26 +144,21 @@ var appSecretInsertCommand = cli.Command{
|
|||||||
internal.FileFlag,
|
internal.FileFlag,
|
||||||
internal.TrimFlag,
|
internal.TrimFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
ArgsUsage: "<domain> <secret-name> <version> <data>",
|
UsageText: "abra app secret insert [options] <domain> <secret> <version> <data>",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
HideHelpCommand: true,
|
||||||
Description: `
|
EnableShellCompletion: true,
|
||||||
This command inserts a secret into an app environment.
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
|
Description: `This command inserts a secret into an app environment.
|
||||||
|
|
||||||
This can be useful when you want to manually generate secrets for an app
|
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
|
environment. Typically, you can let Abra generate them for you on app creation
|
||||||
(see "abra app new --secrets" for more).
|
(see "abra app new --secrets" for more).`,
|
||||||
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
Example:
|
if cmd.Args().Len() != 4 {
|
||||||
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("missing arguments?"))
|
||||||
abra app secret insert myapp db_pass v1 mySecretPassword
|
|
||||||
|
|
||||||
`,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
app := internal.ValidateApp(c)
|
|
||||||
|
|
||||||
if len(c.Args()) != 4 {
|
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("missing arguments?"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
cl, err := client.New(app.Server)
|
||||||
@ -169,9 +166,9 @@ Example:
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
name := c.Args().Get(1)
|
name := cmd.Args().Get(1)
|
||||||
version := c.Args().Get(2)
|
version := cmd.Args().Get(2)
|
||||||
data := c.Args().Get(3)
|
data := cmd.Args().Get(3)
|
||||||
|
|
||||||
if internal.File {
|
if internal.File {
|
||||||
raw, err := os.ReadFile(data)
|
raw, err := os.ReadFile(data)
|
||||||
@ -233,9 +230,10 @@ var appSecretRmCommand = cli.Command{
|
|||||||
internal.OfflineFlag,
|
internal.OfflineFlag,
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
ArgsUsage: "<domain> [<secret-name>]",
|
ArgsUsage: "<domain> [<secret-name>]",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
Description: `
|
Description: `
|
||||||
This command removes app secrets.
|
This command removes app secrets.
|
||||||
|
|
||||||
@ -243,8 +241,8 @@ Example:
|
|||||||
|
|
||||||
abra app secret remove myapp db_pass
|
abra app secret remove myapp db_pass
|
||||||
`,
|
`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
app := internal.ValidateApp(c)
|
app := internal.ValidateApp(cmd)
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -259,12 +257,12 @@ Example:
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Args().Get(1) != "" && rmAllSecrets {
|
if cmd.Args().Get(1) != "" && rmAllSecrets {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("cannot use '<secret-name>' and '--all' together"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("cannot use '<secret-name>' and '--all' together"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Args().Get(1) == "" && !rmAllSecrets {
|
if cmd.Args().Get(1) == "" && !rmAllSecrets {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("no secret(s) specified?"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("no secret(s) specified?"))
|
||||||
}
|
}
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
cl, err := client.New(app.Server)
|
||||||
@ -288,7 +286,7 @@ Example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
match := false
|
match := false
|
||||||
secretToRm := c.Args().Get(1)
|
secretToRm := cmd.Args().Get(1)
|
||||||
for secretName, val := range secrets {
|
for secretName, val := range secrets {
|
||||||
secretRemoteName := fmt.Sprintf("%s_%s_%s", app.StackName(), secretName, val.Version)
|
secretRemoteName := fmt.Sprintf("%s_%s_%s", app.StackName(), secretName, val.Version)
|
||||||
if _, ok := remoteSecretNames[secretRemoteName]; ok {
|
if _, ok := remoteSecretNames[secretRemoteName]; ok {
|
||||||
@ -331,11 +329,12 @@ var appSecretLsCommand = cli.Command{
|
|||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Usage: "List all secrets",
|
Usage: "List all secrets",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -378,14 +377,15 @@ var appSecretLsCommand = cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var appSecretCommand = cli.Command{
|
var appSecretCommand = cli.Command{
|
||||||
Name: "secret",
|
Name: "secret",
|
||||||
Aliases: []string{"s"},
|
Aliases: []string{"s"},
|
||||||
Usage: "Manage app secrets",
|
Usage: "Manage app secrets",
|
||||||
ArgsUsage: "<domain>",
|
HideHelpCommand: true,
|
||||||
Subcommands: []cli.Command{
|
UsageText: "abra app secret [command] [options] [arguments]",
|
||||||
appSecretGenerateCommand,
|
Commands: []*cli.Command{
|
||||||
appSecretInsertCommand,
|
&appSecretGenerateCommand,
|
||||||
appSecretRmCommand,
|
&appSecretInsertCommand,
|
||||||
appSecretLsCommand,
|
&appSecretRmCommand,
|
||||||
|
&appSecretLsCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -13,21 +13,20 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/service"
|
"coopcloud.tech/abra/pkg/service"
|
||||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
containerTypes "github.com/docker/docker/api/types/container"
|
containerTypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appServicesCommand = cli.Command{
|
var appServicesCommand = cli.Command{
|
||||||
Name: "services",
|
Name: "services",
|
||||||
Aliases: []string{"sr"},
|
Aliases: []string{"sr"},
|
||||||
Usage: "Display all services of an app",
|
Usage: "Display all services of an app",
|
||||||
ArgsUsage: "<domain>",
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
UsageText: "abra app services [options] <domain>",
|
||||||
internal.DebugFlag,
|
Before: internal.SubCommandBefore,
|
||||||
},
|
EnableShellCompletion: true,
|
||||||
Before: internal.SubCommandBefore,
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
Action: func(c *cli.Context) error {
|
app := internal.ValidateApp(cmd)
|
||||||
app := internal.ValidateApp(c)
|
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -13,13 +13,14 @@ import (
|
|||||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
dockerClient "github.com/docker/docker/client"
|
dockerClient "github.com/docker/docker/client"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var prune bool
|
var prune bool
|
||||||
|
|
||||||
var pruneFlag = &cli.BoolFlag{
|
var pruneFlag = &cli.BoolFlag{
|
||||||
Name: "prune, p",
|
Name: "prune",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Destination: &prune,
|
Destination: &prune,
|
||||||
Usage: "Prunes unused containers, networks, and dangling images for an app",
|
Usage: "Prunes unused containers, networks, and dangling images for an app",
|
||||||
}
|
}
|
||||||
@ -61,26 +62,25 @@ func pruneApp(cl *dockerClient.Client, app appPkg.App) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var appUndeployCommand = cli.Command{
|
var appUndeployCommand = cli.Command{
|
||||||
Name: "undeploy",
|
Name: "undeploy",
|
||||||
Aliases: []string{"un"},
|
Aliases: []string{"un"},
|
||||||
ArgsUsage: "<domain>",
|
UsageText: "abra app undeploy [options] <domain>",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
pruneFlag,
|
pruneFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Usage: "Undeploy an app",
|
Usage: "Undeploy an app",
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Description: `
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
This does not destroy any of the application data.
|
Description: `This does not destroy any of the application data.
|
||||||
|
|
||||||
However, you should remain vigilant, as your swarm installation will consider
|
However, you should remain vigilant, as your swarm installation will consider
|
||||||
any previously attached volumes as eligible for pruning once undeployed.
|
any previously attached volumes as eligible for pruning once undeployed.
|
||||||
|
|
||||||
Passing "-p/--prune" does not remove those volumes.`,
|
Passing "-p/--prune" does not remove those volumes.`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
app := internal.ValidateApp(c)
|
app := internal.ValidateApp(cmd)
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -14,40 +14,33 @@ import (
|
|||||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
"coopcloud.tech/tagcmp"
|
"coopcloud.tech/tagcmp"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appUpgradeCommand = cli.Command{
|
var appUpgradeCommand = cli.Command{
|
||||||
Name: "upgrade",
|
Name: "upgrade",
|
||||||
Aliases: []string{"up"},
|
Aliases: []string{"up"},
|
||||||
Usage: "Upgrade an app",
|
Usage: "Upgrade an app",
|
||||||
ArgsUsage: "<domain> [<version>]",
|
UsageText: "abra app upgrade [options] <domain> [<version>]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.ForceFlag,
|
internal.ForceFlag,
|
||||||
internal.NoDomainChecksFlag,
|
internal.NoDomainChecksFlag,
|
||||||
internal.DontWaitConvergeFlag,
|
internal.DontWaitConvergeFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.ReleaseNotesFlag,
|
internal.ReleaseNotesFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `
|
Description: `Upgrade an app.
|
||||||
Upgrade an app.
|
|
||||||
|
|
||||||
Unlike "deploy", chaos operations are not supported here. Only recipe versions
|
Unlike "deploy", chaos operations are not supported here. Only recipe versions
|
||||||
are supported values for "[<version>]".
|
are supported values for "[<version>]".
|
||||||
|
|
||||||
An upgrade can be destructive, please ensure you have a copy of your app data
|
An upgrade can be destructive, please ensure you have a copy of your app data
|
||||||
beforehand.
|
beforehand.`,
|
||||||
|
EnableShellCompletion: true,
|
||||||
EXAMPLE:
|
HideHelpCommand: true,
|
||||||
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
abra app upgrade foo.example.com
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
abra app upgrade foo.example.com 1.2.3+3.2.1`,
|
app := internal.ValidateApp(cmd)
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
app := internal.ValidateApp(c)
|
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
@ -85,7 +78,7 @@ EXAMPLE:
|
|||||||
log.Warnf("failed to determine deployed version of %s", app.Name)
|
log.Warnf("failed to determine deployed version of %s", app.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
specificVersion := c.Args().Get(1)
|
specificVersion := cmd.Args().Get(1)
|
||||||
if specificVersion != "" {
|
if specificVersion != "" {
|
||||||
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,22 +10,20 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/upstream/stack"
|
"coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appVolumeListCommand = cli.Command{
|
var appVolumeListCommand = cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
ArgsUsage: "<domain>",
|
UsageText: "abra app volume list [options] <domain>",
|
||||||
Flags: []cli.Flag{
|
Before: internal.SubCommandBefore,
|
||||||
internal.DebugFlag,
|
Usage: "List volumes associated with an app",
|
||||||
internal.NoInputFlag,
|
HideHelpCommand: true,
|
||||||
},
|
EnableShellCompletion: true,
|
||||||
Before: internal.SubCommandBefore,
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
Usage: "List volumes associated with an app",
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
app := internal.ValidateApp(cmd)
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
app := internal.ValidateApp(c)
|
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
cl, err := client.New(app.Server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,27 +62,28 @@ var appVolumeListCommand = cli.Command{
|
|||||||
var appVolumeRemoveCommand = cli.Command{
|
var appVolumeRemoveCommand = cli.Command{
|
||||||
Name: "remove",
|
Name: "remove",
|
||||||
Usage: "Remove volume(s) associated with an app",
|
Usage: "Remove volume(s) associated with an app",
|
||||||
Description: `
|
Description: `Memove volumes associated with an app.
|
||||||
This command supports removing volumes associated with an app. The app in
|
|
||||||
question must be undeployed before you try to remove volumes. See "abra app
|
The app in question must be undeployed before you try to remove volumes. See
|
||||||
undeploy <domain>" for more.
|
"abra app undeploy <domain>" for more.
|
||||||
|
|
||||||
The command is interactive and will show a multiple select input which allows
|
The command is interactive and will show a multiple select input which allows
|
||||||
you to make a seclection. Use the "?" key to see more help on navigating this
|
you to make a seclection. Use the "?" key to see more help on navigating this
|
||||||
interface.
|
interface.
|
||||||
|
|
||||||
Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
||||||
ArgsUsage: "<domain>",
|
HideHelpCommand: true,
|
||||||
Aliases: []string{"rm"},
|
UsageText: "abra app volume remove [options] <domain>",
|
||||||
|
Aliases: []string{"rm"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
internal.NoInputFlag,
|
||||||
internal.ForceFlag,
|
internal.ForceFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.AppNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.AppNameComplete,
|
||||||
app := internal.ValidateApp(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
app := internal.ValidateApp(cmd)
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
cl, err := client.New(app.Server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -145,12 +144,13 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var appVolumeCommand = cli.Command{
|
var appVolumeCommand = cli.Command{
|
||||||
Name: "volume",
|
Name: "volume",
|
||||||
Aliases: []string{"vl"},
|
Aliases: []string{"vl"},
|
||||||
Usage: "Manage app volumes",
|
Usage: "Manage app volumes",
|
||||||
ArgsUsage: "<domain>",
|
UsageText: "abra app volume [command] [options] [arguments]",
|
||||||
Subcommands: []cli.Command{
|
HideHelpCommand: true,
|
||||||
appVolumeListCommand,
|
Commands: []*cli.Command{
|
||||||
appVolumeRemoveCommand,
|
&appVolumeListCommand,
|
||||||
|
&appVolumeRemoveCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package catalogue
|
package catalogue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -15,25 +16,23 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var catalogueGenerateCommand = cli.Command{
|
var catalogueGenerateCommand = cli.Command{
|
||||||
Name: "generate",
|
Name: "generate",
|
||||||
Aliases: []string{"g"},
|
Aliases: []string{"g"},
|
||||||
Usage: "Generate the recipe catalogue",
|
Usage: "Generate the recipe catalogue",
|
||||||
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra catalogue generate [options] [<recipe>]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.PublishFlag,
|
internal.PublishFlag,
|
||||||
internal.DryFlag,
|
internal.DryFlag,
|
||||||
internal.SkipUpdatesFlag,
|
internal.SkipUpdatesFlag,
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `
|
Description: `Generate a new copy of the recipe catalogue.
|
||||||
Generate a new copy of the recipe catalogue.
|
|
||||||
|
|
||||||
It is possible to generate new metadata for a single recipe by passing
|
It is possible to generate new metadata for a single recipe by passing
|
||||||
<recipe>. The existing local catalogue will be updated, not overwritten.
|
<recipe>. The existing local catalogue will be updated, not overwritten.
|
||||||
@ -45,14 +44,14 @@ If you have a Hub account you can have Abra log you in to avoid this. Pass
|
|||||||
Push your new release to git.coopcloud.tech with "-p/--publish". This requires
|
Push your new release to git.coopcloud.tech with "-p/--publish". This requires
|
||||||
that you have permission to git push to these repositories and have your SSH
|
that you have permission to git push to these repositories and have your SSH
|
||||||
keys configured on your account.`,
|
keys configured on your account.`,
|
||||||
ArgsUsage: "[<recipe>]",
|
EnableShellCompletion: true,
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
recipeName := c.Args().First()
|
recipeName := cmd.Args().First()
|
||||||
r := recipe.Get(recipeName)
|
r := recipe.Get(recipeName)
|
||||||
|
|
||||||
if recipeName != "" {
|
if recipeName != "" {
|
||||||
internal.ValidateRecipe(c)
|
internal.ValidateRecipe(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !internal.Chaos {
|
if !internal.Chaos {
|
||||||
@ -205,11 +204,12 @@ keys configured on your account.`,
|
|||||||
|
|
||||||
// CatalogueCommand defines the `abra catalogue` command and sub-commands.
|
// CatalogueCommand defines the `abra catalogue` command and sub-commands.
|
||||||
var CatalogueCommand = cli.Command{
|
var CatalogueCommand = cli.Command{
|
||||||
Name: "catalogue",
|
Name: "catalogue",
|
||||||
Usage: "Manage the recipe catalogue",
|
Usage: "Manage the recipe catalogue",
|
||||||
Aliases: []string{"c"},
|
Aliases: []string{"c"},
|
||||||
ArgsUsage: "<recipe>",
|
HideHelpCommand: true,
|
||||||
Subcommands: []cli.Command{
|
UsageText: "abra catalogue [command] [options] [arguments]",
|
||||||
catalogueGenerateCommand,
|
Commands: []*cli.Command{
|
||||||
|
&catalogueGenerateCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
96
cli/cli.go
96
cli/cli.go
@ -2,6 +2,7 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -18,7 +19,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/web"
|
"coopcloud.tech/abra/pkg/web"
|
||||||
charmLog "github.com/charmbracelet/log"
|
charmLog "github.com/charmbracelet/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AutoCompleteCommand helps people set up auto-complete in their shells
|
// AutoCompleteCommand helps people set up auto-complete in their shells
|
||||||
@ -26,23 +27,15 @@ var AutoCompleteCommand = cli.Command{
|
|||||||
Name: "autocomplete",
|
Name: "autocomplete",
|
||||||
Aliases: []string{"ac"},
|
Aliases: []string{"ac"},
|
||||||
Usage: "Configure shell autocompletion",
|
Usage: "Configure shell autocompletion",
|
||||||
Description: `
|
Description: `Set up shell auto-completion.
|
||||||
Set up shell auto-completion.
|
|
||||||
|
|
||||||
Supported shells are: bash, fish, fizsh & zsh.
|
Supported shells are: bash, fish, fizsh & zsh.`,
|
||||||
|
|
||||||
EXAMPLE:
|
|
||||||
|
|
||||||
abra autocomplete bash`,
|
|
||||||
ArgsUsage: "<shell>",
|
ArgsUsage: "<shell>",
|
||||||
Flags: []cli.Flag{
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
internal.DebugFlag,
|
shellType := cmd.Args().First()
|
||||||
},
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
shellType := c.Args().First()
|
|
||||||
|
|
||||||
if shellType == "" {
|
if shellType == "" {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("no shell provided"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("no shell provided"))
|
||||||
}
|
}
|
||||||
|
|
||||||
supportedShells := map[string]bool{
|
supportedShells := map[string]bool{
|
||||||
@ -113,30 +106,24 @@ var UpgradeCommand = cli.Command{
|
|||||||
Name: "upgrade",
|
Name: "upgrade",
|
||||||
Aliases: []string{"u"},
|
Aliases: []string{"u"},
|
||||||
Usage: "Upgrade abra",
|
Usage: "Upgrade abra",
|
||||||
Description: `
|
Description: `Upgrade abra in-place with the latest stable or release candidate.
|
||||||
Upgrade abra in-place with the latest stable or release candidate.
|
|
||||||
|
|
||||||
Use "-r/--rc" to install the latest release candidate. Please bear in mind that
|
Use "-r/--rc" to install the latest release candidate. Please bear in mind that
|
||||||
it may contain absolutely catastrophic deal-breaker bugs. Thank you very much
|
it may contain absolutely catastrophic deal-breaker bugs. Thank you very much
|
||||||
for the testing efforts 💗
|
for the testing efforts 💗`,
|
||||||
|
|
||||||
EXAMPLE:
|
|
||||||
|
|
||||||
abra upgrade
|
|
||||||
abra upgrade --rc`,
|
|
||||||
Flags: []cli.Flag{internal.RCFlag},
|
Flags: []cli.Flag{internal.RCFlag},
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
mainURL := "https://install.abra.coopcloud.tech"
|
mainURL := "https://install.abra.coopcloud.tech"
|
||||||
cmd := exec.Command("bash", "-c", fmt.Sprintf("wget -q -O- %s | bash", mainURL))
|
c := exec.Command("bash", "-c", fmt.Sprintf("wget -q -O- %s | bash", mainURL))
|
||||||
|
|
||||||
if internal.RC {
|
if internal.RC {
|
||||||
releaseCandidateURL := "https://git.coopcloud.tech/coop-cloud/abra/raw/branch/main/scripts/installer/installer"
|
releaseCandidateURL := "https://git.coopcloud.tech/coop-cloud/abra/raw/branch/main/scripts/installer/installer"
|
||||||
cmd = exec.Command("bash", "-c", fmt.Sprintf("wget -q -O- %s | bash -s -- --rc", releaseCandidateURL))
|
c = exec.Command("bash", "-c", fmt.Sprintf("wget -q -O- %s | bash -s -- --rc", releaseCandidateURL))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("attempting to run %s", cmd)
|
log.Debugf("attempting to run %s", c)
|
||||||
|
|
||||||
if err := internal.RunCmd(cmd); err != nil {
|
if err := internal.RunCmd(c); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,32 +131,32 @@ EXAMPLE:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAbraApp(version, commit string) *cli.App {
|
func newAbraApp(version, commit string) *cli.Command {
|
||||||
app := &cli.App{
|
app := &cli.Command{
|
||||||
Name: "abra",
|
Name: "abra",
|
||||||
Usage: `the Co-op Cloud command-line utility belt 🎩🐇
|
Usage: "The Co-op Cloud command-line utility belt 🎩🐇",
|
||||||
____ ____ _ _
|
UsageText: "abra [command] [options] [arguments]",
|
||||||
/ ___|___ ___ _ __ / ___| | ___ _ _ __| |
|
Version: fmt.Sprintf("%s-%s", version, commit[:7]),
|
||||||
| | / _ \ _____ / _ \| '_ \ | | | |/ _ \| | | |/ _' |
|
Flags: []cli.Flag{
|
||||||
| |__| (_) |_____| (_) | |_) | | |___| | (_) | |_| | (_| |
|
internal.DebugFlag,
|
||||||
\____\___/ \___/| .__/ \____|_|\___/ \__,_|\__,_|
|
internal.OfflineFlag,
|
||||||
|_|
|
internal.NoInputFlag,
|
||||||
`,
|
|
||||||
Version: fmt.Sprintf("%s-%s", version, commit[:7]),
|
|
||||||
Commands: []cli.Command{
|
|
||||||
app.AppCommand,
|
|
||||||
server.ServerCommand,
|
|
||||||
recipe.RecipeCommand,
|
|
||||||
catalogue.CatalogueCommand,
|
|
||||||
UpgradeCommand,
|
|
||||||
AutoCompleteCommand,
|
|
||||||
},
|
},
|
||||||
BashComplete: autocomplete.SubcommandComplete,
|
Commands: []*cli.Command{
|
||||||
|
&app.AppCommand,
|
||||||
|
&server.ServerCommand,
|
||||||
|
&recipe.RecipeCommand,
|
||||||
|
&catalogue.CatalogueCommand,
|
||||||
|
&UpgradeCommand,
|
||||||
|
&AutoCompleteCommand,
|
||||||
|
},
|
||||||
|
EnableShellCompletion: true,
|
||||||
|
UseShortOptionHandling: true,
|
||||||
|
HideHelpCommand: true,
|
||||||
|
ShellComplete: autocomplete.SubcommandComplete,
|
||||||
}
|
}
|
||||||
|
|
||||||
app.EnableBashCompletion = true
|
app.Before = func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
|
||||||
app.Before = func(c *cli.Context) error {
|
|
||||||
paths := []string{
|
paths := []string{
|
||||||
config.ABRA_DIR,
|
config.ABRA_DIR,
|
||||||
config.SERVERS_DIR,
|
config.SERVERS_DIR,
|
||||||
@ -193,6 +180,13 @@ func newAbraApp(version, commit string) *cli.App {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cli.HelpFlag = &cli.BoolFlag{
|
||||||
|
Name: "help",
|
||||||
|
Aliases: []string{"h, H"},
|
||||||
|
Usage: "Show help",
|
||||||
|
Persistent: true,
|
||||||
|
}
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +194,7 @@ func newAbraApp(version, commit string) *cli.App {
|
|||||||
func RunApp(version, commit string) {
|
func RunApp(version, commit string) {
|
||||||
app := newAbraApp(version, commit)
|
app := newAbraApp(version, commit)
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(context.Background(), os.Args); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Secrets stores the variable from SecretsFlag
|
// Secrets stores the variable from SecretsFlag
|
||||||
@ -12,7 +13,8 @@ var Secrets bool
|
|||||||
|
|
||||||
// SecretsFlag turns on/off automatically generating secrets
|
// SecretsFlag turns on/off automatically generating secrets
|
||||||
var SecretsFlag = &cli.BoolFlag{
|
var SecretsFlag = &cli.BoolFlag{
|
||||||
Name: "secrets, S",
|
Name: "secrets",
|
||||||
|
Aliases: []string{"S"},
|
||||||
Usage: "Automatically generate secrets",
|
Usage: "Automatically generate secrets",
|
||||||
Destination: &Secrets,
|
Destination: &Secrets,
|
||||||
}
|
}
|
||||||
@ -22,7 +24,8 @@ var Pass bool
|
|||||||
|
|
||||||
// PassFlag turns on/off storing generated secrets in pass
|
// PassFlag turns on/off storing generated secrets in pass
|
||||||
var PassFlag = &cli.BoolFlag{
|
var PassFlag = &cli.BoolFlag{
|
||||||
Name: "pass, p",
|
Name: "pass",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Usage: "Store the generated secrets in a local pass store",
|
Usage: "Store the generated secrets in a local pass store",
|
||||||
Destination: &Pass,
|
Destination: &Pass,
|
||||||
}
|
}
|
||||||
@ -32,21 +35,24 @@ var PassRemove bool
|
|||||||
|
|
||||||
// PassRemoveFlag turns on/off removing generated secrets from pass
|
// PassRemoveFlag turns on/off removing generated secrets from pass
|
||||||
var PassRemoveFlag = &cli.BoolFlag{
|
var PassRemoveFlag = &cli.BoolFlag{
|
||||||
Name: "pass, p",
|
Name: "pass",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Usage: "Remove generated secrets from a local pass store",
|
Usage: "Remove generated secrets from a local pass store",
|
||||||
Destination: &PassRemove,
|
Destination: &PassRemove,
|
||||||
}
|
}
|
||||||
|
|
||||||
var File bool
|
var File bool
|
||||||
var FileFlag = &cli.BoolFlag{
|
var FileFlag = &cli.BoolFlag{
|
||||||
Name: "file, f",
|
Name: "file",
|
||||||
|
Aliases: []string{"f"},
|
||||||
Usage: "Treat input as a file",
|
Usage: "Treat input as a file",
|
||||||
Destination: &File,
|
Destination: &File,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Trim bool
|
var Trim bool
|
||||||
var TrimFlag = &cli.BoolFlag{
|
var TrimFlag = &cli.BoolFlag{
|
||||||
Name: "trim, t",
|
Name: "trim",
|
||||||
|
Aliases: []string{"t"},
|
||||||
Usage: "Trim input",
|
Usage: "Trim input",
|
||||||
Destination: &Trim,
|
Destination: &Trim,
|
||||||
}
|
}
|
||||||
@ -56,7 +62,8 @@ var Force bool
|
|||||||
|
|
||||||
// ForceFlag turns on/off force functionality.
|
// ForceFlag turns on/off force functionality.
|
||||||
var ForceFlag = &cli.BoolFlag{
|
var ForceFlag = &cli.BoolFlag{
|
||||||
Name: "force, f",
|
Name: "force",
|
||||||
|
Aliases: []string{"f"},
|
||||||
Usage: "Perform action without further prompt. Use with care!",
|
Usage: "Perform action without further prompt. Use with care!",
|
||||||
Destination: &Force,
|
Destination: &Force,
|
||||||
}
|
}
|
||||||
@ -66,7 +73,8 @@ var Chaos bool
|
|||||||
|
|
||||||
// ChaosFlag turns on/off chaos functionality.
|
// ChaosFlag turns on/off chaos functionality.
|
||||||
var ChaosFlag = &cli.BoolFlag{
|
var ChaosFlag = &cli.BoolFlag{
|
||||||
Name: "chaos, C",
|
Name: "chaos",
|
||||||
|
Aliases: []string{"C"},
|
||||||
Usage: "Proceed with uncommitted recipes changes. Use with care!",
|
Usage: "Proceed with uncommitted recipes changes. Use with care!",
|
||||||
Destination: &Chaos,
|
Destination: &Chaos,
|
||||||
}
|
}
|
||||||
@ -76,16 +84,19 @@ var Tty bool
|
|||||||
|
|
||||||
// TtyFlag turns on/off tty mode.
|
// TtyFlag turns on/off tty mode.
|
||||||
var TtyFlag = &cli.BoolFlag{
|
var TtyFlag = &cli.BoolFlag{
|
||||||
Name: "tty, T",
|
Name: "tty",
|
||||||
|
Aliases: []string{"T"},
|
||||||
Usage: "Disables TTY mode to run this command from a script.",
|
Usage: "Disables TTY mode to run this command from a script.",
|
||||||
Destination: &Tty,
|
Destination: &Tty,
|
||||||
}
|
}
|
||||||
|
|
||||||
var NoInput bool
|
var NoInput bool
|
||||||
var NoInputFlag = &cli.BoolFlag{
|
var NoInputFlag = &cli.BoolFlag{
|
||||||
Name: "no-input, n",
|
Name: "no-input",
|
||||||
|
Aliases: []string{"n"},
|
||||||
Usage: "Toggle non-interactive mode",
|
Usage: "Toggle non-interactive mode",
|
||||||
Destination: &NoInput,
|
Destination: &NoInput,
|
||||||
|
Persistent: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug stores the variable from DebugFlag.
|
// Debug stores the variable from DebugFlag.
|
||||||
@ -93,8 +104,10 @@ var Debug bool
|
|||||||
|
|
||||||
// DebugFlag turns on/off verbose logging down to the DEBUG level.
|
// DebugFlag turns on/off verbose logging down to the DEBUG level.
|
||||||
var DebugFlag = &cli.BoolFlag{
|
var DebugFlag = &cli.BoolFlag{
|
||||||
Name: "debug, d",
|
Name: "debug",
|
||||||
|
Aliases: []string{"d"},
|
||||||
Destination: &Debug,
|
Destination: &Debug,
|
||||||
|
Persistent: true,
|
||||||
Usage: "Show DEBUG messages",
|
Usage: "Show DEBUG messages",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +116,11 @@ var Offline bool
|
|||||||
|
|
||||||
// DebugFlag turns on/off offline mode.
|
// DebugFlag turns on/off offline mode.
|
||||||
var OfflineFlag = &cli.BoolFlag{
|
var OfflineFlag = &cli.BoolFlag{
|
||||||
Name: "offline, o",
|
Name: "offline",
|
||||||
|
Aliases: []string{"o"},
|
||||||
Destination: &Offline,
|
Destination: &Offline,
|
||||||
Usage: "Prefer offline & filesystem access when possible",
|
Usage: "Prefer offline & filesystem access when possible",
|
||||||
|
Persistent: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReleaseNotes stores the variable from ReleaseNotesFlag.
|
// ReleaseNotes stores the variable from ReleaseNotesFlag.
|
||||||
@ -113,7 +128,8 @@ var ReleaseNotes bool
|
|||||||
|
|
||||||
// ReleaseNotesFlag turns on/off printing only release notes when upgrading.
|
// ReleaseNotesFlag turns on/off printing only release notes when upgrading.
|
||||||
var ReleaseNotesFlag = &cli.BoolFlag{
|
var ReleaseNotesFlag = &cli.BoolFlag{
|
||||||
Name: "releasenotes, r",
|
Name: "releasenotes",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Destination: &ReleaseNotes,
|
Destination: &ReleaseNotes,
|
||||||
Usage: "Only show release notes",
|
Usage: "Only show release notes",
|
||||||
}
|
}
|
||||||
@ -123,7 +139,8 @@ var MachineReadable bool
|
|||||||
|
|
||||||
// MachineReadableFlag turns on/off machine readable output where supported
|
// MachineReadableFlag turns on/off machine readable output where supported
|
||||||
var MachineReadableFlag = &cli.BoolFlag{
|
var MachineReadableFlag = &cli.BoolFlag{
|
||||||
Name: "machine, m",
|
Name: "machine",
|
||||||
|
Aliases: []string{"m"},
|
||||||
Destination: &MachineReadable,
|
Destination: &MachineReadable,
|
||||||
Usage: "Output in a machine-readable format (where supported)",
|
Usage: "Output in a machine-readable format (where supported)",
|
||||||
}
|
}
|
||||||
@ -133,49 +150,56 @@ var RC bool
|
|||||||
|
|
||||||
// RCFlag chooses the latest release candidate for install
|
// RCFlag chooses the latest release candidate for install
|
||||||
var RCFlag = &cli.BoolFlag{
|
var RCFlag = &cli.BoolFlag{
|
||||||
Name: "rc, r",
|
Name: "rc",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Destination: &RC,
|
Destination: &RC,
|
||||||
Usage: "Install the latest release candidate",
|
Usage: "Install the latest release candidate",
|
||||||
}
|
}
|
||||||
|
|
||||||
var Major bool
|
var Major bool
|
||||||
var MajorFlag = &cli.BoolFlag{
|
var MajorFlag = &cli.BoolFlag{
|
||||||
Name: "major, x",
|
Name: "major",
|
||||||
|
Aliases: []string{"x"},
|
||||||
Usage: "Increase the major part of the version",
|
Usage: "Increase the major part of the version",
|
||||||
Destination: &Major,
|
Destination: &Major,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Minor bool
|
var Minor bool
|
||||||
var MinorFlag = &cli.BoolFlag{
|
var MinorFlag = &cli.BoolFlag{
|
||||||
Name: "minor, y",
|
Name: "minor",
|
||||||
|
Aliases: []string{"y"},
|
||||||
Usage: "Increase the minor part of the version",
|
Usage: "Increase the minor part of the version",
|
||||||
Destination: &Minor,
|
Destination: &Minor,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Patch bool
|
var Patch bool
|
||||||
var PatchFlag = &cli.BoolFlag{
|
var PatchFlag = &cli.BoolFlag{
|
||||||
Name: "patch, z",
|
Name: "patch",
|
||||||
|
Aliases: []string{"z"},
|
||||||
Usage: "Increase the patch part of the version",
|
Usage: "Increase the patch part of the version",
|
||||||
Destination: &Patch,
|
Destination: &Patch,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Dry bool
|
var Dry bool
|
||||||
var DryFlag = &cli.BoolFlag{
|
var DryFlag = &cli.BoolFlag{
|
||||||
Name: "dry-run, r",
|
Name: "dry-run",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Usage: "Only reports changes that would be made",
|
Usage: "Only reports changes that would be made",
|
||||||
Destination: &Dry,
|
Destination: &Dry,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Publish bool
|
var Publish bool
|
||||||
var PublishFlag = &cli.BoolFlag{
|
var PublishFlag = &cli.BoolFlag{
|
||||||
Name: "publish, p",
|
Name: "publish",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Usage: "Publish changes to git.coopcloud.tech",
|
Usage: "Publish changes to git.coopcloud.tech",
|
||||||
Destination: &Publish,
|
Destination: &Publish,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Domain string
|
var Domain string
|
||||||
var DomainFlag = &cli.StringFlag{
|
var DomainFlag = &cli.StringFlag{
|
||||||
Name: "domain, D",
|
Name: "domain",
|
||||||
|
Aliases: []string{"D"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Choose a domain name",
|
Usage: "Choose a domain name",
|
||||||
Destination: &Domain,
|
Destination: &Domain,
|
||||||
@ -183,7 +207,8 @@ var DomainFlag = &cli.StringFlag{
|
|||||||
|
|
||||||
var NewAppServer string
|
var NewAppServer string
|
||||||
var NewAppServerFlag = &cli.StringFlag{
|
var NewAppServerFlag = &cli.StringFlag{
|
||||||
Name: "server, s",
|
Name: "server",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Show apps of a specific server",
|
Usage: "Show apps of a specific server",
|
||||||
Destination: &NewAppServer,
|
Destination: &NewAppServer,
|
||||||
@ -191,21 +216,24 @@ var NewAppServerFlag = &cli.StringFlag{
|
|||||||
|
|
||||||
var NoDomainChecks bool
|
var NoDomainChecks bool
|
||||||
var NoDomainChecksFlag = &cli.BoolFlag{
|
var NoDomainChecksFlag = &cli.BoolFlag{
|
||||||
Name: "no-domain-checks, D",
|
Name: "no-domain-checks",
|
||||||
|
Aliases: []string{"D"},
|
||||||
Usage: "Disable public DNS checks",
|
Usage: "Disable public DNS checks",
|
||||||
Destination: &NoDomainChecks,
|
Destination: &NoDomainChecks,
|
||||||
}
|
}
|
||||||
|
|
||||||
var StdErrOnly bool
|
var StdErrOnly bool
|
||||||
var StdErrOnlyFlag = &cli.BoolFlag{
|
var StdErrOnlyFlag = &cli.BoolFlag{
|
||||||
Name: "stderr, s",
|
Name: "stderr",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Usage: "Only tail stderr",
|
Usage: "Only tail stderr",
|
||||||
Destination: &StdErrOnly,
|
Destination: &StdErrOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
var SinceLogs string
|
var SinceLogs string
|
||||||
var SinceLogsFlag = &cli.StringFlag{
|
var SinceLogsFlag = &cli.StringFlag{
|
||||||
Name: "since, S",
|
Name: "since",
|
||||||
|
Aliases: []string{"S"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "tail logs since YYYY-MM-DDTHH:MM:SSZ",
|
Usage: "tail logs since YYYY-MM-DDTHH:MM:SSZ",
|
||||||
Destination: &SinceLogs,
|
Destination: &SinceLogs,
|
||||||
@ -213,49 +241,56 @@ var SinceLogsFlag = &cli.StringFlag{
|
|||||||
|
|
||||||
var DontWaitConverge bool
|
var DontWaitConverge bool
|
||||||
var DontWaitConvergeFlag = &cli.BoolFlag{
|
var DontWaitConvergeFlag = &cli.BoolFlag{
|
||||||
Name: "no-converge-checks, c",
|
Name: "no-converge-checks",
|
||||||
|
Aliases: []string{"c"},
|
||||||
Usage: "Don't wait for converge logic checks",
|
Usage: "Don't wait for converge logic checks",
|
||||||
Destination: &DontWaitConverge,
|
Destination: &DontWaitConverge,
|
||||||
}
|
}
|
||||||
|
|
||||||
var Watch bool
|
var Watch bool
|
||||||
var WatchFlag = &cli.BoolFlag{
|
var WatchFlag = &cli.BoolFlag{
|
||||||
Name: "watch, w",
|
Name: "watch",
|
||||||
|
Aliases: []string{"w"},
|
||||||
Usage: "Watch status by polling repeatedly",
|
Usage: "Watch status by polling repeatedly",
|
||||||
Destination: &Watch,
|
Destination: &Watch,
|
||||||
}
|
}
|
||||||
|
|
||||||
var OnlyErrors bool
|
var OnlyErrors bool
|
||||||
var OnlyErrorFlag = &cli.BoolFlag{
|
var OnlyErrorFlag = &cli.BoolFlag{
|
||||||
Name: "errors, e",
|
Name: "errors",
|
||||||
|
Aliases: []string{"e"},
|
||||||
Usage: "Only show errors",
|
Usage: "Only show errors",
|
||||||
Destination: &OnlyErrors,
|
Destination: &OnlyErrors,
|
||||||
}
|
}
|
||||||
|
|
||||||
var SkipUpdates bool
|
var SkipUpdates bool
|
||||||
var SkipUpdatesFlag = &cli.BoolFlag{
|
var SkipUpdatesFlag = &cli.BoolFlag{
|
||||||
Name: "skip-updates, s",
|
Name: "skip-updates",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Usage: "Skip updating recipe repositories",
|
Usage: "Skip updating recipe repositories",
|
||||||
Destination: &SkipUpdates,
|
Destination: &SkipUpdates,
|
||||||
}
|
}
|
||||||
|
|
||||||
var AllTags bool
|
var AllTags bool
|
||||||
var AllTagsFlag = &cli.BoolFlag{
|
var AllTagsFlag = &cli.BoolFlag{
|
||||||
Name: "all-tags, a",
|
Name: "all-tags",
|
||||||
|
Aliases: []string{"a"},
|
||||||
Usage: "List all tags, not just upgrades",
|
Usage: "List all tags, not just upgrades",
|
||||||
Destination: &AllTags,
|
Destination: &AllTags,
|
||||||
}
|
}
|
||||||
|
|
||||||
var LocalCmd bool
|
var LocalCmd bool
|
||||||
var LocalCmdFlag = &cli.BoolFlag{
|
var LocalCmdFlag = &cli.BoolFlag{
|
||||||
Name: "local, l",
|
Name: "local",
|
||||||
|
Aliases: []string{"l"},
|
||||||
Usage: "Run command locally",
|
Usage: "Run command locally",
|
||||||
Destination: &LocalCmd,
|
Destination: &LocalCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
var RemoteUser string
|
var RemoteUser string
|
||||||
var RemoteUserFlag = &cli.StringFlag{
|
var RemoteUserFlag = &cli.StringFlag{
|
||||||
Name: "user, u",
|
Name: "user",
|
||||||
|
Aliases: []string{"u"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "User to run command within a service context",
|
Usage: "User to run command within a service context",
|
||||||
Destination: &RemoteUser,
|
Destination: &RemoteUser,
|
||||||
@ -263,7 +298,8 @@ var RemoteUserFlag = &cli.StringFlag{
|
|||||||
|
|
||||||
var GitName string
|
var GitName string
|
||||||
var GitNameFlag = &cli.StringFlag{
|
var GitNameFlag = &cli.StringFlag{
|
||||||
Name: "git-name, gn",
|
Name: "git-name",
|
||||||
|
Aliases: []string{"gn"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Git (user) name to do commits with",
|
Usage: "Git (user) name to do commits with",
|
||||||
Destination: &GitName,
|
Destination: &GitName,
|
||||||
@ -271,7 +307,8 @@ var GitNameFlag = &cli.StringFlag{
|
|||||||
|
|
||||||
var GitEmail string
|
var GitEmail string
|
||||||
var GitEmailFlag = &cli.StringFlag{
|
var GitEmailFlag = &cli.StringFlag{
|
||||||
Name: "git-email, ge",
|
Name: "git-email",
|
||||||
|
Aliases: []string{"ge"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Git email name to do commits with",
|
Usage: "Git email name to do commits with",
|
||||||
Destination: &GitEmail,
|
Destination: &GitEmail,
|
||||||
@ -279,13 +316,14 @@ var GitEmailFlag = &cli.StringFlag{
|
|||||||
|
|
||||||
var AllServices bool
|
var AllServices bool
|
||||||
var AllServicesFlag = &cli.BoolFlag{
|
var AllServicesFlag = &cli.BoolFlag{
|
||||||
Name: "all-services, a",
|
Name: "all-services",
|
||||||
|
Aliases: []string{"a"},
|
||||||
Usage: "Restart all services",
|
Usage: "Restart all services",
|
||||||
Destination: &AllServices,
|
Destination: &AllServices,
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubCommandBefore wires up pre-action machinery (e.g. --debug handling).
|
// SubCommandBefore wires up pre-action machinery (e.g. --debug handling).
|
||||||
func SubCommandBefore(c *cli.Context) error {
|
func SubCommandBefore(ctx context.Context, cmd *cli.Command) error {
|
||||||
if Debug {
|
if Debug {
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
log.SetOutput(os.Stderr)
|
log.SetOutput(os.Stderr)
|
||||||
|
@ -4,13 +4,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ShowSubcommandHelpAndError exits the program on error, logs the error to the
|
// ShowSubcommandHelpAndError exits the program on error, logs the error to the
|
||||||
// terminal, and shows the help command.
|
// terminal, and shows the help command.
|
||||||
func ShowSubcommandHelpAndError(c *cli.Context, err interface{}) {
|
func ShowSubcommandHelpAndError(cmd *cli.Command, err interface{}) {
|
||||||
if err2 := cli.ShowSubcommandHelp(c); err2 != nil {
|
if err2 := cli.ShowSubcommandHelp(cmd); err2 != nil {
|
||||||
log.Error(err2)
|
log.Error(err2)
|
||||||
}
|
}
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
@ -9,12 +9,12 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ValidateRecipe ensures the recipe arg is valid.
|
// ValidateRecipe ensures the recipe arg is valid.
|
||||||
func ValidateRecipe(c *cli.Context) recipe.Recipe {
|
func ValidateRecipe(cmd *cli.Command) recipe.Recipe {
|
||||||
recipeName := c.Args().First()
|
recipeName := cmd.Args().First()
|
||||||
|
|
||||||
if recipeName == "" && !NoInput {
|
if recipeName == "" && !NoInput {
|
||||||
var recipes []string
|
var recipes []string
|
||||||
@ -54,7 +54,7 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if recipeName == "" {
|
if recipeName == "" {
|
||||||
ShowSubcommandHelpAndError(c, errors.New("no recipe name provided"))
|
ShowSubcommandHelpAndError(cmd, errors.New("no recipe name provided"))
|
||||||
}
|
}
|
||||||
|
|
||||||
chosenRecipe := recipe.Get(recipeName)
|
chosenRecipe := recipe.Get(recipeName)
|
||||||
@ -64,7 +64,7 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe {
|
|||||||
}
|
}
|
||||||
_, err = chosenRecipe.GetComposeConfig(nil)
|
_, err = chosenRecipe.GetComposeConfig(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c.Command.Name == "generate" {
|
if cmd.Name == "generate" {
|
||||||
if strings.Contains(err.Error(), "missing a compose") {
|
if strings.Contains(err.Error(), "missing a compose") {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -83,11 +83,11 @@ func ValidateRecipe(c *cli.Context) recipe.Recipe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateApp ensures the app name arg is valid.
|
// ValidateApp ensures the app name arg is valid.
|
||||||
func ValidateApp(c *cli.Context) app.App {
|
func ValidateApp(cmd *cli.Command) app.App {
|
||||||
appName := c.Args().First()
|
appName := cmd.Args().First()
|
||||||
|
|
||||||
if appName == "" {
|
if appName == "" {
|
||||||
ShowSubcommandHelpAndError(c, errors.New("no app provided"))
|
ShowSubcommandHelpAndError(cmd, errors.New("no app provided"))
|
||||||
}
|
}
|
||||||
|
|
||||||
app, err := app.Get(appName)
|
app, err := app.Get(appName)
|
||||||
@ -101,8 +101,8 @@ func ValidateApp(c *cli.Context) app.App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateDomain ensures the domain name arg is valid.
|
// ValidateDomain ensures the domain name arg is valid.
|
||||||
func ValidateDomain(c *cli.Context) string {
|
func ValidateDomain(cmd *cli.Command) string {
|
||||||
domainName := c.Args().First()
|
domainName := cmd.Args().First()
|
||||||
|
|
||||||
if domainName == "" && !NoInput {
|
if domainName == "" && !NoInput {
|
||||||
prompt := &survey.Input{
|
prompt := &survey.Input{
|
||||||
@ -115,7 +115,7 @@ func ValidateDomain(c *cli.Context) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if domainName == "" {
|
if domainName == "" {
|
||||||
ShowSubcommandHelpAndError(c, errors.New("no domain provided"))
|
ShowSubcommandHelpAndError(cmd, errors.New("no domain provided"))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("validated %s as domain argument", domainName)
|
log.Debugf("validated %s as domain argument", domainName)
|
||||||
@ -124,10 +124,10 @@ func ValidateDomain(c *cli.Context) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateSubCmdFlags ensures flag order conforms to correct order
|
// ValidateSubCmdFlags ensures flag order conforms to correct order
|
||||||
func ValidateSubCmdFlags(c *cli.Context) bool {
|
func ValidateSubCmdFlags(cmd *cli.Command) bool {
|
||||||
for argIdx, arg := range c.Args() {
|
for argIdx, arg := range cmd.Args().Slice() {
|
||||||
if !strings.HasPrefix(arg, "--") {
|
if !strings.HasPrefix(arg, "--") {
|
||||||
for _, flag := range c.Args()[argIdx:] {
|
for _, flag := range cmd.Args().Slice()[argIdx:] {
|
||||||
if strings.HasPrefix(flag, "--") {
|
if strings.HasPrefix(flag, "--") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -138,8 +138,8 @@ func ValidateSubCmdFlags(c *cli.Context) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateServer ensures the server name arg is valid.
|
// ValidateServer ensures the server name arg is valid.
|
||||||
func ValidateServer(c *cli.Context) string {
|
func ValidateServer(cmd *cli.Command) string {
|
||||||
serverName := c.Args().First()
|
serverName := cmd.Args().First()
|
||||||
|
|
||||||
serverNames, err := config.ReadServerNames()
|
serverNames, err := config.ReadServerNames()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -164,11 +164,11 @@ func ValidateServer(c *cli.Context) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if serverName == "" {
|
if serverName == "" {
|
||||||
ShowSubcommandHelpAndError(c, errors.New("no server provided"))
|
ShowSubcommandHelpAndError(cmd, errors.New("no server provided"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matched {
|
if !matched {
|
||||||
ShowSubcommandHelpAndError(c, errors.New("server doesn't exist?"))
|
ShowSubcommandHelpAndError(cmd, errors.New("server doesn't exist?"))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("validated %s as server argument", serverName)
|
log.Debugf("validated %s as server argument", serverName)
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
gitPkg "coopcloud.tech/abra/pkg/git"
|
gitPkg "coopcloud.tech/abra/pkg/git"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var recipeDiffCommand = cli.Command{
|
var recipeDiffCommand = cli.Command{
|
||||||
Name: "diff",
|
Name: "diff",
|
||||||
Usage: "Show unstaged changes in recipe config",
|
Usage: "Show unstaged changes in recipe config",
|
||||||
Description: "This command requires /usr/bin/git.",
|
Description: "This command requires /usr/bin/git.",
|
||||||
Aliases: []string{"d"},
|
HideHelpCommand: true,
|
||||||
ArgsUsage: "<recipe>",
|
Aliases: []string{"d"},
|
||||||
Flags: []cli.Flag{
|
UsageText: "abra recipe diff [options] <recipe>",
|
||||||
internal.DebugFlag,
|
Before: internal.SubCommandBefore,
|
||||||
internal.NoInputFlag,
|
EnableShellCompletion: true,
|
||||||
},
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
Before: internal.SubCommandBefore,
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
r := internal.ValidateRecipe(cmd)
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
r := internal.ValidateRecipe(c)
|
|
||||||
|
|
||||||
if err := gitPkg.DiffUnstaged(r.Dir); err != nil {
|
if err := gitPkg.DiffUnstaged(r.Dir); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -1,32 +1,30 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var recipeFetchCommand = cli.Command{
|
var recipeFetchCommand = cli.Command{
|
||||||
Name: "fetch",
|
Name: "fetch",
|
||||||
Usage: "Fetch recipe(s)",
|
Usage: "Fetch recipe(s)",
|
||||||
Aliases: []string{"f"},
|
Aliases: []string{"f"},
|
||||||
ArgsUsage: "[<recipe>]",
|
UsageText: "abra recipe fetch [options] [<recipe>]",
|
||||||
Description: "Retrieves all recipes if no <recipe> argument is passed",
|
Description: "Retrieves all recipes if no <recipe> argument is passed",
|
||||||
Flags: []cli.Flag{
|
Before: internal.SubCommandBefore,
|
||||||
internal.DebugFlag,
|
EnableShellCompletion: true,
|
||||||
internal.NoInputFlag,
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
internal.OfflineFlag,
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
},
|
recipeName := cmd.Args().First()
|
||||||
Before: internal.SubCommandBefore,
|
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
recipeName := c.Args().First()
|
|
||||||
r := recipe.Get(recipeName)
|
r := recipe.Get(recipeName)
|
||||||
if recipeName != "" {
|
if recipeName != "" {
|
||||||
internal.ValidateRecipe(c)
|
internal.ValidateRecipe(cmd)
|
||||||
if err := r.Ensure(false, false); err != nil {
|
if err := r.Ensure(false, false); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
@ -8,25 +9,24 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
"coopcloud.tech/abra/pkg/lint"
|
"coopcloud.tech/abra/pkg/lint"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var recipeLintCommand = cli.Command{
|
var recipeLintCommand = cli.Command{
|
||||||
Name: "lint",
|
Name: "lint",
|
||||||
Usage: "Lint a recipe",
|
Usage: "Lint a recipe",
|
||||||
Aliases: []string{"l"},
|
Aliases: []string{"l"},
|
||||||
ArgsUsage: "<recipe>",
|
UsageText: "abra recipe lint [options] <recipe>",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OnlyErrorFlag,
|
internal.OnlyErrorFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
recipe := internal.ValidateRecipe(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
recipe := internal.ValidateRecipe(cmd)
|
||||||
|
|
||||||
if err := recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -10,29 +11,30 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var pattern string
|
var pattern string
|
||||||
var patternFlag = &cli.StringFlag{
|
var patternFlag = &cli.StringFlag{
|
||||||
Name: "pattern, p",
|
Name: "pattern",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Simple string to filter recipes",
|
Usage: "Simple string to filter recipes",
|
||||||
Destination: &pattern,
|
Destination: &pattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
var recipeListCommand = cli.Command{
|
var recipeListCommand = cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List available recipes",
|
Usage: "List recipes",
|
||||||
Aliases: []string{"ls"},
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra recipe list [options]",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
patternFlag,
|
patternFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
catl, err := recipe.ReadRecipeCatalogue(internal.Offline)
|
catl, err := recipe.ReadRecipeCatalogue(internal.Offline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
|
@ -2,6 +2,7 @@ package recipe
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -13,7 +14,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/git"
|
"coopcloud.tech/abra/pkg/git"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// recipeMetadata is the recipe metadata for the README.md
|
// recipeMetadata is the recipe metadata for the README.md
|
||||||
@ -34,27 +35,24 @@ var recipeNewCommand = cli.Command{
|
|||||||
Name: "new",
|
Name: "new",
|
||||||
Aliases: []string{"n"},
|
Aliases: []string{"n"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.GitNameFlag,
|
internal.GitNameFlag,
|
||||||
internal.GitEmailFlag,
|
internal.GitEmailFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Usage: "Create a new recipe",
|
Usage: "Create a new recipe",
|
||||||
ArgsUsage: "<recipe>",
|
UsageText: "abra recipe new [options] <recipe>",
|
||||||
Description: `
|
HideHelpCommand: true,
|
||||||
Create a new recipe.
|
Description: `Create a new recipe.
|
||||||
|
|
||||||
Abra uses the built-in example repository which is available here:
|
Abra uses the built-in example repository which is available here:
|
||||||
|
|
||||||
https://git.coopcloud.tech/coop-cloud/example`,
|
https://git.coopcloud.tech/coop-cloud/example`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
recipeName := c.Args().First()
|
recipeName := cmd.Args().First()
|
||||||
r := recipe.Get(recipeName)
|
r := recipe.Get(recipeName)
|
||||||
|
|
||||||
if recipeName == "" {
|
if recipeName == "" {
|
||||||
internal.ShowSubcommandHelpAndError(c, errors.New("no recipe name provided"))
|
internal.ShowSubcommandHelpAndError(cmd, errors.New("no recipe name provided"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(r.Dir); !os.IsNotExist(err) {
|
if _, err := os.Stat(r.Dir); !os.IsNotExist(err) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RecipeCommand defines all recipe related sub-commands.
|
// RecipeCommand defines all recipe related sub-commands.
|
||||||
@ -9,9 +9,8 @@ var RecipeCommand = cli.Command{
|
|||||||
Name: "recipe",
|
Name: "recipe",
|
||||||
Aliases: []string{"r"},
|
Aliases: []string{"r"},
|
||||||
Usage: "Manage recipes",
|
Usage: "Manage recipes",
|
||||||
ArgsUsage: "<recipe>",
|
UsageText: "abra recipe [command] [options] [arguments]",
|
||||||
Description: `
|
Description: `A recipe is a blueprint for an app. It is a bunch of config files which
|
||||||
A recipe is a blueprint for an app. It is a bunch of config files which
|
|
||||||
describe how to deploy and maintain an app. Recipes are maintained by the Co-op
|
describe how to deploy and maintain an app. Recipes are maintained by the Co-op
|
||||||
Cloud community and you can use Abra to read them, deploy them and create apps
|
Cloud community and you can use Abra to read them, deploy them and create apps
|
||||||
for you.
|
for you.
|
||||||
@ -19,16 +18,17 @@ for you.
|
|||||||
Anyone who uses a recipe can become a maintainer. Maintainers typically make
|
Anyone who uses a recipe can become a maintainer. Maintainers typically make
|
||||||
sure the recipe is in good working order and the config upgraded in a timely
|
sure the recipe is in good working order and the config upgraded in a timely
|
||||||
manner.`,
|
manner.`,
|
||||||
Subcommands: []cli.Command{
|
HideHelpCommand: true,
|
||||||
recipeFetchCommand,
|
Commands: []*cli.Command{
|
||||||
recipeLintCommand,
|
&recipeFetchCommand,
|
||||||
recipeListCommand,
|
&recipeLintCommand,
|
||||||
recipeNewCommand,
|
&recipeListCommand,
|
||||||
recipeReleaseCommand,
|
&recipeNewCommand,
|
||||||
recipeSyncCommand,
|
&recipeReleaseCommand,
|
||||||
recipeUpgradeCommand,
|
&recipeSyncCommand,
|
||||||
recipeVersionCommand,
|
&recipeUpgradeCommand,
|
||||||
recipeResetCommand,
|
&recipeVersionCommand,
|
||||||
recipeDiffCommand,
|
&recipeResetCommand,
|
||||||
|
&recipeDiffCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -18,17 +19,19 @@ import (
|
|||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var recipeReleaseCommand = cli.Command{
|
var recipeReleaseCommand = cli.Command{
|
||||||
Name: "release",
|
Name: "release",
|
||||||
Aliases: []string{"rl"},
|
Aliases: []string{"rl"},
|
||||||
Usage: "Release a new recipe version",
|
Usage: "Release a new recipe version",
|
||||||
ArgsUsage: "<recipe> [<version>]",
|
HideHelpCommand: true,
|
||||||
Description: `
|
UsageText: "abra recipe release [options] <recipe> [<version>]",
|
||||||
Create a new version of a recipe. These versions are then published on the
|
Description: `Create a new version of a recipe.
|
||||||
Co-op Cloud recipe catalogue. These versions take the following form:
|
|
||||||
|
These versions are then published on the Co-op Cloud recipe catalogue. These
|
||||||
|
versions take the following form:
|
||||||
|
|
||||||
a.b.c+x.y.z
|
a.b.c+x.y.z
|
||||||
|
|
||||||
@ -46,19 +49,17 @@ Publish your new release to git.coopcloud.tech with "-p/--publish". This
|
|||||||
requires that you have permission to git push to these repositories and have
|
requires that you have permission to git push to these repositories and have
|
||||||
your SSH keys configured on your account.`,
|
your SSH keys configured on your account.`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.DryFlag,
|
internal.DryFlag,
|
||||||
internal.MajorFlag,
|
internal.MajorFlag,
|
||||||
internal.MinorFlag,
|
internal.MinorFlag,
|
||||||
internal.PatchFlag,
|
internal.PatchFlag,
|
||||||
internal.PublishFlag,
|
internal.PublishFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
recipe := internal.ValidateRecipe(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
recipe := internal.ValidateRecipe(cmd)
|
||||||
|
|
||||||
imagesTmp, err := getImageVersions(recipe)
|
imagesTmp, err := getImageVersions(recipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -75,7 +76,7 @@ your SSH keys configured on your account.`,
|
|||||||
log.Fatalf("main app service version for %s is empty?", recipe.Name)
|
log.Fatalf("main app service version for %s is empty?", recipe.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
tagString := c.Args().Get(1)
|
tagString := cmd.Args().Get(1)
|
||||||
if tagString != "" {
|
if tagString != "" {
|
||||||
if _, err := tagcmp.Parse(tagString); err != nil {
|
if _, err := tagcmp.Parse(tagString); err != nil {
|
||||||
log.Fatalf("cannot parse %s, invalid tag specified?", tagString)
|
log.Fatalf("cannot parse %s, invalid tag specified?", tagString)
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var recipeResetCommand = cli.Command{
|
var recipeResetCommand = cli.Command{
|
||||||
Name: "reset",
|
Name: "reset",
|
||||||
Usage: "Remove all unstaged changes from recipe config",
|
Usage: "Remove all unstaged changes from recipe config",
|
||||||
Description: "WARNING: this will delete your changes. Be Careful.",
|
Description: "WARNING: this will delete your changes. Be Careful.",
|
||||||
Aliases: []string{"rs"},
|
HideHelpCommand: true,
|
||||||
ArgsUsage: "<recipe>",
|
Aliases: []string{"rs"},
|
||||||
Flags: []cli.Flag{
|
UsageText: "abra recipe reset [options] <recipe>",
|
||||||
internal.DebugFlag,
|
Before: internal.SubCommandBefore,
|
||||||
internal.NoInputFlag,
|
EnableShellCompletion: true,
|
||||||
},
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
Before: internal.SubCommandBefore,
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
recipeName := cmd.Args().First()
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
recipeName := c.Args().First()
|
|
||||||
r := recipe.Get(recipeName)
|
r := recipe.Get(recipeName)
|
||||||
|
|
||||||
if recipeName != "" {
|
if recipeName != "" {
|
||||||
internal.ValidateRecipe(c)
|
internal.ValidateRecipe(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := git.PlainOpen(r.Dir)
|
repo, err := git.PlainOpen(r.Dir)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -12,35 +13,35 @@ import (
|
|||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var recipeSyncCommand = cli.Command{
|
var recipeSyncCommand = cli.Command{
|
||||||
Name: "sync",
|
Name: "sync",
|
||||||
Aliases: []string{"s"},
|
Aliases: []string{"s"},
|
||||||
Usage: "Sync recipe version label",
|
Usage: "Sync recipe version label",
|
||||||
ArgsUsage: "<recipe> [<version>]",
|
HideHelpCommand: true,
|
||||||
|
UsageText: "abra recipe lint [options] <recipe> [<version>]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.DryFlag,
|
internal.DryFlag,
|
||||||
internal.MajorFlag,
|
internal.MajorFlag,
|
||||||
internal.MinorFlag,
|
internal.MinorFlag,
|
||||||
internal.PatchFlag,
|
internal.PatchFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `
|
Description: `Generate labels for the main recipe service.
|
||||||
Generate labels for the main recipe service (i.e. by convention, the service
|
|
||||||
named "app") which corresponds to the following format:
|
By convention, the service named "app" using the following format:
|
||||||
|
|
||||||
coop-cloud.${STACK_NAME}.version=<version>
|
coop-cloud.${STACK_NAME}.version=<version>
|
||||||
|
|
||||||
Where <version> can be specifed on the command-line or Abra can attempt to
|
Where <version> can be specifed on the command-line or Abra can attempt to
|
||||||
auto-generate it for you. The <recipe> configuration will be updated on the
|
auto-generate it for you. The <recipe> configuration will be updated on the
|
||||||
local file system.`,
|
local file system.`,
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
recipe := internal.ValidateRecipe(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
recipe := internal.ValidateRecipe(cmd)
|
||||||
|
|
||||||
mainApp, err := internal.GetMainAppImage(recipe)
|
mainApp, err := internal.GetMainAppImage(recipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,7 +60,7 @@ local file system.`,
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTag := c.Args().Get(1)
|
nextTag := cmd.Args().Get(1)
|
||||||
if len(tags) == 0 && nextTag == "" {
|
if len(tags) == 0 && nextTag == "" {
|
||||||
log.Warnf("no git tags found for %s", recipe.Name)
|
log.Warnf("no git tags found for %s", recipe.Name)
|
||||||
if internal.NoInput {
|
if internal.NoInput {
|
||||||
|
@ -2,6 +2,7 @@ package recipe
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -19,7 +20,7 @@ import (
|
|||||||
"coopcloud.tech/tagcmp"
|
"coopcloud.tech/tagcmp"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type imgPin struct {
|
type imgPin struct {
|
||||||
@ -27,8 +28,8 @@ type imgPin struct {
|
|||||||
version tagcmp.Tag
|
version tagcmp.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
// anUpgrade represents a single service upgrade (as within a recipe), and the list of tags that it can be upgraded to,
|
// anUpgrade represents a single service upgrade (as within a recipe), and the
|
||||||
// for serialization purposes.
|
// list of tags that it can be upgraded to, for serialization purposes.
|
||||||
type anUpgrade struct {
|
type anUpgrade struct {
|
||||||
Service string `json:"service"`
|
Service string `json:"service"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
@ -37,13 +38,13 @@ type anUpgrade struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var recipeUpgradeCommand = cli.Command{
|
var recipeUpgradeCommand = cli.Command{
|
||||||
Name: "upgrade",
|
Name: "upgrade",
|
||||||
Aliases: []string{"u"},
|
Aliases: []string{"u"},
|
||||||
Usage: "Upgrade recipe image tags",
|
Usage: "Upgrade recipe image tags",
|
||||||
Description: `
|
HideHelpCommand: true,
|
||||||
Parse all image tags within the given <recipe> configuration and prompt with
|
Description: `Upgrade a given <recipe> configuration.
|
||||||
more recent tags to upgrade to. It will update the relevant compose file tags
|
|
||||||
on the local file system.
|
It will update the relevant compose file tags on the local file system.
|
||||||
|
|
||||||
Some image tags cannot be parsed because they do not follow some sort of
|
Some image tags cannot be parsed because they do not follow some sort of
|
||||||
semver-like convention. In this case, all possible tags will be listed and it
|
semver-like convention. In this case, all possible tags will be listed and it
|
||||||
@ -53,25 +54,20 @@ The command is interactive and will show a select input which allows you to
|
|||||||
make a seclection. Use the "?" key to see more help on navigating this
|
make a seclection. Use the "?" key to see more help on navigating this
|
||||||
interface.
|
interface.
|
||||||
|
|
||||||
You may invoke this command in "wizard" mode and be prompted for input.
|
You may invoke this command in "wizard" mode and be prompted for input.`,
|
||||||
|
UsageText: "abra recipe upgrade [options] [<recipe>]",
|
||||||
EXAMPLE:
|
|
||||||
|
|
||||||
abra recipe upgrade`,
|
|
||||||
ArgsUsage: "<recipe>",
|
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.PatchFlag,
|
internal.PatchFlag,
|
||||||
internal.MinorFlag,
|
internal.MinorFlag,
|
||||||
internal.MajorFlag,
|
internal.MajorFlag,
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
internal.AllTagsFlag,
|
internal.AllTagsFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
recipe := internal.ValidateRecipe(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
recipe := internal.ValidateRecipe(cmd)
|
||||||
|
|
||||||
if err := recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
if err := recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package recipe
|
package recipe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
recipePkg "coopcloud.tech/abra/pkg/recipe"
|
recipePkg "coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sortServiceByName(versions [][]string) func(i, j int) bool {
|
func sortServiceByName(versions [][]string) func(i, j int) bool {
|
||||||
@ -24,20 +25,19 @@ func sortServiceByName(versions [][]string) func(i, j int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var recipeVersionCommand = cli.Command{
|
var recipeVersionCommand = cli.Command{
|
||||||
Name: "versions",
|
Name: "versions",
|
||||||
Aliases: []string{"v"},
|
Aliases: []string{"v"},
|
||||||
Usage: "List recipe versions",
|
Usage: "List recipe versions",
|
||||||
ArgsUsage: "<recipe>",
|
UsageText: "abra recipe version [options] <recipe>",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.RecipeNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.RecipeNameComplete,
|
||||||
recipe := internal.ValidateRecipe(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
recipe := internal.ValidateRecipe(cmd)
|
||||||
|
|
||||||
catl, err := recipePkg.ReadRecipeCatalogue(internal.Offline)
|
catl, err := recipePkg.ReadRecipeCatalogue(internal.Offline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -13,12 +14,13 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/server"
|
"coopcloud.tech/abra/pkg/server"
|
||||||
sshPkg "coopcloud.tech/abra/pkg/ssh"
|
sshPkg "coopcloud.tech/abra/pkg/ssh"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var local bool
|
var local bool
|
||||||
var localFlag = &cli.BoolFlag{
|
var localFlag = &cli.BoolFlag{
|
||||||
Name: "local, l",
|
Name: "local",
|
||||||
|
Aliases: []string{"l"},
|
||||||
Usage: "Use local server",
|
Usage: "Use local server",
|
||||||
Destination: &local,
|
Destination: &local,
|
||||||
}
|
}
|
||||||
@ -92,15 +94,16 @@ func createServerDir(name string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var serverAddCommand = cli.Command{
|
var serverAddCommand = cli.Command{
|
||||||
Name: "add",
|
Name: "add",
|
||||||
Aliases: []string{"a"},
|
Aliases: []string{"a"},
|
||||||
Usage: "Add a new server to your configuration",
|
Usage: "Add a new server",
|
||||||
Description: `
|
UsageText: "abra server add [options] <domain>",
|
||||||
Add a new server to your configuration so that it can be managed by Abra.
|
HideHelpCommand: true,
|
||||||
|
Description: `Add a new server to your configuration so that it can be managed by Abra.
|
||||||
|
|
||||||
Abra relies on the standard SSH command-line and ~/.ssh/config for client
|
Abra relies on the standard SSH command-line and ~/.ssh/config for client
|
||||||
connection details. You must configure an entry per-host in your ~/.ssh/config
|
connection details. You must configure an entry per-host in your ~/.ssh/config
|
||||||
for each server. For example:
|
for each server:
|
||||||
|
|
||||||
Host example.com example
|
Host example.com example
|
||||||
Hostname example.com
|
Hostname example.com
|
||||||
@ -108,10 +111,6 @@ for each server. For example:
|
|||||||
Port 12345
|
Port 12345
|
||||||
IdentityFile ~/.ssh/example@somewhere
|
IdentityFile ~/.ssh/example@somewhere
|
||||||
|
|
||||||
You can then add a server like so:
|
|
||||||
|
|
||||||
abra server add example.com
|
|
||||||
|
|
||||||
If "--local" is passed, then Abra assumes that the current local server is
|
If "--local" is passed, then Abra assumes that the current local server is
|
||||||
intended as the target server. This is useful when you want to have your entire
|
intended as the target server. This is useful when you want to have your entire
|
||||||
Co-op Cloud config located on the server itself, and not on your local
|
Co-op Cloud config located on the server itself, and not on your local
|
||||||
@ -119,28 +118,24 @@ developer machine. The domain is then set to "default".
|
|||||||
|
|
||||||
You can also pass "--no-domain-checks/-D" flag to use any arbitrary name
|
You can also pass "--no-domain-checks/-D" flag to use any arbitrary name
|
||||||
instead of a real domain. The host will be resolved with the "Hostname" entry
|
instead of a real domain. The host will be resolved with the "Hostname" entry
|
||||||
of your ~/.ssh/config. Checks for a valid online domain will be skipped:
|
of your ~/.ssh/config. Checks for a valid online domain will be skipped.`,
|
||||||
|
|
||||||
abra server add -D example`,
|
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
internal.NoDomainChecksFlag,
|
internal.NoDomainChecksFlag,
|
||||||
localFlag,
|
localFlag,
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
ArgsUsage: "<name>",
|
ArgsUsage: "<name>",
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
if len(c.Args()) > 0 && local || !internal.ValidateSubCmdFlags(c) {
|
if cmd.Args().Len() > 0 && local || !internal.ValidateSubCmdFlags(cmd) {
|
||||||
err := errors.New("cannot use <name> and --local together")
|
err := errors.New("cannot use <name> and --local together")
|
||||||
internal.ShowSubcommandHelpAndError(c, err)
|
internal.ShowSubcommandHelpAndError(cmd, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var name string
|
var name string
|
||||||
if local {
|
if local {
|
||||||
name = "default"
|
name = "default"
|
||||||
} else {
|
} else {
|
||||||
name = internal.ValidateDomain(c)
|
name = internal.ValidateDomain(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(d1): reasonable 5 second timeout for connections which can't
|
// NOTE(d1): reasonable 5 second timeout for connections which can't
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/context"
|
contextPkg "coopcloud.tech/abra/pkg/context"
|
||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/docker/cli/cli/connhelper/ssh"
|
"github.com/docker/cli/cli/connhelper/ssh"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var serverListCommand = cli.Command{
|
var serverListCommand = cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
Usage: "List managed servers",
|
Usage: "List managed servers",
|
||||||
|
UsageText: "abra server list [options]",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
internal.DebugFlag,
|
||||||
internal.MachineReadableFlag,
|
internal.MachineReadableFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
dockerContextStore := context.NewDefaultDockerContextStore()
|
dockerContextStore := contextPkg.NewDefaultDockerContextStore()
|
||||||
contexts, err := dockerContextStore.Store.List()
|
contexts, err := dockerContextStore.Store.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -39,14 +41,14 @@ var serverListCommand = cli.Command{
|
|||||||
|
|
||||||
for _, serverName := range serverNames {
|
for _, serverName := range serverNames {
|
||||||
var row []string
|
var row []string
|
||||||
for _, ctx := range contexts {
|
for _, dockerCtx := range contexts {
|
||||||
endpoint, err := context.GetContextEndpoint(ctx)
|
endpoint, err := contextPkg.GetContextEndpoint(dockerCtx)
|
||||||
if err != nil && strings.Contains(err.Error(), "does not exist") {
|
if err != nil && strings.Contains(err.Error(), "does not exist") {
|
||||||
// No local context found, we can continue safely
|
// No local context found, we can continue safely
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Name == serverName {
|
if dockerCtx.Name == serverName {
|
||||||
sp, err := ssh.ParseURL(endpoint)
|
sp, err := ssh.ParseURL(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -9,13 +9,14 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/formatter"
|
"coopcloud.tech/abra/pkg/formatter"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var allFilter bool
|
var allFilter bool
|
||||||
|
|
||||||
var allFilterFlag = &cli.BoolFlag{
|
var allFilterFlag = &cli.BoolFlag{
|
||||||
Name: "all, a",
|
Name: "all",
|
||||||
|
Aliases: []string{"a"},
|
||||||
Usage: "Remove all unused images not just dangling ones",
|
Usage: "Remove all unused images not just dangling ones",
|
||||||
Destination: &allFilter,
|
Destination: &allFilter,
|
||||||
}
|
}
|
||||||
@ -23,17 +24,19 @@ var allFilterFlag = &cli.BoolFlag{
|
|||||||
var volumesFilter bool
|
var volumesFilter bool
|
||||||
|
|
||||||
var volumesFilterFlag = &cli.BoolFlag{
|
var volumesFilterFlag = &cli.BoolFlag{
|
||||||
Name: "volumes, v",
|
Name: "volumes",
|
||||||
|
Aliases: []string{"v"},
|
||||||
Usage: "Prune volumes. This will remove app data, Be Careful!",
|
Usage: "Prune volumes. This will remove app data, Be Careful!",
|
||||||
Destination: &volumesFilter,
|
Destination: &volumesFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverPruneCommand = cli.Command{
|
var serverPruneCommand = cli.Command{
|
||||||
Name: "prune",
|
Name: "prune",
|
||||||
Aliases: []string{"p"},
|
Aliases: []string{"p"},
|
||||||
Usage: "Prune resources on a server",
|
Usage: "Prune resources on a server",
|
||||||
Description: `
|
UsageText: "abra server prune [options] <server>",
|
||||||
Prunes unused containers, networks, and dangling images.
|
HideHelpCommand: true,
|
||||||
|
Description: `Prunes unused containers, networks, and dangling images.
|
||||||
|
|
||||||
Use "-v/--volumes" to remove volumes that are not associated with a deployed
|
Use "-v/--volumes" to remove volumes that are not associated with a deployed
|
||||||
app. This can result in unwanted data loss if not used carefully.`,
|
app. This can result in unwanted data loss if not used carefully.`,
|
||||||
@ -41,14 +44,12 @@ app. This can result in unwanted data loss if not used carefully.`,
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
allFilterFlag,
|
allFilterFlag,
|
||||||
volumesFilterFlag,
|
volumesFilterFlag,
|
||||||
internal.DebugFlag,
|
|
||||||
internal.OfflineFlag,
|
|
||||||
internal.NoInputFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
BashComplete: autocomplete.ServerNameComplete,
|
EnableShellCompletion: true,
|
||||||
Action: func(c *cli.Context) error {
|
ShellComplete: autocomplete.ServerNameComplete,
|
||||||
serverName := internal.ValidateServer(c)
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
serverName := internal.ValidateServer(cmd)
|
||||||
|
|
||||||
cl, err := client.New(serverName)
|
cl, err := client.New(serverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -57,7 +58,6 @@ app. This can result in unwanted data loss if not used carefully.`,
|
|||||||
|
|
||||||
var args filters.Args
|
var args filters.Args
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
cr, err := cl.ContainersPrune(ctx, args)
|
cr, err := cl.ContainersPrune(ctx, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
@ -9,29 +10,25 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/client"
|
"coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var serverRemoveCommand = cli.Command{
|
var serverRemoveCommand = cli.Command{
|
||||||
Name: "remove",
|
Name: "remove",
|
||||||
Aliases: []string{"rm"},
|
Aliases: []string{"rm"},
|
||||||
ArgsUsage: "<server>",
|
UsageText: "abra server remove [options] <domain>",
|
||||||
Usage: "Remove a managed server",
|
Usage: "Remove a managed server",
|
||||||
Description: `
|
HideHelpCommand: true,
|
||||||
Remove a managed server.
|
Description: `Remove a managed server.
|
||||||
|
|
||||||
Abra will remove the internal bookkeeping (~/.abra/servers/...) and underlying
|
Abra will remove the internal bookkeeping ($ABRA_DIR/servers/...) and
|
||||||
client connection context. This server will then be lost in time, like tears in
|
underlying client connection context. This server will then be lost in time,
|
||||||
rain.`,
|
like tears in rain.`,
|
||||||
Flags: []cli.Flag{
|
Before: internal.SubCommandBefore,
|
||||||
internal.DebugFlag,
|
EnableShellCompletion: true,
|
||||||
internal.NoInputFlag,
|
ShellComplete: autocomplete.ServerNameComplete,
|
||||||
internal.OfflineFlag,
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
},
|
serverName := internal.ValidateServer(cmd)
|
||||||
Before: internal.SubCommandBefore,
|
|
||||||
BashComplete: autocomplete.ServerNameComplete,
|
|
||||||
Action: func(c *cli.Context) error {
|
|
||||||
serverName := internal.ValidateServer(c)
|
|
||||||
|
|
||||||
if err := client.DeleteContext(serverName); err != nil {
|
if err := client.DeleteContext(serverName); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServerCommand defines the `abra server` command and its subcommands
|
// ServerCommand defines the `abra server` command and its subcommands
|
||||||
var ServerCommand = cli.Command{
|
var ServerCommand = cli.Command{
|
||||||
Name: "server",
|
Name: "server",
|
||||||
Aliases: []string{"s"},
|
Aliases: []string{"s"},
|
||||||
Usage: "Manage servers",
|
Usage: "Manage servers",
|
||||||
Subcommands: []cli.Command{
|
UsageText: "abra server [command] [options] [arguments]",
|
||||||
serverAddCommand,
|
HideHelpCommand: true,
|
||||||
serverListCommand,
|
Commands: []*cli.Command{
|
||||||
serverRemoveCommand,
|
&serverAddCommand,
|
||||||
serverPruneCommand,
|
&serverListCommand,
|
||||||
|
&serverRemoveCommand,
|
||||||
|
&serverPruneCommand,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -23,44 +23,44 @@ import (
|
|||||||
dockerclient "github.com/docker/docker/client"
|
dockerclient "github.com/docker/docker/client"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SERVER = "localhost"
|
const SERVER = "localhost"
|
||||||
|
|
||||||
var majorUpdate bool
|
var majorUpdate bool
|
||||||
var majorFlag = &cli.BoolFlag{
|
var majorFlag = &cli.BoolFlag{
|
||||||
Name: "major, m",
|
Name: "major",
|
||||||
|
Aliases: []string{"m"},
|
||||||
Usage: "Also check for major updates",
|
Usage: "Also check for major updates",
|
||||||
Destination: &majorUpdate,
|
Destination: &majorUpdate,
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateAll bool
|
var updateAll bool
|
||||||
var allFlag = &cli.BoolFlag{
|
var allFlag = &cli.BoolFlag{
|
||||||
Name: "all, a",
|
Name: "all",
|
||||||
|
Aliases: []string{"a"},
|
||||||
Usage: "Update all deployed apps",
|
Usage: "Update all deployed apps",
|
||||||
Destination: &updateAll,
|
Destination: &updateAll,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify checks for available upgrades
|
// Notify checks for available upgrades
|
||||||
var Notify = cli.Command{
|
var Notify = cli.Command{
|
||||||
Name: "notify",
|
Name: "notify",
|
||||||
Aliases: []string{"n"},
|
Aliases: []string{"n"},
|
||||||
Usage: "Check for available upgrades",
|
Usage: "Check for available upgrades",
|
||||||
|
UsageText: "kadabra notify [options]",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
majorFlag,
|
majorFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `
|
Description: `Notify on new versions for deployed apps.
|
||||||
Read the deployed app versions and look for new versions in the recipe
|
|
||||||
catalogue.
|
|
||||||
|
|
||||||
If a new patch/minor version is available, a notification is printed.
|
If a new patch/minor version is available, a notification is printed.
|
||||||
|
|
||||||
Use "--major" to include new major versions.`,
|
Use "--major" to include new major versions.`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
cl, err := client.New("default")
|
cl, err := client.New("default")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -92,20 +92,18 @@ Use "--major" to include new major versions.`,
|
|||||||
|
|
||||||
// UpgradeApp upgrades apps.
|
// UpgradeApp upgrades apps.
|
||||||
var UpgradeApp = cli.Command{
|
var UpgradeApp = cli.Command{
|
||||||
Name: "upgrade",
|
Name: "upgrade",
|
||||||
Aliases: []string{"u"},
|
Aliases: []string{"u"},
|
||||||
Usage: "Upgrade apps",
|
Usage: "Upgrade apps",
|
||||||
ArgsUsage: "<stack-name> <recipe>",
|
UsageText: "kadabra notify [options] <stack> <recipe>",
|
||||||
|
HideHelpCommand: true,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
internal.DebugFlag,
|
|
||||||
internal.ChaosFlag,
|
internal.ChaosFlag,
|
||||||
majorFlag,
|
majorFlag,
|
||||||
allFlag,
|
allFlag,
|
||||||
internal.OfflineFlag,
|
|
||||||
},
|
},
|
||||||
Before: internal.SubCommandBefore,
|
Before: internal.SubCommandBefore,
|
||||||
Description: `
|
Description: `Upgrade an app by specifying stack name and recipe.
|
||||||
Upgrade an app by specifying stack name and recipe.
|
|
||||||
|
|
||||||
Use "--all" to upgrade every deployed app.
|
Use "--all" to upgrade every deployed app.
|
||||||
|
|
||||||
@ -116,15 +114,15 @@ available, the app is upgraded.
|
|||||||
To include major versions use the "--major" flag. You probably don't want that
|
To include major versions use the "--major" flag. You probably don't want that
|
||||||
as it will break things. Only apps that are not deployed with "--chaos" are
|
as it will break things. Only apps that are not deployed with "--chaos" are
|
||||||
upgraded, to update chaos deployments use the "--chaos" flag. Use it with care.`,
|
upgraded, to update chaos deployments use the "--chaos" flag. Use it with care.`,
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
cl, err := client.New("default")
|
cl, err := client.New("default")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !updateAll {
|
if !updateAll {
|
||||||
stackName := c.Args().Get(0)
|
stackName := cmd.Args().Get(0)
|
||||||
recipeName := c.Args().Get(1)
|
recipeName := cmd.Args().Get(1)
|
||||||
err = tryUpgrade(cl, stackName, recipeName)
|
err = tryUpgrade(cl, stackName, recipeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -468,25 +466,24 @@ func upgrade(cl *dockerclient.Client, stackName, recipeName, upgradeVersion stri
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAbraApp(version, commit string) *cli.App {
|
func newAbraApp(version, commit string) *cli.Command {
|
||||||
app := &cli.App{
|
app := &cli.Command{
|
||||||
Name: "kadabra",
|
Name: "kadabra",
|
||||||
Usage: `The Co-op Cloud auto-updater
|
Usage: "The Co-op Cloud auto-updater 🤖🚀",
|
||||||
____ ____ _ _
|
Version: fmt.Sprintf("%s-%s", version, commit[:7]),
|
||||||
/ ___|___ ___ _ __ / ___| | ___ _ _ __| |
|
UsageText: "kadabra [command] [options] [arguments]",
|
||||||
| | / _ \ _____ / _ \| '_ \ | | | |/ _ \| | | |/ _' |
|
HideHelpCommand: true,
|
||||||
| |__| (_) |_____| (_) | |_) | | |___| | (_) | |_| | (_| |
|
Flags: []cli.Flag{
|
||||||
\____\___/ \___/| .__/ \____|_|\___/ \__,_|\__,_|
|
internal.OfflineFlag,
|
||||||
|_|
|
internal.DebugFlag,
|
||||||
`,
|
},
|
||||||
Version: fmt.Sprintf("%s-%s", version, commit[:7]),
|
Commands: []*cli.Command{
|
||||||
Commands: []cli.Command{
|
&Notify,
|
||||||
Notify,
|
&UpgradeApp,
|
||||||
UpgradeApp,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Before = func(c *cli.Context) error {
|
app.Before = func(ctx context.Context, cmd *cli.Command) error {
|
||||||
charmLog.SetDefault(log.Logger)
|
charmLog.SetDefault(log.Logger)
|
||||||
log.Debugf("kadabra version %s, commit %s", version, commit)
|
log.Debugf("kadabra version %s, commit %s", version, commit)
|
||||||
return nil
|
return nil
|
||||||
@ -499,7 +496,7 @@ func newAbraApp(version, commit string) *cli.App {
|
|||||||
func RunApp(version, commit string) {
|
func RunApp(version, commit string) {
|
||||||
app := newAbraApp(version, commit)
|
app := newAbraApp(version, commit)
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(context.Background(), os.Args); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
go.mod
6
go.mod
@ -2,6 +2,8 @@ module coopcloud.tech/abra
|
|||||||
|
|
||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
|
replace github.com/urfave/cli/v3 => github.com/fiatjaf/cli/v3 v3.0.0-20240704165307-ad0e1925dd42
|
||||||
|
|
||||||
require (
|
require (
|
||||||
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb
|
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb
|
||||||
git.coopcloud.tech/coop-cloud/godotenv v1.5.2-0.20231130100509-01bff8284355
|
git.coopcloud.tech/coop-cloud/godotenv v1.5.2-0.20231130100509-01bff8284355
|
||||||
@ -18,6 +20,7 @@ require (
|
|||||||
github.com/olekukonko/tablewriter v0.0.5
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/schollz/progressbar/v3 v3.14.4
|
github.com/schollz/progressbar/v3 v3.14.4
|
||||||
|
github.com/urfave/cli/v3 v3.0.0-alpha9
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gotest.tools/v3 v3.5.1
|
gotest.tools/v3 v3.5.1
|
||||||
)
|
)
|
||||||
@ -36,7 +39,6 @@ require (
|
|||||||
github.com/charmbracelet/x/ansi v0.1.2 // indirect
|
github.com/charmbracelet/x/ansi v0.1.2 // indirect
|
||||||
github.com/cloudflare/circl v1.3.9 // indirect
|
github.com/cloudflare/circl v1.3.9 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
|
||||||
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
|
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||||
@ -84,7 +86,6 @@ require (
|
|||||||
github.com/prometheus/common v0.55.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
@ -134,7 +135,6 @@ require (
|
|||||||
github.com/spf13/cobra v1.8.1 // indirect
|
github.com/spf13/cobra v1.8.1 // indirect
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/theupdateframework/notary v0.7.0 // indirect
|
github.com/theupdateframework/notary v0.7.0 // indirect
|
||||||
github.com/urfave/cli v1.22.15
|
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
golang.org/x/sys v0.22.0
|
golang.org/x/sys v0.22.0
|
||||||
)
|
)
|
||||||
|
13
go.sum
13
go.sum
@ -49,7 +49,6 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
|
|||||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
|
||||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
@ -274,7 +273,6 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
|
|||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
@ -357,6 +355,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
|||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/fiatjaf/cli/v3 v3.0.0-20240704165307-ad0e1925dd42 h1:yId1d3b2PHJ9vnYCxojs9NslXYVQ1iv7svK/CuDRoU0=
|
||||||
|
github.com/fiatjaf/cli/v3 v3.0.0-20240704165307-ad0e1925dd42/go.mod h1:Z1ItyMma7t6I7zHG9OpbExhHQOSkFf/96n+mAZ9MtVI=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
@ -803,7 +803,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
|||||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
@ -861,9 +860,6 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
|
||||||
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
@ -871,9 +867,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
@ -893,8 +886,6 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
|
|||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
|
|
||||||
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
|
|
||||||
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
|
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
|
||||||
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
package autocomplete
|
package autocomplete
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/app"
|
"coopcloud.tech/abra/pkg/app"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppNameComplete copletes app names.
|
// AppNameComplete copletes app names.
|
||||||
func AppNameComplete(c *cli.Context) {
|
func AppNameComplete(ctx context.Context, cmd *cli.Command) {
|
||||||
appNames, err := app.GetAppNames()
|
appNames, err := app.GetAppNames()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.NArg() > 0 {
|
if cmd.NArg() > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,13 +37,13 @@ func ServiceNameComplete(appName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RecipeNameComplete completes recipe names.
|
// RecipeNameComplete completes recipe names.
|
||||||
func RecipeNameComplete(c *cli.Context) {
|
func RecipeNameComplete(ctx context.Context, cmd *cli.Command) {
|
||||||
catl, err := recipe.ReadRecipeCatalogue(false)
|
catl, err := recipe.ReadRecipeCatalogue(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.NArg() > 0 {
|
if cmd.NArg() > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,13 +67,13 @@ func RecipeVersionComplete(recipeName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ServerNameComplete completes server names.
|
// ServerNameComplete completes server names.
|
||||||
func ServerNameComplete(c *cli.Context) {
|
func ServerNameComplete(ctx context.Context, cmd *cli.Command) {
|
||||||
files, err := app.LoadAppFiles("")
|
files, err := app.LoadAppFiles("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.NArg() > 0 {
|
if cmd.NArg() > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,8 +83,8 @@ func ServerNameComplete(c *cli.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SubcommandComplete completes sub-commands.
|
// SubcommandComplete completes sub-commands.
|
||||||
func SubcommandComplete(c *cli.Context) {
|
func SubcommandComplete(ctx context.Context, cmd *cli.Command) {
|
||||||
if c.NArg() > 0 {
|
if cmd.NArg() > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ _cli_bash_autocomplete() {
|
|||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
if [[ "$cur" == "-"* ]]; then
|
if [[ "$cur" == "-"* ]]; then
|
||||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-shell-completion )
|
||||||
else
|
else
|
||||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-shell-completion )
|
||||||
fi
|
fi
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||||
return 0
|
return 0
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
function complete_abra_args
|
function complete_abra_args
|
||||||
set -l cmd (commandline -poc) --generate-bash-completion
|
set -l cmd (commandline -poc) --generate-shell-completion
|
||||||
$cmd
|
$cmd
|
||||||
end
|
end
|
||||||
complete -c abra -f -n "not __fish_seen_subcommand_from -h --help -v --version complete_abra_args" -a "(complete_abra_args)"
|
complete -c abra -f -n "not __fish_seen_subcommand_from -h --help -v --version complete_abra_args" -a "(complete_abra_args)"
|
||||||
|
@ -2,7 +2,7 @@ $fn = $($MyInvocation.MyCommand.Name)
|
|||||||
$name = $fn -replace "(.*)\.ps1$", '$1'
|
$name = $fn -replace "(.*)\.ps1$", '$1'
|
||||||
Register-ArgumentCompleter -Native -CommandName $name -ScriptBlock {
|
Register-ArgumentCompleter -Native -CommandName $name -ScriptBlock {
|
||||||
param($commandName, $wordToComplete, $cursorPosition)
|
param($commandName, $wordToComplete, $cursorPosition)
|
||||||
$other = "$wordToComplete --generate-bash-completion"
|
$other = "$wordToComplete --generate-shell-completion"
|
||||||
Invoke-Expression $other | ForEach-Object {
|
Invoke-Expression $other | ForEach-Object {
|
||||||
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ _cli_zsh_autocomplete() {
|
|||||||
local cur
|
local cur
|
||||||
cur=${words[-1]}
|
cur=${words[-1]}
|
||||||
if [[ "$cur" == "-"* ]]; then
|
if [[ "$cur" == "-"* ]]; then
|
||||||
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}")
|
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} ${cur} --generate-shell-completion)}")
|
||||||
else
|
else
|
||||||
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --generate-bash-completion)}")
|
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --generate-shell-completion)}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${opts[1]}" != "" ]]; then
|
if [[ "${opts[1]}" != "" ]]; then
|
||||||
|
Loading…
x
Reference in New Issue
Block a user