Compare commits
19 Commits
a94dc125f4
...
bd32d20a2b
Author | SHA1 | Date |
---|---|---|
p4u1 | bd32d20a2b | |
p4u1 | 621858e6a1 | |
p4u1 | 53e13b3d68 | |
p4u1 | e8340cd40a | |
p4u1 | 0841de7c9e | |
p4u1 | 17a558489c | |
p4u1 | ea92a9f879 | |
p4u1 | 0c6792057a | |
p4u1 | 8dac0e0e68 | |
p4u1 | b2f290ce3e | |
decentral1se | 66b40a9189 | |
decentral1se | 049f02f063 | |
decentral1se | 15857e6453 | |
decentral1se | 31e0ed75b0 | |
p4u1 | b1d3fcbb0b | |
p4u1 | 7b6134f35e | |
decentral1se | 316b59b465 | |
decentral1se | 92b073d5b6 | |
Comrade Renovate Bot | 9b0dd933b5 |
|
@ -11,6 +11,7 @@
|
|||
- kawaiipunk
|
||||
- knoflook
|
||||
- moritz
|
||||
- p4u1
|
||||
- rix
|
||||
- roxxers
|
||||
- vera
|
||||
|
|
7
Makefile
7
Makefile
|
@ -2,6 +2,7 @@ ABRA := ./cmd/abra
|
|||
KADABRA := ./cmd/kadabra
|
||||
COMMIT := $(shell git rev-list -1 HEAD)
|
||||
GOPATH := $(shell go env GOPATH)
|
||||
GOVERSION := 1.21
|
||||
LDFLAGS := "-X 'main.Commit=$(COMMIT)'"
|
||||
DIST_LDFLAGS := $(LDFLAGS)" -s -w"
|
||||
|
||||
|
@ -30,6 +31,12 @@ build-kadabra:
|
|||
|
||||
build: build-abra build-kadabra
|
||||
|
||||
build-docker-abra:
|
||||
@docker run -it -v $(PWD):/abra golang:$(GOVERSION) \
|
||||
bash -c 'cd /abra; ./scripts/docker/build.sh'
|
||||
|
||||
build-docker: build-docker-abra
|
||||
|
||||
clean:
|
||||
@rm '$(GOPATH)/bin/abra'
|
||||
@rm '$(GOPATH)/bin/kadabra'
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"coopcloud.tech/abra/cli/internal"
|
||||
"coopcloud.tech/abra/pkg/app"
|
||||
"coopcloud.tech/abra/pkg/autocomplete"
|
||||
"coopcloud.tech/abra/pkg/client"
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
|
@ -45,6 +46,17 @@ Example:
|
|||
},
|
||||
Before: internal.SubCommandBefore,
|
||||
Subcommands: []cli.Command{appCmdListCommand},
|
||||
BashComplete: func(ctx *cli.Context) {
|
||||
args := ctx.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
autocomplete.AppNameComplete(ctx)
|
||||
case 1:
|
||||
autocomplete.ServiceNameComplete(args.Get(0))
|
||||
case 2:
|
||||
cmdNameComplete(args.Get(0))
|
||||
}
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
app := internal.ValidateApp(c)
|
||||
|
||||
|
@ -187,6 +199,20 @@ func parseCmdArgs(args []string, isLocal bool) (bool, string) {
|
|||
return hasCmdArgs, parsedCmdArgs
|
||||
}
|
||||
|
||||
func cmdNameComplete(appName string) {
|
||||
app, err := app.Get(appName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cmdNames, _ := getShCmdNames(app)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, n := range cmdNames {
|
||||
fmt.Println(n)
|
||||
}
|
||||
}
|
||||
|
||||
var appCmdListCommand = cli.Command{
|
||||
Name: "list",
|
||||
Aliases: []string{"ls"},
|
||||
|
@ -222,13 +248,11 @@ var appCmdListCommand = cli.Command{
|
|||
}
|
||||
}
|
||||
|
||||
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh")
|
||||
cmdNames, err := config.ReadAbraShCmdNames(abraShPath)
|
||||
cmdNames, err := getShCmdNames(app)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
sort.Strings(cmdNames)
|
||||
for _, cmdName := range cmdNames {
|
||||
fmt.Println(cmdName)
|
||||
}
|
||||
|
@ -236,3 +260,14 @@ var appCmdListCommand = cli.Command{
|
|||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func getShCmdNames(app config.App) ([]string, error) {
|
||||
abraShPath := fmt.Sprintf("%s/%s/%s", config.RECIPES_DIR, app.Recipe, "abra.sh")
|
||||
cmdNames, err := config.ReadAbraShCmdNames(abraShPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Strings(cmdNames)
|
||||
return cmdNames, nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
@ -62,7 +61,7 @@ And if you want to copy that file back to your current working directory locally
|
|||
|
||||
srcPath, dstPath, service, toContainer, err := parseSrcAndDst(src, dst)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
cl, err := client.New(app.Server)
|
||||
|
@ -107,22 +106,8 @@ func parseSrcAndDst(src, dst string) (srcPath string, dstPath string, service st
|
|||
return "", "", "", false, errServiceMissing
|
||||
}
|
||||
|
||||
type CopyMode int
|
||||
|
||||
const (
|
||||
CopyModeFileToFile = CopyMode(iota)
|
||||
CopyModeFileToFileRename
|
||||
CopyModeFileToDir
|
||||
CopyModeDirToDir
|
||||
CopyModeFilesToDir
|
||||
)
|
||||
|
||||
// copyToContainer works with one of the following:
|
||||
//
|
||||
// <file> + <dst_dir> = <dst_dir>/<file>
|
||||
// <file> + <dst_dir>/<file> = <dst_dir>/<file> (overrides the file)
|
||||
// <src_dir> + <dst_dir> = <dst_dir>/<src_dir>/<contents_of_src_dir>
|
||||
// <src_dir>/ + <dst_dir> = <dst_dir>/<contents_of_src_dir>
|
||||
// copyToContainer copies a file or directory from the local file system to the container.
|
||||
// See the possible copy modes and their documentation.
|
||||
func copyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath string) error {
|
||||
srcStat, err := os.Stat(srcPath)
|
||||
if err != nil {
|
||||
|
@ -167,7 +152,7 @@ func copyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath stri
|
|||
}
|
||||
case CopyModeFileToFile:
|
||||
// Remove the file component from the path, since docker can only copy
|
||||
// to a directoy.
|
||||
// to a directory.
|
||||
dstPath, _ = path.Split(dstPath)
|
||||
case CopyModeFileToFileRename:
|
||||
// Copy the file to the temp directory and move it to its dstPath
|
||||
|
@ -209,6 +194,8 @@ func copyToContainer(cl *dockerClient.Client, containerID, srcPath, dstPath stri
|
|||
return nil
|
||||
}
|
||||
|
||||
// copyFromContainer copies a file or directory from the given container to the local file system.
|
||||
// See the possible copy modes and their documentation.
|
||||
func copyFromContainer(cl *dockerClient.Client, containerID, srcPath, dstPath string) error {
|
||||
srcStat, err := cl.ContainerStatPath(context.Background(), containerID, srcPath)
|
||||
if err != nil {
|
||||
|
@ -242,7 +229,7 @@ func copyFromContainer(cl *dockerClient.Client, containerID, srcPath, dstPath st
|
|||
switch mode {
|
||||
case CopyModeFileToFile:
|
||||
// Remove the file component from the path, since docker can only copy
|
||||
// to a directoy.
|
||||
// to a directory.
|
||||
dstPath, _ = path.Split(dstPath)
|
||||
case CopyModeFileToFileRename:
|
||||
// Copy the file to the temp directory and move it to its dstPath
|
||||
|
@ -292,6 +279,29 @@ var (
|
|||
ErrDstDirNotExist = fmt.Errorf("destination directory does not exist")
|
||||
)
|
||||
|
||||
type CopyMode int
|
||||
|
||||
const (
|
||||
// Copy a src file to a dest file. The src and dest file names are the same.
|
||||
// <dir_src>/<file> + <dir_dst>/<file> -> <dir_dst>/<file>
|
||||
CopyModeFileToFile = CopyMode(iota)
|
||||
// Copy a src file to a dest file. The src and dest file names are not the same.
|
||||
// <dir_src>/<file_src> + <dir_dst>/<file_dst> -> <dir_dst>/<file_dst>
|
||||
CopyModeFileToFileRename
|
||||
// Copy a src file to dest directory. The dest file gets created in the dest
|
||||
// folder with the src filename.
|
||||
// <dir_src>/<file> + <dir_dst> -> <dir_dst>/<file>
|
||||
CopyModeFileToDir
|
||||
// Copy a src directory to dest directory.
|
||||
// <dir_src> + <dir_dst> -> <dir_dst>/<dir_src>
|
||||
CopyModeDirToDir
|
||||
// Copy all files in the src directory to the dest directory. This works recursively.
|
||||
// <dir_src>/ + <dir_dst> -> <dir_dst>/<files_from_dir_src>
|
||||
CopyModeFilesToDir
|
||||
)
|
||||
|
||||
// copyMode takes a src and dest path and file mode to determine the copy mode.
|
||||
// See the possible copy modes and their documentation.
|
||||
func copyMode(srcPath, dstPath string, srcMode os.FileMode, dstMode os.FileMode, dstExists bool) (CopyMode, error) {
|
||||
_, srcFile := path.Split(srcPath)
|
||||
_, dstFile := path.Split(dstPath)
|
||||
|
|
4
go.mod
4
go.mod
|
@ -16,7 +16,7 @@ require (
|
|||
github.com/moby/term v0.5.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/schollz/progressbar/v3 v3.14.0
|
||||
github.com/schollz/progressbar/v3 v3.14.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
gotest.tools/v3 v3.5.1
|
||||
)
|
||||
|
@ -82,7 +82,7 @@ require (
|
|||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/term v0.14.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
|
|
8
go.sum
8
go.sum
|
@ -901,8 +901,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
|
|||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/schollz/progressbar/v3 v3.14.0 h1:rFEVJhQPeI8aAXu2xOGjTQ1+w+8SSzQf99fO1q3kQxs=
|
||||
github.com/schollz/progressbar/v3 v3.14.0/go.mod h1:l7jf8Ehh0x7Li8QCcEe28x7lf/9HJXLQm67VKd10NqU=
|
||||
github.com/schollz/progressbar/v3 v3.14.1 h1:VD+MJPCr4s3wdhTc7OEJ/Z3dAeBzJ7yKH/P4lC5yRTI=
|
||||
github.com/schollz/progressbar/v3 v3.14.1/go.mod h1:Zc9xXneTzWXF81TGoqL71u0sBPjULtEHYtj/WVgVy8E=
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
|
@ -1324,8 +1324,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
|
|||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
|
||||
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -25,6 +25,16 @@ func AppNameComplete(c *cli.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func ServiceNameComplete(appName string) {
|
||||
serviceNames, err := config.GetAppServiceNames(appName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, s := range serviceNames {
|
||||
fmt.Println(s)
|
||||
}
|
||||
}
|
||||
|
||||
// RecipeNameComplete completes recipe names.
|
||||
func RecipeNameComplete(c *cli.Context) {
|
||||
catl, err := recipe.ReadRecipeCatalogue(false)
|
||||
|
|
|
@ -69,7 +69,7 @@ func GetContainer(c context.Context, cl *client.Client, filters filters.Args, no
|
|||
return containers[0], nil
|
||||
}
|
||||
|
||||
// Retrieves the container for the given stack and service.
|
||||
// GetContainerFromStackAndService retrieves the container for the given stack and service.
|
||||
func GetContainerFromStackAndService(cl *client.Client, stack, service string) (types.Container, error) {
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("name", fmt.Sprintf("^%s_%s", stack, service))
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ! -f .envrc ]; then
|
||||
. .envrc.sample
|
||||
else
|
||||
. .envrc
|
||||
fi
|
||||
|
||||
git config --global --add safe.directory /abra # work around funky file permissions
|
||||
|
||||
make build
|
|
@ -25,6 +25,24 @@ teardown(){
|
|||
fi
|
||||
}
|
||||
|
||||
# bats test_tags=slow
|
||||
@test "autocomplete" {
|
||||
run $ABRA app cmd --generate-bash-completion
|
||||
assert_success
|
||||
assert_output "$TEST_APP_DOMAIN"
|
||||
|
||||
run $ABRA app cmd "$TEST_APP_DOMAIN" --generate-bash-completion
|
||||
assert_success
|
||||
assert_output "app"
|
||||
|
||||
run $ABRA app cmd "$TEST_APP_DOMAIN" app --generate-bash-completion
|
||||
assert_success
|
||||
assert_output "test_cmd
|
||||
test_cmd_arg
|
||||
test_cmd_args
|
||||
test_cmd_export"
|
||||
}
|
||||
|
||||
@test "validate app argument" {
|
||||
run $ABRA app cmd
|
||||
assert_failure
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
_common_setup() {
|
||||
load '/usr/lib/bats/bats-support/load'
|
||||
load '/usr/lib/bats/bats-assert/load'
|
||||
load '/usr/lib/bats/bats-file/load'
|
||||
bats_load_library bats-support
|
||||
bats_load_library bats-assert
|
||||
bats_load_library bats-file
|
||||
|
||||
load "$PWD/tests/integration/helpers/app"
|
||||
load "$PWD/tests/integration/helpers/git"
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
_add_server() {
|
||||
run $ABRA server add "$TEST_SERVER"
|
||||
if [[ "$TEST_SERVER" == "default" ]]; then
|
||||
run $ABRA server add -l
|
||||
else
|
||||
run $ABRA server add "$TEST_SERVER"
|
||||
fi
|
||||
assert_success
|
||||
assert_exists "$ABRA_DIR/servers/$TEST_SERVER"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue