forked from toolshed/abra
Compare commits
18 Commits
main
...
0.4.0-alpha-rc8
| Author | SHA1 | Date | |
|---|---|---|---|
|
6998298d32
|
|||
|
323f4467c8
|
|||
|
e8e41850b5
|
|||
|
0e23ec53d7
|
|||
|
b943a8b9b1
|
|||
|
acc665f054
|
|||
| 860f1d6376 | |||
| 2122f0e67c | |||
| 6aa23a76a1 | |||
|
338360096c
|
|||
|
7a8c7cd50f
|
|||
|
bafc8a8e34
|
|||
|
3d44d8c9fd
|
|||
|
b8b4616498
|
|||
| da97117929 | |||
| 978297c464 | |||
| 11da4808fc | |||
|
4023e6a066
|
-10
@@ -7,16 +7,6 @@ steps:
|
||||
commands:
|
||||
- make check
|
||||
|
||||
- name: make static
|
||||
image: golang:1.18
|
||||
ignore: true # until we decide we all want this check
|
||||
environment:
|
||||
STATIC_CHECK_URL: honnef.co/go/tools/cmd/staticcheck
|
||||
STATIC_CHECK_VERSION: v0.2.0
|
||||
commands:
|
||||
- go install $STATIC_CHECK_URL@$STATIC_CHECK_VERSION
|
||||
- make static
|
||||
|
||||
- name: make build
|
||||
image: golang:1.18
|
||||
commands:
|
||||
|
||||
@@ -5,7 +5,7 @@ LDFLAGS := "-X 'main.Commit=$(COMMIT)'"
|
||||
DIST_LDFLAGS := $(LDFLAGS)" -s -w"
|
||||
export GOPRIVATE=coopcloud.tech
|
||||
|
||||
all: format check static build test
|
||||
all: format check build test
|
||||
|
||||
run:
|
||||
@go run -ldflags=$(LDFLAGS) $(ABRA)
|
||||
@@ -28,9 +28,6 @@ format:
|
||||
check:
|
||||
@test -z $$(gofmt -l .) || (echo "gofmt: formatting issue - run 'make format' to resolve" && exit 1)
|
||||
|
||||
static:
|
||||
@staticcheck $(ABRA)
|
||||
|
||||
test:
|
||||
@go test ./... -cover -v
|
||||
|
||||
|
||||
@@ -29,5 +29,6 @@ var AppCommand = cli.Command{
|
||||
appVolumeCommand,
|
||||
appVersionCommand,
|
||||
appErrorsCommand,
|
||||
appCmdCommand,
|
||||
},
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
var appCheckCommand = cli.Command{
|
||||
Name: "check",
|
||||
Aliases: []string{"c"},
|
||||
Aliases: []string{"chk"},
|
||||
Usage: "Check if app is configured correctly",
|
||||
ArgsUsage: "<domain>",
|
||||
Flags: []cli.Flag{
|
||||
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"coopcloud.tech/abra/cli/internal"
|
||||
"coopcloud.tech/abra/pkg/autocomplete"
|
||||
"coopcloud.tech/abra/pkg/client"
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
containerPkg "coopcloud.tech/abra/pkg/container"
|
||||
"coopcloud.tech/abra/pkg/formatter"
|
||||
"coopcloud.tech/abra/pkg/upstream/container"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var localCmd bool
|
||||
var localCmdFlag = &cli.BoolFlag{
|
||||
Name: "local, l",
|
||||
Usage: "Run command locally",
|
||||
Destination: &localCmd,
|
||||
}
|
||||
|
||||
var remoteUser string
|
||||
var remoteUserFlag = &cli.StringFlag{
|
||||
Name: "user, u",
|
||||
Value: "",
|
||||
Usage: "User to run command within a service context",
|
||||
Destination: &remoteUser,
|
||||
}
|
||||
|
||||
var appCmdCommand = cli.Command{
|
||||
Name: "command",
|
||||
Aliases: []string{"cmd"},
|
||||
Usage: "Run app commands",
|
||||
Description: `
|
||||
This command runs app specific commands.
|
||||
|
||||
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
|
||||
work station by passing "--local". Arguments can be passed into these functions
|
||||
using the "-- <args>" syntax.
|
||||
|
||||
Example:
|
||||
|
||||
abra app cmd example.com app create_user -- me@example.com
|
||||
`,
|
||||
ArgsUsage: "<domain> [<service>] <command>",
|
||||
Flags: []cli.Flag{
|
||||
internal.DebugFlag,
|
||||
localCmdFlag,
|
||||
remoteUserFlag,
|
||||
},
|
||||
BashComplete: autocomplete.AppNameComplete,
|
||||
Before: internal.SubCommandBefore,
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
|
||||
if localCmd && remoteUser != "" {
|
||||
internal.ShowSubcommandHelpAndError(c, errors.New("cannot use --local & <user> together"))
|
||||
}
|
||||
|
||||
abraSh := path.Join(config.RECIPES_DIR, app.Recipe, "abra.sh")
|
||||
if _, err := os.Stat(abraSh); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
logrus.Fatalf("%s does not exist for %s?", abraSh, app.Name)
|
||||
}
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
var parsedCmdArgs string
|
||||
var cmdArgsIdx int
|
||||
var hasCmdArgs bool
|
||||
for idx, arg := range c.Args() {
|
||||
if arg == "--" {
|
||||
cmdArgsIdx = idx
|
||||
hasCmdArgs = true
|
||||
}
|
||||
|
||||
if hasCmdArgs && idx > cmdArgsIdx {
|
||||
parsedCmdArgs += fmt.Sprintf("%s ", c.Args().Get(idx))
|
||||
}
|
||||
}
|
||||
|
||||
if localCmd {
|
||||
cmdName := c.Args().Get(1)
|
||||
if err := ensureCommand(abraSh, app.Recipe, cmdName); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
logrus.Debugf("--local detected, running %s on local work station", cmdName)
|
||||
|
||||
var sourceAndExec string
|
||||
if hasCmdArgs {
|
||||
logrus.Debugf("parsed following command arguments: %s", parsedCmdArgs)
|
||||
sourceAndExec = fmt.Sprintf("TARGET=local; APP_NAME=%s; . %s; %s %s", app.StackName(), abraSh, cmdName, parsedCmdArgs)
|
||||
} else {
|
||||
logrus.Debug("did not detect any command arguments")
|
||||
sourceAndExec = fmt.Sprintf("TARGET=local; APP_NAME=%s; . %s; %s", app.StackName(), abraSh, cmdName)
|
||||
}
|
||||
|
||||
cmd := exec.Command("/bin/sh", "-c", sourceAndExec)
|
||||
|
||||
if err := internal.RunCmd(cmd); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
targetServiceName := c.Args().Get(1)
|
||||
|
||||
cmdName := c.Args().Get(2)
|
||||
if err := ensureCommand(abraSh, app.Recipe, cmdName); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
serviceNames, err := config.GetAppServiceNames(app.Name)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
matchingServiceName := false
|
||||
for _, serviceName := range serviceNames {
|
||||
if serviceName == targetServiceName {
|
||||
matchingServiceName = true
|
||||
}
|
||||
}
|
||||
|
||||
if !matchingServiceName {
|
||||
logrus.Fatalf("no service %s for %s?", targetServiceName, app.Name)
|
||||
}
|
||||
|
||||
logrus.Debugf("running command %s within the context of %s_%s", cmdName, app.StackName(), targetServiceName)
|
||||
|
||||
if hasCmdArgs {
|
||||
logrus.Debugf("parsed following command arguments: %s", parsedCmdArgs)
|
||||
} else {
|
||||
logrus.Debug("did not detect any command arguments")
|
||||
}
|
||||
|
||||
if err := runCmdRemote(app, abraSh, targetServiceName, cmdName, parsedCmdArgs); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func ensureCommand(abraSh, recipeName, execCmd string) error {
|
||||
bytes, err := ioutil.ReadFile(abraSh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !strings.Contains(string(bytes), execCmd) {
|
||||
return fmt.Errorf("%s doesn't have a %s function", recipeName, execCmd)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCmdRemote(app config.App, abraSh, serviceName, cmdName, cmdArgs string) error {
|
||||
cl, err := client.New(app.Server)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), serviceName))
|
||||
|
||||
targetContainer, err := containerPkg.GetContainer(context.Background(), cl, filters, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf("retrieved %s as target container on %s", formatter.ShortenID(targetContainer.ID), app.Server)
|
||||
|
||||
toTarOpts := &archive.TarOptions{NoOverwriteDirNonDir: true, Compression: archive.Gzip}
|
||||
content, err := archive.TarWithOptions(abraSh, toTarOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
copyOpts := types.CopyToContainerOptions{AllowOverwriteDirWithFile: false, CopyUIDGID: false}
|
||||
if err := cl.CopyToContainer(context.Background(), targetContainer.ID, "/tmp", content, copyOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cmd []string
|
||||
if cmdArgs != "" {
|
||||
cmd = []string{"/bin/sh", "-c", fmt.Sprintf("TARGET=%s; APP_NAME=%s; . /tmp/abra.sh; %s %s", serviceName, app.StackName(), cmdName, cmdArgs)}
|
||||
} else {
|
||||
cmd = []string{"/bin/sh", "-c", fmt.Sprintf("TARGET=%s; APP_NAME=%s; . /tmp/abra.sh; %s", serviceName, app.StackName(), cmdName)}
|
||||
}
|
||||
|
||||
logrus.Debugf("running command: %s", strings.Join(cmd, " "))
|
||||
|
||||
execCreateOpts := types.ExecConfig{
|
||||
AttachStderr: true,
|
||||
AttachStdin: true,
|
||||
AttachStdout: true,
|
||||
Cmd: cmd,
|
||||
Detach: false,
|
||||
Tty: true,
|
||||
}
|
||||
|
||||
if remoteUser != "" {
|
||||
logrus.Debugf("running command with user %s", remoteUser)
|
||||
execCreateOpts.User = remoteUser
|
||||
}
|
||||
|
||||
// FIXME: avoid instantiating a new CLI
|
||||
dcli, err := command.NewDockerCli()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := container.RunExec(dcli, cl, targetContainer.ID, &execCreateOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
var appConfigCommand = cli.Command{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Aliases: []string{"cfg"},
|
||||
Usage: "Edit app config",
|
||||
ArgsUsage: "<domain>",
|
||||
Flags: []cli.Flag{
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ func configureAndCp(
|
||||
}
|
||||
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", fmt.Sprintf("%s_%s", app.StackName(), service))
|
||||
filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), service))
|
||||
|
||||
container, err := container.GetContainer(context.Background(), cl, filters, internal.NoInput)
|
||||
if err != nil {
|
||||
|
||||
+3
-1
@@ -2,6 +2,7 @@ package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -95,7 +96,8 @@ func checkErrors(c *cli.Context, cl *dockerClient.Client, app config.App) error
|
||||
|
||||
for _, service := range recipe.Config.Services {
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", service.Name)
|
||||
filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), service.Name))
|
||||
|
||||
containers, err := cl.ContainerList(context.Background(), types.ContainerListOptions{Filters: filters})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+9
-5
@@ -29,9 +29,12 @@ var logOpts = types.ContainerLogsOptions{
|
||||
}
|
||||
|
||||
// stackLogs lists logs for all stack services
|
||||
func stackLogs(c *cli.Context, stackName string, client *dockerClient.Client) {
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", stackName)
|
||||
func stackLogs(c *cli.Context, app config.App, client *dockerClient.Client) {
|
||||
filters, err := app.Filters(true, false)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
serviceOpts := types.ServiceListOptions{Filters: filters}
|
||||
services, err := client.ServiceList(context.Background(), serviceOpts)
|
||||
if err != nil {
|
||||
@@ -86,7 +89,7 @@ var appLogsCommand = cli.Command{
|
||||
serviceName := c.Args().Get(1)
|
||||
if serviceName == "" {
|
||||
logrus.Debugf("tailing logs for all %s services", app.Recipe)
|
||||
stackLogs(c, app.StackName(), cl)
|
||||
stackLogs(c, app, cl)
|
||||
} else {
|
||||
logrus.Debugf("tailing logs for %s", serviceName)
|
||||
if err := tailServiceLogs(c, cl, app, serviceName); err != nil {
|
||||
@@ -100,7 +103,8 @@ var appLogsCommand = cli.Command{
|
||||
|
||||
func tailServiceLogs(c *cli.Context, cl *dockerClient.Client, app config.App, serviceName string) error {
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", fmt.Sprintf("%s_%s", app.StackName(), serviceName))
|
||||
filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), serviceName))
|
||||
|
||||
chosenService, err := service.GetService(context.Background(), cl, filters, internal.NoInput)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
|
||||
+4
-3
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/buger/goterm"
|
||||
dockerFormatter "github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
dockerClient "github.com/docker/docker/client"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
@@ -67,8 +66,10 @@ var appPsCommand = cli.Command{
|
||||
|
||||
// showPSOutput renders ps output.
|
||||
func showPSOutput(c *cli.Context, app config.App, cl *dockerClient.Client) {
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", app.StackName())
|
||||
filters, err := app.Filters(true, true)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
containers, err := cl.ContainerList(context.Background(), types.ContainerListOptions{Filters: filters})
|
||||
if err != nil {
|
||||
|
||||
+10
-3
@@ -11,7 +11,6 @@ import (
|
||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@@ -66,8 +65,11 @@ var appRemoveCommand = cli.Command{
|
||||
logrus.Fatalf("%s is still deployed. Run \"abra app undeploy %s\"", app.Name, app.Name)
|
||||
}
|
||||
|
||||
fs := filters.NewArgs()
|
||||
fs.Add("name", app.StackName())
|
||||
fs, err := app.Filters(false, false)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
secretList, err := cl.SecretList(context.Background(), types.SecretListOptions{Filters: fs})
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
@@ -112,6 +114,11 @@ var appRemoveCommand = cli.Command{
|
||||
logrus.Info("no secrets to remove")
|
||||
}
|
||||
|
||||
fs, err = app.Filters(false, true)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
volumeListOKBody, err := cl.VolumeList(context.Background(), fs)
|
||||
volumeList := volumeListOKBody.Volumes
|
||||
if err != nil {
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ var appRunCommand = cli.Command{
|
||||
}
|
||||
|
||||
serviceName := c.Args().Get(1)
|
||||
stackAndServiceName := fmt.Sprintf("%s_%s", app.StackName(), serviceName)
|
||||
stackAndServiceName := fmt.Sprintf("^%s_%s", app.StackName(), serviceName)
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", stackAndServiceName)
|
||||
|
||||
|
||||
+10
-5
@@ -14,7 +14,6 @@ import (
|
||||
"coopcloud.tech/abra/pkg/formatter"
|
||||
"coopcloud.tech/abra/pkg/secret"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
dockerClient "github.com/docker/docker/client"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
@@ -217,8 +216,11 @@ Example:
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", app.StackName())
|
||||
filters, err := app.Filters(false, false)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
secretList, err := cl.SecretList(context.Background(), types.SecretListOptions{Filters: filters})
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
@@ -291,8 +293,11 @@ var appSecretLsCommand = cli.Command{
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", app.StackName())
|
||||
filters, err := app.Filters(false, false)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
secretList, err := cl.SecretList(context.Background(), types.SecretListOptions{Filters: filters})
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
|
||||
+12
-2
@@ -26,7 +26,12 @@ var appVolumeListCommand = cli.Command{
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
|
||||
volumeList, err := client.GetVolumes(context.Background(), app.Server, app.StackName())
|
||||
filters, err := app.Filters(false, true)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
volumeList, err := client.GetVolumes(context.Background(), app.Server, filters)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
@@ -75,7 +80,12 @@ Passing "--force/-f" will select all volumes for removal. Be careful.
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
|
||||
volumeList, err := client.GetVolumes(context.Background(), app.Server, app.StackName())
|
||||
filters, err := app.Filters(false, true)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
volumeList, err := client.GetVolumes(context.Background(), app.Server, filters)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
+4
-4
@@ -132,10 +132,6 @@ func NewAction(c *cli.Context) error {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
if err := promptForSecrets(Domain); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
sanitisedAppName := config.SanitiseAppName(Domain)
|
||||
logrus.Debugf("%s sanitised as %s for new app", Domain, sanitisedAppName)
|
||||
|
||||
@@ -143,6 +139,10 @@ func NewAction(c *cli.Context) error {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
if err := promptForSecrets(Domain); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
var secrets AppSecrets
|
||||
var secretTable *tablewriter.Table
|
||||
if Secrets {
|
||||
|
||||
@@ -4,12 +4,12 @@ go 1.16
|
||||
|
||||
require (
|
||||
coopcloud.tech/tagcmp v0.0.0-20211103052201-885b22f77d52
|
||||
github.com/AlecAivazis/survey/v2 v2.3.2
|
||||
github.com/AlecAivazis/survey/v2 v2.3.4
|
||||
github.com/Autonomic-Cooperative/godotenv v1.3.1-0.20210731094149-b031ea1211e7
|
||||
github.com/Gurpartap/logrus-stack v0.0.0-20170710170904-89c00d8a28f4
|
||||
github.com/docker/cli v20.10.13+incompatible
|
||||
github.com/docker/cli v20.10.14+incompatible
|
||||
github.com/docker/distribution v2.8.1+incompatible
|
||||
github.com/docker/docker v20.10.13+incompatible
|
||||
github.com/docker/docker v20.10.14+incompatible
|
||||
github.com/docker/go-units v0.4.0
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/hetznercloud/hcloud-go v1.33.1
|
||||
|
||||
@@ -51,8 +51,8 @@ coopcloud.tech/libcapsul v0.0.0-20211022074848-c35e78fe3f3e/go.mod h1:HEQ9pSJRsD
|
||||
coopcloud.tech/tagcmp v0.0.0-20211103052201-885b22f77d52 h1:cyFFOl0tKe+dVHt8saejG8xoff33eQiHxFCVzRpPUjM=
|
||||
coopcloud.tech/tagcmp v0.0.0-20211103052201-885b22f77d52/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.4 h1:pchTU9rsLUSvWEl2Aq9Pv3k0IE2fkqtGxazskAMd9Ng=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.4/go.mod h1:hrV6Y/kQCLhIZXGcriDCUBtB3wnN7156gMXJ3+b23xM=
|
||||
github.com/Autonomic-Cooperative/godotenv v1.3.1-0.20210731094149-b031ea1211e7 h1:asQtdXYbxEYWcwAQqJTVYC/RltB4eqoWKvqWg/LFPOg=
|
||||
github.com/Autonomic-Cooperative/godotenv v1.3.1-0.20210731094149-b031ea1211e7/go.mod h1:oZRCMMRS318l07ei4DTqbZoOawfJlJ4yyo8juk2v4Rk=
|
||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
@@ -101,8 +101,8 @@ github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfy
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 h1:XcF0cTDJeiuZ5NU8w7WUDge0HRwwNRmxj/GGk6KSA6g=
|
||||
@@ -312,8 +312,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKY
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
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.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
|
||||
@@ -331,16 +332,16 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v20.10.13+incompatible h1:o/STAn7e+b/pQ6keReGRoewVmAgXUkZAMQ8st4vHdKg=
|
||||
github.com/docker/cli v20.10.13+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v20.10.14+incompatible h1:dSBKJOVesDgHo7rbxlYjYsXe7gPzrTT+/cKQgpDAazg=
|
||||
github.com/docker/cli v20.10.14+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v20.10.13+incompatible h1:5s7uxnKZG+b8hYWlPYUi6x1Sjpq2MSt96d15eLZeHyw=
|
||||
github.com/docker/docker v20.10.13+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v20.10.14+incompatible h1:+T9/PRYWNDo5SZl5qS1r9Mo/0Q8AwxKKPtu9S1yxM0w=
|
||||
github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
|
||||
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
|
||||
@@ -603,8 +604,8 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN
|
||||
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
github.com/hetznercloud/hcloud-go v1.33.1 h1:W1HdO2bRLTKU4WsyqAasDSpt54fYO4WNckWYfH5AuCQ=
|
||||
github.com/hetznercloud/hcloud-go v1.33.1/go.mod h1:XX/TQub3ge0yWR2yHWmnDVIrB+MQbda1pHxkUmDlUME=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -667,8 +668,6 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5 h1:hyz3dwM5QLc1Rfoz4FuWJQG5BN7tc6K1MndAUnGpQr4=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@@ -953,7 +952,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
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/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.1/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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@@ -1046,7 +1044,6 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
||||
@@ -7,15 +7,12 @@ import (
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
)
|
||||
|
||||
func GetVolumes(ctx context.Context, server string, appName string) ([]*types.Volume, error) {
|
||||
func GetVolumes(ctx context.Context, server string, fs filters.Args) ([]*types.Volume, error) {
|
||||
cl, err := New(server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fs := filters.NewArgs()
|
||||
fs.Add("name", appName)
|
||||
|
||||
volumeListOKBody, err := cl.VolumeList(ctx, fs)
|
||||
volumeList := volumeListOKBody.Volumes
|
||||
if err != nil {
|
||||
|
||||
+51
-1
@@ -13,6 +13,7 @@ import (
|
||||
loader "coopcloud.tech/abra/pkg/upstream/stack"
|
||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||
composetypes "github.com/docker/cli/cli/compose/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -63,6 +64,49 @@ func (a App) StackName() string {
|
||||
return stackName
|
||||
}
|
||||
|
||||
// Filters retrieves exact app filters for querying the container runtime. Due
|
||||
// to upstream issues, filtering works different depending on what you're
|
||||
// querying. So, for example, secrets don't work with regex! The caller needs
|
||||
// to implement their own validation that the right secrets are matched. In
|
||||
// order to handle these cases, we provide the `appendServiceNames` /
|
||||
// `exactMatch` modifiers.
|
||||
func (a App) Filters(appendServiceNames, exactMatch bool) (filters.Args, error) {
|
||||
filters := filters.NewArgs()
|
||||
|
||||
composeFiles, err := GetAppComposeFiles(a.Recipe, a.Env)
|
||||
if err != nil {
|
||||
return filters, err
|
||||
}
|
||||
|
||||
opts := stack.Deploy{Composefiles: composeFiles}
|
||||
compose, err := GetAppComposeConfig(a.Recipe, opts, a.Env)
|
||||
if err != nil {
|
||||
return filters, err
|
||||
}
|
||||
|
||||
for _, service := range compose.Services {
|
||||
var filter string
|
||||
|
||||
if appendServiceNames {
|
||||
if exactMatch {
|
||||
filter = fmt.Sprintf("^%s_%s", a.StackName(), service.Name)
|
||||
} else {
|
||||
filter = fmt.Sprintf("%s_%s", a.StackName(), service.Name)
|
||||
}
|
||||
} else {
|
||||
if exactMatch {
|
||||
filter = fmt.Sprintf("^%s", a.StackName())
|
||||
} else {
|
||||
filter = fmt.Sprintf("%s", a.StackName())
|
||||
}
|
||||
}
|
||||
|
||||
filters.Add("name", filter)
|
||||
}
|
||||
|
||||
return filters, nil
|
||||
}
|
||||
|
||||
// ByServer sort a slice of Apps
|
||||
type ByServer []App
|
||||
|
||||
@@ -288,7 +332,13 @@ func TemplateAppEnvSample(recipeName, appName, server, domain string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tpl.Execute(file, struct{ Name string }{recipeName}); err != nil {
|
||||
type templateVars struct {
|
||||
Name string
|
||||
Domain string
|
||||
}
|
||||
|
||||
tvars := templateVars{Name: recipeName, Domain: domain}
|
||||
if err := tpl.Execute(file, tvars); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
ABRA_VERSION="0.3.0-alpha"
|
||||
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/coop-cloud/abra/releases/tags/$ABRA_VERSION"
|
||||
RC_VERSION="0.4.0-alpha-rc6"
|
||||
RC_VERSION="0.4.0-alpha-rc8"
|
||||
RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/coop-cloud/abra/releases/tags/$RC_VERSION"
|
||||
|
||||
for arg in "$@"; do
|
||||
|
||||
Reference in New Issue
Block a user