Compare commits

..

33 Commits

Author SHA1 Message Date
34775f306b Merge branch 'main' into merge-logging
All checks were successful
continuous-integration/drone/pr Build is passing
2020-12-30 11:21:03 +01:00
375a4dd29d Re-add require_app_latest for custom commands
All checks were successful
continuous-integration/drone/push Build is passing
Revision of 67cce192df.

See https://git.autonomic.zone/coop-cloud/abra/pulls/54#issuecomment-2300.
2020-12-30 11:19:55 +01:00
2b951e9f54 Mark minor
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-30 11:18:32 +01:00
3wc
01184c313a Add missing CHANGELOG entries
All checks were successful
continuous-integration/drone/push Build is passing
Closes #46
2020-12-30 00:43:52 +02:00
3936d6afc0 Merge logs/multilogs and avoid multitail external
All checks were successful
continuous-integration/drone/pr Build is passing
2020-12-29 23:22:46 +01:00
407744827f Add change log entry for #42
All checks were successful
continuous-integration/drone/push Build is passing
See https://git.autonomic.zone/coop-cloud/abra/issues/42.
2020-12-29 17:11:30 +01:00
b634b4c668 Merge pull request 'Make sure to git pull latest changes on ~/.abra/apps side' (#54) from latest-checks into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: https://git.autonomic.zone/coop-cloud/abra/pulls/54
2020-12-29 17:10:16 +01:00
67cce192df Don't do more cloning that necessary
All checks were successful
continuous-integration/drone/pr Build is passing
2020-12-29 17:06:49 +01:00
3a9e141b24 Pull latest changes
Closes https://git.autonomic.zone/coop-cloud/abra/issues/42.
2020-12-29 17:06:32 +01:00
ebfe7ca4e8 Suppress output of clone and do better logging 2020-12-29 17:05:30 +01:00
fff2fbe819 Prepare function name for new functionality 2020-12-29 17:05:00 +01:00
f213c3df5f Follow convention and show type of message 2020-12-29 17:04:17 +01:00
9b1be33018 Mark as quote and not as entry
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-29 15:11:15 +01:00
6ecf4f287a Add missing )
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-29 15:10:57 +01:00
e1d6ff8b73 Add docs link
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-29 15:10:05 +01:00
07d4815a74 Start 0.5.0 change log
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-29 15:08:42 +01:00
33315f6b43 Merge pull request '<app> -> <type>' (#53) from app-goes-to-type into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: https://git.autonomic.zone/coop-cloud/abra/pulls/53
2020-12-29 15:03:43 +01:00
f017324431 <app> -> <type>
All checks were successful
continuous-integration/drone/pr Build is passing
Closes https://git.autonomic.zone/coop-cloud/abra/issues/48.
2020-12-29 14:56:50 +01:00
4339c91cf3 Merge pull request 'Remove abra server use' (#52) from server-use-remove into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: https://git.autonomic.zone/coop-cloud/abra/pulls/52
2020-12-29 14:26:39 +01:00
592f515ec4 Remove abra server use
All checks were successful
continuous-integration/drone/pr Build is passing
2020-12-29 14:24:50 +01:00
3wc
77ba5652b2 Run "check" during "deploy", + "--skip-check"
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-29 11:15:14 +02:00
3wc
fdf6334ed3 Use temporary ABRA_DIr in tests
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-27 21:53:44 +02:00
3wc
73e5e64b9a Bump version
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-27 21:45:37 +02:00
3f9b4477cd Swap args around
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-27 13:11:22 +01:00
3wc
412729aac9 Fix calling logs with no arguments
Some checks failed
continuous-integration/drone/push Build is failing
Closes #31
2020-12-27 12:23:16 +02:00
3wc
8022a2cb41 Add cheeky network command
Some checks failed
continuous-integration/drone/push Build is failing
2020-12-27 12:07:10 +02:00
3wc
35182ed260 Get both .. volume .. and custom commands working 2020-12-27 12:07:10 +02:00
3wc
d90c6ef361 Add --no-tty option to app run 2020-12-27 12:07:10 +02:00
3wc
40ca8dfe93 Add --server filter to app list..
.. and add `server <host> apps` as an alias.
2020-12-27 12:07:10 +02:00
3wc
7f009f927b Fix app ls --status
Closes #35
2020-12-27 12:06:39 +02:00
3wc
e222f4152b Pin kcov version
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-24 01:07:01 +02:00
3wc
893150cdd9 Pin shellcheck version
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-24 00:55:57 +02:00
3wc
61126f16e1 Update installer
Some checks failed
continuous-integration/drone/push Build is failing
2020-12-24 00:50:50 +02:00
6 changed files with 203 additions and 156 deletions

View File

@ -3,7 +3,7 @@ kind: pipeline
name: linters name: linters
steps: steps:
- name: run shellcheck - name: run shellcheck
image: koalaman/shellcheck-alpine:latest image: koalaman/shellcheck-alpine:v0.7.1
commands: commands:
- shellcheck abra - shellcheck abra
@ -15,9 +15,9 @@ steps:
- name: collect code coverage - name: collect code coverage
failure: ignore # until we fix this failure: ignore # until we fix this
image: kcov/kcov:latest image: kcov/kcov:38
commands: commands:
- apk add bats git bash - apt update && apt install -y bats git bash
- kcov . bats tests || true - kcov . bats tests || true
- name: send code coverage report to codecov - name: send code coverage report to codecov

View File

@ -1,6 +1,21 @@
# abra x.x.x (UNRELEASED) # abra x.x.x (UNRELEASED)
- ??? - Drop `multilogs` command ([#56](https://git.autonomic.zone/coop-cloud/abra/pulls/56))
- Remove `server use` command ([#51](https://git.autonomic.zone/coop-cloud/abra/issues/51))
- `new <app>` becomes `new <type>` ([#48](https://git.autonomic.zone/coop-cloud/abra/issues/48))
- `check` is run on `deploy` now and configurable ([77ba5652b2fe15820f5edfa0f642636f7b8eae7e](https://git.autonomic.zone/coop-cloud/abra/commit/77ba5652b2fe15820f5edfa0f642636f7b8eae7e))
- App configurations are always updated now ([#42](https://git.autonomic.zone/coop-cloud/abra/issues/42))
# abra 0.4.1 (2020-12-24)
- Bug-fixes on `app ls --status` & custom commands
- Add `app ls --server=...` and alias
# abra 0.4.0 (2020-12-24)
- New command-line interface based on docopt
- ~/.abra directory instead of expecting local .env files
- Integration tests & code coverage
# abra 0.3.1 (2020-09-27) # abra 0.3.1 (2020-09-27)
@ -8,7 +23,7 @@
# abra 0.3.0 (2020-09-27) # abra 0.3.0 (2020-09-27)
- Add multilogs stack logs implementation ([#8](https://git.autonomic.zone/compose-stacks/abra/issues/8) - Add multilogs stack logs implementation ([#8](https://git.autonomic.zone/compose-stacks/abra/issues/8))
- Add beginnings of "monorepo" functionality - Add beginnings of "monorepo" functionality
# abra 0.2.0 (2020-09-24) # abra 0.2.0 (2020-09-24)

View File

@ -7,6 +7,10 @@
The cooperative cloud utility belt 🎩🐇 The cooperative cloud utility belt 🎩🐇
## Documentation
> [docs.cloud.autonomic.zone](https://docs.cloud.autonomic.zone/)
## Install ## Install
```sh ```sh

306
abra
View File

@ -11,29 +11,28 @@ DOC="
The cooperative cloud utility belt 🎩🐇 The cooperative cloud utility belt 🎩🐇
Usage: Usage:
abra [options] app new [--server=<server>] [--domain=<domain>] [--pass] [--auto] <app> abra [options] app new [--server=<server>] [--domain=<domain>] [--pass] [--auto] <type>
abra [options] app (list|ls) [--status] abra [options] app (list|ls) [--status] [--server=<server>]
abra [options] app <domain> deploy abra [options] app <domain> deploy [--skip-check]
abra [options] app <domain> undeploy abra [options] app <domain> undeploy
abra [options] app <domain> config abra [options] app <domain> config
abra [options] app <domain> (delete|rm) [--force] abra [options] app <domain> (delete|rm) [--force]
abra [options] app <domain> logs [<service>] abra [options] app <domain> logs [<service>]
abra [options] app <domain> multilogs
abra [options] app <domain> cp <src> <dst> abra [options] app <domain> cp <src> <dst>
abra [options] app <domain> check abra [options] app <domain> check
abra [options] app <domain> ps abra [options] app <domain> ps
abra [options] app <domain> run [--user=<user>] <service> <args>... abra [options] app <domain> run [--no-tty] [--user=<user>] <service> <args>...
abra [options] app <domain> run <service> <args>... abra [options] app <domain> run <service> <args>...
abra [options] app <domain> secret auto [--pass] abra [options] app <domain> secret auto [--pass]
abra [options] app <domain> secret generate <secret> <version> [<cmd>] [--pass] abra [options] app <domain> secret generate <secret> <version> [<cmd>] [--pass]
abra [options] app <domain> secret insert <secret> <version> <data> [--pass] abra [options] app <domain> secret insert <secret> <version> <data> [--pass]
abra [options] app <domain> secret (delete|rm) (<secret>|--all) [--pass] [--force] abra [options] app <domain> secret (delete|rm) (<secret>|--all) [--pass] [--force]
abra [options] app <domain> <command> [<arg>] abra [options] app <domain> <command> [<args>...]
abra [options] server add <host> [<user>] [<port>] abra [options] server add <host> [<user>] [<port>]
abra [options] server (list|ls) abra [options] server (list|ls)
abra [options] server rm <host> abra [options] server <host> rm
abra [options] server use <host> abra [options] server <host> init
abra [options] server init <host> abra [options] server <host> apps [--status]
abra [options] upgrade abra [options] upgrade
Options: Options:
@ -144,88 +143,91 @@ eval "var_$1+=($value)"; else eval "var_$1=$value"; fi; return 0; fi; done
return 1; }; stdout() { printf -- "cat <<'EOM'\n%s\nEOM\n" "$1"; }; stderr() { return 1; }; stdout() { printf -- "cat <<'EOM'\n%s\nEOM\n" "$1"; }; stderr() {
printf -- "cat <<'EOM' >&2\n%s\nEOM\n" "$1"; }; error() { printf -- "cat <<'EOM' >&2\n%s\nEOM\n" "$1"; }; error() {
[[ -n $1 ]] && stderr "$1"; stderr "$usage"; _return 1; }; _return() { [[ -n $1 ]] && stderr "$1"; stderr "$usage"; _return 1; }; _return() {
printf -- "exit %d\n" "$1"; exit "$1"; }; set -e; trimmed_doc=${DOC:1:1497} printf -- "exit %d\n" "$1"; exit "$1"; }; set -e; trimmed_doc=${DOC:1:1520}
usage=${DOC:40:1189}; digest=feaba; shorts=(-e -v -h -s '' '' '' '' '' '' '' '') usage=${DOC:40:1212}; digest=7df47
longs=(--env --version --help --stack --server --domain --pass --auto --status --force --user --all) shorts=(-e -h -v -s '' '' '' '' '' '' '' '' '' '')
argcounts=(1 0 0 1 1 1 0 0 0 0 1 0); node_0(){ value __env 0; }; node_1(){ longs=(--env --help --version --stack --server --domain --pass --auto --status --skip-check --force --no-tty --user --all)
switch __version 1; }; node_2(){ switch __help 2; }; node_3(){ value __stack 3 argcounts=(1 0 0 1 1 1 0 0 0 0 0 0 1 0); node_0(){ value __env 0; }; node_1(){
switch __help 1; }; node_2(){ switch __version 2; }; node_3(){ value __stack 3
}; node_4(){ value __server 4; }; node_5(){ value __domain 5; }; node_6(){ }; node_4(){ value __server 4; }; node_5(){ value __domain 5; }; node_6(){
switch __pass 6; }; node_7(){ switch __auto 7; }; node_8(){ switch __status 8; } switch __pass 6; }; node_7(){ switch __auto 7; }; node_8(){ switch __status 8; }
node_9(){ switch __force 9; }; node_10(){ value __user 10; }; node_11(){ node_9(){ switch __skip_check 9; }; node_10(){ switch __force 10; }; node_11(){
switch __all 11; }; node_12(){ value _app_ a; }; node_13(){ value _domain_ a; } switch __no_tty 11; }; node_12(){ value __user 12; }; node_13(){ switch __all 13
node_14(){ value _service_ a; }; node_15(){ value _src_ a; }; node_16(){ }; node_14(){ value _type_ a; }; node_15(){ value _domain_ a; }; node_16(){
value _dst_ a; }; node_17(){ value _args_ a true; }; node_18(){ value _secret_ a value _service_ a; }; node_17(){ value _src_ a; }; node_18(){ value _dst_ a; }
}; node_19(){ value _version_ a; }; node_20(){ value _cmd_ a; }; node_21(){ node_19(){ value _args_ a true; }; node_20(){ value _secret_ a; }; node_21(){
value _data_ a; }; node_22(){ value _command_ a; }; node_23(){ value _arg_ a; } value _version_ a; }; node_22(){ value _cmd_ a; }; node_23(){ value _data_ a; }
node_24(){ value _host_ a; }; node_25(){ value _user_ a; }; node_26(){ node_24(){ value _command_ a; }; node_25(){ value _host_ a; }; node_26(){
value _port_ a; }; node_27(){ _command app; }; node_28(){ _command new; } value _user_ a; }; node_27(){ value _port_ a; }; node_28(){ _command app; }
node_29(){ _command list; }; node_30(){ _command ls; }; node_31(){ node_29(){ _command new; }; node_30(){ _command list; }; node_31(){ _command ls
_command deploy; }; node_32(){ _command undeploy; }; node_33(){ _command config }; node_32(){ _command deploy; }; node_33(){ _command undeploy; }; node_34(){
}; node_34(){ _command delete; }; node_35(){ _command rm; }; node_36(){ _command config; }; node_35(){ _command delete; }; node_36(){ _command rm; }
_command logs; }; node_37(){ _command multilogs; }; node_38(){ _command cp; } node_37(){ _command logs; }; node_38(){ _command cp; }; node_39(){
node_39(){ _command check; }; node_40(){ _command ps; }; node_41(){ _command run _command check; }; node_40(){ _command ps; }; node_41(){ _command run; }
}; node_42(){ _command secret; }; node_43(){ _command auto; }; node_44(){ node_42(){ _command secret; }; node_43(){ _command auto; }; node_44(){
_command generate; }; node_45(){ _command insert; }; node_46(){ _command server _command generate; }; node_45(){ _command insert; }; node_46(){ _command server
}; node_47(){ _command add; }; node_48(){ _command use; }; node_49(){ }; node_47(){ _command add; }; node_48(){ _command init; }; node_49(){
_command init; }; node_50(){ _command upgrade; }; node_51(){ optional 0 1 2 3; } _command apps; }; node_50(){ _command upgrade; }; node_51(){ optional 0 1 2 3; }
node_52(){ optional 51; }; node_53(){ optional 4; }; node_54(){ optional 5; } node_52(){ optional 51; }; node_53(){ optional 4; }; node_54(){ optional 5; }
node_55(){ optional 6; }; node_56(){ optional 7; }; node_57(){ node_55(){ optional 6; }; node_56(){ optional 7; }; node_57(){
required 52 27 28 53 54 55 56 12; }; node_58(){ either 29 30; }; node_59(){ required 52 28 29 53 54 55 56 14; }; node_58(){ either 30 31; }; node_59(){
required 58; }; node_60(){ optional 8; }; node_61(){ required 52 27 59 60; } required 58; }; node_60(){ optional 8; }; node_61(){ required 52 28 59 60 53; }
node_62(){ required 52 27 13 31; }; node_63(){ required 52 27 13 32; } node_62(){ optional 9; }; node_63(){ required 52 28 15 32 62; }; node_64(){
node_64(){ required 52 27 13 33; }; node_65(){ either 34 35; }; node_66(){ required 52 28 15 33; }; node_65(){ required 52 28 15 34; }; node_66(){
required 65; }; node_67(){ optional 9; }; node_68(){ required 52 27 13 66 67; } either 35 36; }; node_67(){ required 66; }; node_68(){ optional 10; }
node_69(){ optional 14; }; node_70(){ required 52 27 13 36 69; }; node_71(){ node_69(){ required 52 28 15 67 68; }; node_70(){ optional 16; }; node_71(){
required 52 27 13 37; }; node_72(){ required 52 27 13 38 15 16; }; node_73(){ required 52 28 15 37 70; }; node_72(){ required 52 28 15 38 17 18; }; node_73(){
required 52 27 13 39; }; node_74(){ required 52 27 13 40; }; node_75(){ required 52 28 15 39; }; node_74(){ required 52 28 15 40; }; node_75(){
optional 10; }; node_76(){ oneormore 17; }; node_77(){ optional 11; }; node_76(){ optional 12; }; node_77(){ oneormore 19; }
required 52 27 13 41 75 14 76; }; node_78(){ required 52 27 13 41 14 76; } node_78(){ required 52 28 15 41 75 76 16 77; }; node_79(){
node_79(){ required 52 27 13 42 43 55; }; node_80(){ optional 20; }; node_81(){ required 52 28 15 41 16 77; }; node_80(){ required 52 28 15 42 43 55; }
required 52 27 13 42 44 18 19 80 55; }; node_82(){ node_81(){ optional 22; }; node_82(){ required 52 28 15 42 44 20 21 81 55; }
required 52 27 13 42 45 18 19 21 55; }; node_83(){ either 18 11; }; node_84(){ node_83(){ required 52 28 15 42 45 20 21 23 55; }; node_84(){ either 20 13; }
required 83; }; node_85(){ required 52 27 13 42 66 84 55 67; }; node_86(){ node_85(){ required 84; }; node_86(){ required 52 28 15 42 67 85 55 68; }
optional 23; }; node_87(){ required 52 27 13 22 86; }; node_88(){ optional 25; } node_87(){ optional 77; }; node_88(){ required 52 28 15 24 87; }; node_89(){
node_89(){ optional 26; }; node_90(){ required 52 46 47 24 88 89; }; node_91(){ optional 26; }; node_90(){ optional 27; }; node_91(){ required 52 46 47 25 89 90
required 52 46 59; }; node_92(){ required 52 46 35 24; }; node_93(){ }; node_92(){ required 52 46 59; }; node_93(){ required 52 46 25 36; }
required 52 46 48 24; }; node_94(){ required 52 46 49 24; }; node_95(){ node_94(){ required 52 46 25 48; }; node_95(){ required 52 46 25 49 60; }
required 52 50; }; node_96(){ node_96(){ required 52 50; }; node_97(){
either 57 61 62 63 64 68 70 71 72 73 74 77 78 79 81 82 85 87 90 91 92 93 94 95 either 57 61 63 64 65 69 71 72 73 74 78 79 80 82 83 86 88 91 92 93 94 95 96; }
}; node_97(){ required 96; }; cat <<<' docopt_exit() { node_98(){ required 97; }; cat <<<' docopt_exit() {
[[ -n $1 ]] && printf "%s\n" "$1" >&2; printf "%s\n" "${DOC:40:1189}" >&2 [[ -n $1 ]] && printf "%s\n" "$1" >&2; printf "%s\n" "${DOC:40:1212}" >&2
exit 1; }'; unset var___env var___version var___help var___stack var___server \ exit 1; }'; unset var___env var___help var___version var___stack var___server \
var___domain var___pass var___auto var___status var___force var___user \ var___domain var___pass var___auto var___status var___skip_check var___force \
var___all var__app_ var__domain_ var__service_ var__src_ var__dst_ var__args_ \ var___no_tty var___user var___all var__type_ var__domain_ var__service_ \
var__secret_ var__version_ var__cmd_ var__data_ var__command_ var__arg_ \ var__src_ var__dst_ var__args_ var__secret_ var__version_ var__cmd_ var__data_ \
var__host_ var__user_ var__port_ var_app var_new var_list var_ls var_deploy \ var__command_ var__host_ var__user_ var__port_ var_app var_new var_list var_ls \
var_undeploy var_config var_delete var_rm var_logs var_multilogs var_cp \ var_deploy var_undeploy var_config var_delete var_rm var_logs var_cp var_check \
var_check var_ps var_run var_secret var_auto var_generate var_insert \ var_ps var_run var_secret var_auto var_generate var_insert var_server var_add \
var_server var_add var_use var_init var_upgrade; parse 97 "$@" var_init var_apps var_upgrade; parse 98 "$@"; local prefix=${DOCOPT_PREFIX:-''}
local prefix=${DOCOPT_PREFIX:-''}; unset "${prefix}__env" "${prefix}__version" \ unset "${prefix}__env" "${prefix}__help" "${prefix}__version" \
"${prefix}__help" "${prefix}__stack" "${prefix}__server" "${prefix}__domain" \ "${prefix}__stack" "${prefix}__server" "${prefix}__domain" "${prefix}__pass" \
"${prefix}__pass" "${prefix}__auto" "${prefix}__status" "${prefix}__force" \ "${prefix}__auto" "${prefix}__status" "${prefix}__skip_check" \
"${prefix}__user" "${prefix}__all" "${prefix}_app_" "${prefix}_domain_" \ "${prefix}__force" "${prefix}__no_tty" "${prefix}__user" "${prefix}__all" \
"${prefix}_service_" "${prefix}_src_" "${prefix}_dst_" "${prefix}_args_" \ "${prefix}_type_" "${prefix}_domain_" "${prefix}_service_" "${prefix}_src_" \
"${prefix}_secret_" "${prefix}_version_" "${prefix}_cmd_" "${prefix}_data_" \ "${prefix}_dst_" "${prefix}_args_" "${prefix}_secret_" "${prefix}_version_" \
"${prefix}_command_" "${prefix}_arg_" "${prefix}_host_" "${prefix}_user_" \ "${prefix}_cmd_" "${prefix}_data_" "${prefix}_command_" "${prefix}_host_" \
"${prefix}_port_" "${prefix}app" "${prefix}new" "${prefix}list" "${prefix}ls" \ "${prefix}_user_" "${prefix}_port_" "${prefix}app" "${prefix}new" \
"${prefix}deploy" "${prefix}undeploy" "${prefix}config" "${prefix}delete" \ "${prefix}list" "${prefix}ls" "${prefix}deploy" "${prefix}undeploy" \
"${prefix}rm" "${prefix}logs" "${prefix}multilogs" "${prefix}cp" \ "${prefix}config" "${prefix}delete" "${prefix}rm" "${prefix}logs" \
"${prefix}check" "${prefix}ps" "${prefix}run" "${prefix}secret" \ "${prefix}cp" "${prefix}check" "${prefix}ps" "${prefix}run" "${prefix}secret" \
"${prefix}auto" "${prefix}generate" "${prefix}insert" "${prefix}server" \ "${prefix}auto" "${prefix}generate" "${prefix}insert" "${prefix}server" \
"${prefix}add" "${prefix}use" "${prefix}init" "${prefix}upgrade" "${prefix}add" "${prefix}init" "${prefix}apps" "${prefix}upgrade"
eval "${prefix}"'__env=${var___env:-}' eval "${prefix}"'__env=${var___env:-}'
eval "${prefix}"'__version=${var___version:-false}'
eval "${prefix}"'__help=${var___help:-false}' eval "${prefix}"'__help=${var___help:-false}'
eval "${prefix}"'__version=${var___version:-false}'
eval "${prefix}"'__stack=${var___stack:-}' eval "${prefix}"'__stack=${var___stack:-}'
eval "${prefix}"'__server=${var___server:-}' eval "${prefix}"'__server=${var___server:-}'
eval "${prefix}"'__domain=${var___domain:-}' eval "${prefix}"'__domain=${var___domain:-}'
eval "${prefix}"'__pass=${var___pass:-false}' eval "${prefix}"'__pass=${var___pass:-false}'
eval "${prefix}"'__auto=${var___auto:-false}' eval "${prefix}"'__auto=${var___auto:-false}'
eval "${prefix}"'__status=${var___status:-false}' eval "${prefix}"'__status=${var___status:-false}'
eval "${prefix}"'__skip_check=${var___skip_check:-false}'
eval "${prefix}"'__force=${var___force:-false}' eval "${prefix}"'__force=${var___force:-false}'
eval "${prefix}"'__no_tty=${var___no_tty:-false}'
eval "${prefix}"'__user=${var___user:-}' eval "${prefix}"'__user=${var___user:-}'
eval "${prefix}"'__all=${var___all:-false}' eval "${prefix}"'__all=${var___all:-false}'
eval "${prefix}"'_app_=${var__app_:-}' eval "${prefix}"'_type_=${var__type_:-}'
eval "${prefix}"'_domain_=${var__domain_:-}' eval "${prefix}"'_domain_=${var__domain_:-}'
eval "${prefix}"'_service_=${var__service_:-}' eval "${prefix}"'_service_=${var__service_:-}'
eval "${prefix}"'_src_=${var__src_:-}'; eval "${prefix}"'_dst_=${var__dst_:-}' eval "${prefix}"'_src_=${var__src_:-}'; eval "${prefix}"'_dst_=${var__dst_:-}'
@ -235,7 +237,7 @@ fi; eval "${prefix}"'_secret_=${var__secret_:-}'
eval "${prefix}"'_version_=${var__version_:-}' eval "${prefix}"'_version_=${var__version_:-}'
eval "${prefix}"'_cmd_=${var__cmd_:-}'; eval "${prefix}"'_data_=${var__data_:-}' eval "${prefix}"'_cmd_=${var__cmd_:-}'; eval "${prefix}"'_data_=${var__data_:-}'
eval "${prefix}"'_command_=${var__command_:-}' eval "${prefix}"'_command_=${var__command_:-}'
eval "${prefix}"'_arg_=${var__arg_:-}'; eval "${prefix}"'_host_=${var__host_:-}' eval "${prefix}"'_host_=${var__host_:-}'
eval "${prefix}"'_user_=${var__user_:-}' eval "${prefix}"'_user_=${var__user_:-}'
eval "${prefix}"'_port_=${var__port_:-}' eval "${prefix}"'_port_=${var__port_:-}'
eval "${prefix}"'app=${var_app:-false}'; eval "${prefix}"'new=${var_new:-false}' eval "${prefix}"'app=${var_app:-false}'; eval "${prefix}"'new=${var_new:-false}'
@ -245,7 +247,6 @@ eval "${prefix}"'undeploy=${var_undeploy:-false}'
eval "${prefix}"'config=${var_config:-false}' eval "${prefix}"'config=${var_config:-false}'
eval "${prefix}"'delete=${var_delete:-false}' eval "${prefix}"'delete=${var_delete:-false}'
eval "${prefix}"'rm=${var_rm:-false}'; eval "${prefix}"'logs=${var_logs:-false}' eval "${prefix}"'rm=${var_rm:-false}'; eval "${prefix}"'logs=${var_logs:-false}'
eval "${prefix}"'multilogs=${var_multilogs:-false}'
eval "${prefix}"'cp=${var_cp:-false}' eval "${prefix}"'cp=${var_cp:-false}'
eval "${prefix}"'check=${var_check:-false}' eval "${prefix}"'check=${var_check:-false}'
eval "${prefix}"'ps=${var_ps:-false}'; eval "${prefix}"'run=${var_run:-false}' eval "${prefix}"'ps=${var_ps:-false}'; eval "${prefix}"'run=${var_run:-false}'
@ -254,23 +255,24 @@ eval "${prefix}"'auto=${var_auto:-false}'
eval "${prefix}"'generate=${var_generate:-false}' eval "${prefix}"'generate=${var_generate:-false}'
eval "${prefix}"'insert=${var_insert:-false}' eval "${prefix}"'insert=${var_insert:-false}'
eval "${prefix}"'server=${var_server:-false}' eval "${prefix}"'server=${var_server:-false}'
eval "${prefix}"'add=${var_add:-false}'; eval "${prefix}"'use=${var_use:-false}' eval "${prefix}"'add=${var_add:-false}'
eval "${prefix}"'init=${var_init:-false}' eval "${prefix}"'init=${var_init:-false}'
eval "${prefix}"'apps=${var_apps:-false}'
eval "${prefix}"'upgrade=${var_upgrade:-false}'; local docopt_i=1 eval "${prefix}"'upgrade=${var_upgrade:-false}'; local docopt_i=1
[[ $BASH_VERSION =~ ^4.3 ]] && docopt_i=2; for ((;docopt_i>0;docopt_i--)); do [[ $BASH_VERSION =~ ^4.3 ]] && docopt_i=2; for ((;docopt_i>0;docopt_i--)); do
declare -p "${prefix}__env" "${prefix}__version" "${prefix}__help" \ declare -p "${prefix}__env" "${prefix}__help" "${prefix}__version" \
"${prefix}__stack" "${prefix}__server" "${prefix}__domain" "${prefix}__pass" \ "${prefix}__stack" "${prefix}__server" "${prefix}__domain" "${prefix}__pass" \
"${prefix}__auto" "${prefix}__status" "${prefix}__force" "${prefix}__user" \ "${prefix}__auto" "${prefix}__status" "${prefix}__skip_check" \
"${prefix}__all" "${prefix}_app_" "${prefix}_domain_" "${prefix}_service_" \ "${prefix}__force" "${prefix}__no_tty" "${prefix}__user" "${prefix}__all" \
"${prefix}_src_" "${prefix}_dst_" "${prefix}_args_" "${prefix}_secret_" \ "${prefix}_type_" "${prefix}_domain_" "${prefix}_service_" "${prefix}_src_" \
"${prefix}_version_" "${prefix}_cmd_" "${prefix}_data_" "${prefix}_command_" \ "${prefix}_dst_" "${prefix}_args_" "${prefix}_secret_" "${prefix}_version_" \
"${prefix}_arg_" "${prefix}_host_" "${prefix}_user_" "${prefix}_port_" \ "${prefix}_cmd_" "${prefix}_data_" "${prefix}_command_" "${prefix}_host_" \
"${prefix}app" "${prefix}new" "${prefix}list" "${prefix}ls" "${prefix}deploy" \ "${prefix}_user_" "${prefix}_port_" "${prefix}app" "${prefix}new" \
"${prefix}undeploy" "${prefix}config" "${prefix}delete" "${prefix}rm" \ "${prefix}list" "${prefix}ls" "${prefix}deploy" "${prefix}undeploy" \
"${prefix}logs" "${prefix}multilogs" "${prefix}cp" "${prefix}check" \ "${prefix}config" "${prefix}delete" "${prefix}rm" "${prefix}logs" \
"${prefix}ps" "${prefix}run" "${prefix}secret" "${prefix}auto" \ "${prefix}cp" "${prefix}check" "${prefix}ps" "${prefix}run" "${prefix}secret" \
"${prefix}generate" "${prefix}insert" "${prefix}server" "${prefix}add" \ "${prefix}auto" "${prefix}generate" "${prefix}insert" "${prefix}server" \
"${prefix}use" "${prefix}init" "${prefix}upgrade"; done; } "${prefix}add" "${prefix}init" "${prefix}apps" "${prefix}upgrade"; done; }
# docopt parser above, complete command for generating this parser is `docopt.sh abra` # docopt parser above, complete command for generating this parser is `docopt.sh abra`
PROGRAM_NAME=$(basename "$0") PROGRAM_NAME=$(basename "$0")
@ -291,7 +293,7 @@ warning() {
} }
success() { success() {
echo "$(tput setaf 2)$*$(tput sgr0)" echo "$(tput setaf 2)SUCCESS: $*$(tput sgr0)"
} }
###### Default settings ###### Default settings
@ -318,16 +320,19 @@ require_stack() {
fi fi
} }
require_app_clone() { require_app_latest() {
APP="$1" APP="$1"
APP_DIR="$ABRA_DIR/apps/$APP" APP_DIR="$ABRA_DIR/apps/$APP"
if [ ! -d "$APP_DIR" ]; then if [ ! -d "$APP_DIR" ]; then
warning "'$APP' not found, fetching via git.." warning "The app type '$APP' was not found, fetching via Git"
if ! git clone "$GIT_URL/$APP.git" "$ABRA_DIR/apps/$APP"; then if ! git clone "$GIT_URL/$APP.git" "$ABRA_DIR/apps/$APP" > /dev/null 2>&1 ; then
error "Could not retrieve '$APP', this app doesn't exist?" error "Could not retrieve app type '$APP', this app type doesn't exist?"
fi fi
success "Fetched app configuration via Git"
fi fi
cd "$APP_DIR" && git pull > /dev/null 2>&1
} }
# FIXME 3wc: update or remove # FIXME 3wc: update or remove
@ -346,8 +351,7 @@ load_custom_commands() {
if [ -n "$abra__domain_" ]; then if [ -n "$abra__domain_" ]; then
load_instance load_instance
load_instance_env load_instance_env
require_app_latest "$APP"
require_app_clone "$APP"
fi fi
if [ -f "$APP_DIR/abra-commands.sh" ]; then if [ -f "$APP_DIR/abra-commands.sh" ]; then
@ -448,6 +452,22 @@ parse_secret() {
sub_app_secret_generate sub_app_secret_generate
} }
stack_logs (){
# Note(decentral1se): see https://github.com/moby/moby/issues/31458#issuecomment-617871046
STACK="$1"
services=$(docker stack services "${STACK}" --format "{{.ID}}")
# shellcheck disable=SC2154
trap 'jobs=$(jobs -p) && test -n "$jobs" && kill $jobs' EXIT
for item in ${services//\\n/$'\n'}; do
docker service logs -f -t --tail 10 "$item" &
done
sleep infinity
}
####################################### #######################################
# abra app .. # abra app ..
####################################### #######################################
@ -458,19 +478,28 @@ sub_app_ls (){
} }
sub_app_list (){ sub_app_list (){
SERVER="$abra___server"
if [ -z "$SERVER" ]; then
SERVER='*'
fi
shopt -s nullglob dotglob shopt -s nullglob dotglob
# shellcheck disable=SC2206 # shellcheck disable=SC2206
ENV_FILES=($ABRA_DIR/servers/*/*.env) ENV_FILES=($ABRA_DIR/servers/$SERVER/*.env)
shopt -u nullglob dotglob shopt -u nullglob dotglob
STATUS="$( [[ $abra___status == "true" ]] && echo "Y" )" STATUS="$( [[ $abra___status == "true" ]] && echo "Y" )"
if [ -n "$STATUS" ]; then if [ -n "$STATUS" ]; then
if [ -z "$SERVER" ]; then
get_servers get_servers
else
SERVERS=( "$SERVER" )
fi
local -a DEPLOYED_APPS # array local -a DEPLOYED_APPS # array
warning "Loading status from ${#SERVERS[@]} servers, patience advised.." warning "Loading status from ${#SERVERS[@]} server(s), patience advised.."
for SERVER in "${SERVERS[@]}"; do for SERVER in "${SERVERS[@]}"; do
SERVER="${SERVER##*/}" # basename SERVER="${SERVER##*/}" # basename
@ -480,8 +509,6 @@ sub_app_list (){
done done
fi fi
printf '%s\n' "${DEPLOYED_APPS[@]}"
printf "%s lovely apps:\n\n" "${#ENV_FILES[@]}" printf "%s lovely apps:\n\n" "${#ENV_FILES[@]}"
for i in "${!ENV_FILES[@]}"; do for i in "${!ENV_FILES[@]}"; do
@ -502,7 +529,7 @@ sub_app_list (){
APP="$(source "$ENV_FILE" && echo "$APP")" APP="$(source "$ENV_FILE" && echo "$APP")"
# shellcheck disable=SC1090 # shellcheck disable=SC1090
APP_STACK_NAME="$(source "$ENV_FILE" && echo "$STACK_NAME")" APP_STACK_NAME="$(source "$ENV_FILE" && echo "$STACK_NAME")"
if [ -z "$STACK_NAME" ]; then if [ -z "$APP_STACK_NAME" ]; then
APP_STACK_NAME="${DOMAIN//./_}" APP_STACK_NAME="${DOMAIN//./_}"
fi fi
if [ -n "$STATUS" ]; then if [ -n "$STATUS" ]; then
@ -518,11 +545,15 @@ sub_app_new (){
require_abra_dir require_abra_dir
get_servers get_servers
APP=$abra__app_ # Note(decentral1se): we are overloading the use of the word "app" on this
# the interface and therefore try to use the word "type" to refer to "a type
# of app" vs. "an instance of an app"
APP=$abra__type_
SERVER=$abra___server SERVER=$abra___server
DOMAIN=$abra___domain DOMAIN=$abra___domain
require_app_clone "$APP" require_app_latest "$APP"
if [ -z "$SERVER" ]; then if [ -z "$SERVER" ]; then
echo "Where would you like to put $APP?" echo "Where would you like to put $APP?"
@ -578,7 +609,11 @@ sub_app_deploy (){
load_instance load_instance
load_instance_env load_instance_env
require_app_clone "$APP" require_app_latest "$APP"
if [ "$abra___skip_check" == "false" ]; then
sub_app_check
fi
echo "About to deploy:" echo "About to deploy:"
echo " Server: $(tput setaf 4)${SERVER}$(tput sgr0)" echo " Server: $(tput setaf 4)${SERVER}$(tput sgr0)"
@ -600,7 +635,6 @@ sub_app_deploy (){
prompt_confirm prompt_confirm
APP=$(basename "$APP_DIR") APP=$(basename "$APP_DIR")
require_app_clone "$APP"
( (
cd "$APP_DIR" || error "\$APP_DIR '$APP_DIR' not found" cd "$APP_DIR" || error "\$APP_DIR '$APP_DIR' not found"
@ -640,15 +674,17 @@ sub_app_check (){
load_instance load_instance
load_instance_env load_instance_env
APP_ENV=$(grep -v '^#' "$ENV_FILE" | sed 's/^.* \([^=]\+\)=.*/\1/' | sort) #APP_ENV=$(grep -v '^#' "$ENV_FILE" | sed 's/^.* \([^=]\+\)=.*/\1/' | sort)
STACK_ENV=$(grep -v '^#' "$APP_DIR/.envrc.sample" | sed 's/^.* \([^=]\+\)=.*/\1/' | sort) APP_ENV=$(grep -v '^#' "$ENV_FILE" | cut -d' ' -f2 | cut -d'=' -f1 | sort)
#STACK_ENV=$(grep -v '^#' "$APP_DIR/.envrc.sample" | sed 's/^.* \([^=]\+\)=.*/\1/' | sort)
STACK_ENV=$(grep -v '^#' "$APP_DIR/.envrc.sample" | cut -d' ' -f2 | cut -d'=' -f1 | sort)
# Only show "1", items in STACK_ENV which aren't in APP_ENV # Only show "1", items in STACK_ENV which aren't in APP_ENV
MISSING_VARS=$(comm -23 <(echo "$STACK_ENV") <(echo "$APP_ENV")) MISSING_VARS=$(comm -23 <(echo "$STACK_ENV") <(echo "$APP_ENV"))
if [ -z "$MISSING_VARS" ]; then if [ -z "$MISSING_VARS" ]; then
success "Yay! All the necessary basic variables are defined" success "Yay! All the necessary basic variables are defined"
exit 0 return 0
fi fi
error "Found missing variables: $MISSING_VARS" error "Found missing variables: $MISSING_VARS"
@ -790,6 +826,12 @@ sub_app_run(){
RUN_USER="-u $abra___user" RUN_USER="-u $abra___user"
fi fi
if [ "$abra___no_tty" = "true" ]; then
ARGS="-i"
else
ARGS="-it"
fi
CONTAINER=$(docker container ls --format "table {{.ID}},{{.Names}}" \ CONTAINER=$(docker container ls --format "table {{.ID}},{{.Names}}" \
| grep "${STACK_NAME}_${abra__service_}" | head -n1 | cut -d',' -f1) | grep "${STACK_NAME}_${abra__service_}" | head -n1 | cut -d',' -f1)
@ -801,32 +843,11 @@ sub_app_run(){
# 3wc: we want the "splitting" that shellcheck warns us about, so that -u and # 3wc: we want the "splitting" that shellcheck warns us about, so that -u and
# $RUN_USER aren't treated as a single argument: # $RUN_USER aren't treated as a single argument:
# shellcheck disable=SC2086 # shellcheck disable=SC2086
docker exec $RUN_USER -it "$CONTAINER" "$@" docker exec $RUN_USER $ARGS "$CONTAINER" "$@"
return return
} }
###### .. app <domain> multilogs
sub_app_multilogs() {
# Inspired by https://github.com/moby/moby/issues/31458#issuecomment-475411564
require_multitail
load_instance
load_instance_env
# Get a list of the service names
SERVICES=$(docker stack services --format "{{.Name}}" "${STACK_NAME}")
# Sort the service names
SERVICES=$(echo "${SERVICES}" | sort)
# Create the command to run
COMMAND='multitail --mergeall'
for SERVICE in ${SERVICES}; do
COMMAND="${COMMAND} -L 'docker service logs --tail 20 -f ${SERVICE}'"
done
# Run the command
bash -c "${COMMAND}"
}
###### .. app <domain> logs <service> <args>... ###### .. app <domain> logs <service> <args>...
sub_app_logs (){ sub_app_logs (){
load_instance load_instance
@ -835,8 +856,8 @@ sub_app_logs (){
SERVICE="${abra__service_}" SERVICE="${abra__service_}"
if [ -z "$SERVICE" ]; then if [ -z "$SERVICE" ]; then
warning "No \$SERVICE provided, running multilogs" stack_logs "${STACK_NAME}"
sub_app_multilogs return
fi fi
shift shift
@ -950,9 +971,10 @@ sub_server_delete() {
docker context rm "$abra__host_" docker context rm "$abra__host_"
} }
###### .. server <host> use ###### .. server <host> apps
sub_server_use() { sub_server_apps() {
docker context use "$abra__host_" abra___server="$abra__host_"
sub_app_list
} }
####################################### #######################################
@ -964,18 +986,24 @@ sub_upgrade() {
curl https://install.abra.autonomic.zone | bash curl https://install.abra.autonomic.zone | bash
} }
###### .. volume <args>... ###### .. stack <args>...
sub_stack() { sub_stack() {
# shellcheck disable=SC2068 # shellcheck disable=SC2068
docker stack $@ docker stack $@
} }
###### .. stack <args>... ###### .. volume <args>...
sub_volume() { sub_volume() {
# shellcheck disable=SC2068 # shellcheck disable=SC2068
docker volume $@ docker volume $@
} }
###### .. network <args>...
sub_network() {
# shellcheck disable=SC2068
docker network $@
}
####################################### #######################################
# Main # Main
####################################### #######################################
@ -985,9 +1013,9 @@ abra() {
# the place to handle the dynamically-defined vars # the place to handle the dynamically-defined vars
declare abra___stack abra___env abra__command_ abra__args_ \ declare abra___stack abra___env abra__command_ abra__args_ \
abra__secret_ abra__version_ abra__data_ abra___user abra__host_ \ abra__secret_ abra__version_ abra__data_ abra___user abra__host_ \
abra__app_ abra__port_ abra__user_ abra__service_ abra__src_ abra__dst_ \ abra__type_ abra__port_ abra__user_ abra__service_ abra__src_ abra__dst_ \
abra__domain_ abra___server abra___domain abra___force abra___pass \ abra__domain_ abra___server abra___domain abra___force abra___pass \
abra___auto abra___status abra___auto abra___status abra___no_tty abra___skip_check
if ! type tput > /dev/null 2>&1; then if ! type tput > /dev/null 2>&1; then
tput() { tput() {

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
ABRA_VERSION="0.3.1" ABRA_VERSION="0.4.1"
ABRA_SRC="https://git.autonomic.zone/coop-cloud/abra/raw/tag/$ABRA_VERSION/abra" ABRA_SRC="https://git.autonomic.zone/coop-cloud/abra/raw/tag/$ABRA_VERSION/abra"
function install_abra { function install_abra {

View File

@ -1,37 +1,37 @@
#!/usr/bin/env bats #!/usr/bin/env bats
setup() { setup() {
mkdir -p ~/.abra/servers/default export ABRA_DIR=$(mktemp -d)
mkdir -p $ABRA_DIR/servers/default
} }
teardown() { teardown() {
rm -rf ~/.abra/servers/default rm -rf "$ABRA_DIR"
rm -rf ~/.abra/servers/swarm.test.com
} }
@test "abra server add/rm works" { @test "abra server add/rm works" {
./abra server add swarm.test.com ./abra server add swarm.test.com
docker context ls | grep swarm.test.com docker context ls | grep swarm.test.com
[ -d ~/.abra/servers/swarm.test.com ] [ -d $ABRA_DIR/servers/swarm.test.com ]
./abra server rm swarm.test.com ./abra server swarm.test.com rm
./abra server add swarm.test.com foobar 12345 ./abra server add swarm.test.com foobar 12345
[ -d ~/.abra/servers/swarm.test.com ] [ -d $ABRA_DIR/servers/swarm.test.com ]
./abra server rm swarm.test.com ./abra server swarm.test.com rm
} }
@test "abra app new/rm works" { @test "abra app new/rm works" {
./abra app new --server default --domain traefik.test.com traefik ./abra app new --server default --domain traefik.test.com traefik
[ -f ~/.abra/servers/default/traefik.test.com.env ] [ -f $ABRA_DIR/servers/default/traefik.test.com.env ]
# interactive prompt # interactive prompt
echo "y" | ./abra app traefik.test.com delete echo "y" | ./abra app traefik.test.com delete
[ ! -f ~/.abra/servers/default/traefik.test.com.env ] [ ! -f $ABRA_DIR/servers/default/traefik.test.com.env ]
# --force # --force
./abra app new --server default --domain traefik.test.com traefik ./abra app new --server default --domain traefik.test.com traefik
./abra app traefik.test.com delete --force ./abra app traefik.test.com delete --force
[ ! -f ~/.abra/servers/default/traefik.test.com.env ] [ ! -f $ABRA_DIR/servers/default/traefik.test.com.env ]
} }
@test "abra app <domain> secret (insert|generate|rm)" { @test "abra app <domain> secret (insert|generate|rm)" {