gc swiss army knife roundup =========================== # maart 2021: cli brainstorm v1 https://hackmd.io/HlsWcOpoRLyx-mtIcLu1PQ # leon: nodejs cli mockup v1 lightweight, spec-based, multi-command nodejs: ``` $ cat src/cmd/helloworld.js module.exports = (gctl) => { gctl.helloworld = async (opts) => { console.log("helloworld! "+opts.value) opts.greetings = opts.greetings || [] opts.greetings.push( new Date() ) // advanced: (recursively) call or chain (other) cmds (SUPER commands e.g.) if( String(opts.value).match(/recursive/) ) return await gctl.dry({value:123}) // call other cmd directly gctl.execute({ // call other subcmd _order:[ {key:"helloworld", value:"recursive1"}, {key:"helloworld", value:"recursive2"} ] }) } gctl.cmds.push({ // automatic help generation names: ['helloworld', 'hw'], type: 'string', help: 'simple example cmd', //helpArg: 'HELLOWORLD' }) $ ./gctl usage: ./gctl [OPTIONS] options: -c ARG, --collections=ARG commaseparated, or use * to select all collections. --ns=ARG, --nostate=ARG exclude _state$ or runtime collections (--project enforces this). --dry=ARG dry run (dont execute anything). -e ARG, --exec=ARG execute cmd on selected host. --hw=ARG, --helloworld=ARG simple example cmd. -h ARG, --host=ARG select a host: gcaldi, gcv1, gcv2. -v, --verbose Verbose output. Use multiple times for more verbose. ``` # joost: spec mockup v1.1 https://hackmd.io/Wv7ZaxgbTl6lFit74SsUNA > lange termijn: remote controllable stack dmv. websocketd # leon: bash cli mockup v1.1 [Deze bash](https://gitlab.com/groundcontrol-app/gctl/-/blob/master/gc) versie is geinspireerd op laatste spec, met als verschil: * selectors (`gc:live` e.g.) vs actions (`db`) * multi-actions voor zowel bash EN nodejs * server/monitoring tools (`stack_init` om te installeren) ``` $ gc usage: ./gc <cmd> [cmd] ... CMDS: stack_init install tcptrack && ss (tiny) monitor utils servers loadavg view server load (selectors: server) sockets get sockets statistics tcptrack realtime monitor server connections db copy database (selectors: from, to) SELECTORS: server=uri gc:<stack>/<env>, mongodb:<uri>, gc:int, gc:acc, or gc:live from=uri gc:<stack>/<env>, mongodb:<uri>, gc:int, gc:acc, or gc:live to=uri gc:<stack>/<env>, mongodb:<uri>, gc:int, gc:acc, or gc:live SERVERS: - gc:local - gc:int - gc:live - gc:aldi - gc:v1 examples: ./gc server=gc:aldi loadavg server=gc:v2 loadavg ./gc from=gc:aldi to=gc:local db ``` > NOTE: dit startpunt heeft mn voorkeur met evt. nodejs subcommando's voor mongodb plumbing. # leon: bash cli v1.2 Proberen: ``` intikken in je browser en opslaan: https://gitlab.com/groundcontrol-app/gctl/-/raw/master/bash/gc $ chmod 755 gc $ ./gc usage: ./gc <cmd> [cmd] ... examples: ./gc int_to_acc src_sync ./gc acc_to_live src_sync ./gc server=gc:aldi loadavg server=gc:live loadavg CMDS: src_sync rsync stack-environment (selectors: from, to) alias <name> <cmd ...> create alias for oneliners (edit ~/.gc for multiliners) install_stack ubuntu: install docker + nginx-proxy-manager + acc/live env's scale <up|down> docker: scale api/sender between 1/1 or 7/4 (using docker-compose) db_sync copy database (selectors: from, to, db_strategy, collections) db_collections_list list mongo collection (selectors: PORT_LOCAL) db_dump list mongo collection (selectors: LOCAL_PORT) install_utils install tcptrack && ss (tiny) monitor utils loadavg print server load (selectors: server) sockets print sockets statistics tcptrack realtime monitor server connections ping ping all related URLS of selected server servers list all servers (from ~/.ssh/config) sshtunnel open sshtunnel (selectors: server, port_local, port_remote) ALIASES: stored in /home/leon/.gc health foo SELECTORS: server=uri gc:<stack>/<env>, mongodb:<uri>, gc:int, gc:acc, or gc:live from=uri gc:<stack>/<env>, mongodb:<uri>, gc:int, gc:acc, or gc:live to=uri gc:<stack>/<env>, mongodb:<uri>, gc:int, gc:acc, or gc:live int_to_acc alias for: from=gc:int to=gc:local/acc acc_to_live alias for: from=gc:local/acc to=gc:/local/live interactive interactive=1 (default), use interactive=0 for scripts port_local=<port> port for sshtunnel/database use port_remote=<port> port for sshtunnel/database use user <username> username to use with sshtunnel/database db_strategy=<strategy> database sync strategy ("merge" or "drop_and_import") collections=<foo bar> select mongo collections (space-separated, * = all) SERVERS: <env> can be: acc, live, int - gc:local - gc:int - gc:live - gc:aldi - gc:v1 ``` De `./gc int_to_acc src_sync` werkt al (equivalent van ./sync), source is [hier](https://gitlab.com/groundcontrol-app/gctl/-/blob/master/bash/cmd/sync) ## Stack-like execution Dit was nodig aangezien de spec (https://hackmd.io/Wv7ZaxgbTl6lFit74SsUNA) een beetje dubbelzinnig werd kwa herbruikbare cmds. makkelijker format: `./gc <selector> <cmd> [...]` e.g. ``` $ ./gc server=gc:aldi loadavg server=gc:live loadavg [gcaldi] [loadavg] [gcaldi] 0.16 0.09 0.08 2/1324 16022 diskspace: 34% MemFree: 4188200 kB [gclive] 0.14 0.10 0.09 1/1265 4181798 diskspace: 17% MemFree: 1322396 kB ``` Dit kan je lezen als: `loadavg(server) ; loadavg(server)`. Heel simpel, gewoon global vars en functies. ## Alias gooi gewoon dit in `~/.gc`: ``` pingall(){ _gc server=gc:aldi ping server=gc:live ping } ``` > en dan kan je gewoon runnen: ``` $ ./gc pingall [gcaldi] [ping] [gcaldi] [ONLINE] mission.aldi.groundcontrol.app/login [gcaldi] [ONLINE] api.aldi.groundcontrol.app [gcaldi] [ONLINE] mission.acc.aldi.groundcontrol.app/login [gcaldi] [ONLINE] api.acc.aldi.groundcontrol.app [gclive] [ONLINE] mission.groundcontrol.app/login [gclive] [ONLINE] api.groundcontrol.app [gclive] [ONLINE] mission.acc.groundcontrol.app/login [gclive] [ONLINE] api.acc.groundcontrol.app ``` > `./gc alias foo bar` subcommando werkt half, en moet nog ff de stackbased parser disablen (die voert `foo bar` ook uit haha). ## prompt missing selectors/args missende selectors word zo in een commando opgevangen: ``` sshtunnel(){ _ensure_selector PORT_LOCAL _ensure_selector PORT_REMOTE ... ``` demo: ``` $ ./gc server=gc:int sshtunnel loadavg [gcint] [sshtunnel] [missing selector: port_local] enter value: 8888 [missing selector: port_remote] enter value: 27017 [gcint] closing (previous) sshtunnels.. [gcint] 17780 [gcint] $ ssh groundcontrol@gcint -fN -L 8888:127.0.0.1:27017 [gcint] opened tunnel gcint:27017 <---> gc:local:8888 [gcint] [loadavg] [gcint] 0.16 0.10 0.03 1/507 1273785 diskspace: 17% MemFree: 303160 kB ``` hieronder sshtunnel zie je de selectors WEL opgegeven via de cmdline (dus hij prompt niet) ## SSH tunnel / Mongodump Hiermee ben ik een eind gekomen, en dat werkt 'sortof': ``` $ ./gc server=gc:int port_local=8888 port_remote=27017 sshtunnel loadavg [gcint] [sshtunnel] [gcint] closing (previous) sshtunnels.. [gcint] 17507 [gcint] 17547 [gcint] $ ssh groundcontrol@gcint -fN -L 8888:127.0.0.1:27017 [gcint] opened tunnel gcint:27017 <---> gc:local:8888 [gcint] [loadavg] [gcint] 0.15 0.10 0.03 1/504 1273687 diskspace: 17% MemFree: 306092 kB ``` Het finetunen wil ik doen a.d.v. de docker-in-docker / next step: ## Next step: highlevel 'sync' commando prototypen dmv. bestaande sub commandos Wellicht gewoon 'sensen' adv. current directory? (`$ pwd`) : ``` $ cd acc $ ./gc sync $ cd - $ cd live $ ./gc sync ``` een dergelijk highlevel multi-server 'story' kunnen we nu makkelijker prototypen: ``` sync(){ docker-compose down _str_match $(pwd) "acc" && _gc from:gc:int to=gc:local/acc src_sync db_sync _str_match $(pwd) "live" && _gc from=gc:local/acc to=gc:local/live src_sync db_sync docker-compose up -d } ``` > de `db_sync` verschilt per case, die we a.d.v. selectors `db_strategy=merge` en `collections=*,-state` e.g. kunnen finetunen. Ook kunnen we evt. aliases maken voor de `collections`-selector (voor `db_sync`): * collections=runtime --> `collections=messages,answers,*_states,*_logs` * collections=runtime,users --> `collections=messages,answers,*_states,*_logs,users` ## call 04-11-2021 ``` 4:35 <LeonvanKammen> Joost Lubach 14:35 <LeonvanKammen> 2:34 PM 14:35 <LeonvanKammen> gc sync gc:local gc:acc 14:35 <LeonvanKammen> gc sync . gc:groundcontrol/acc 14:35 <LeonvanKammen> gc sync /Users/joost/Work/groundcontrol gc:groundcontrol/acc 14:35 <LeonvanKammen> Joost Lubach 14:35 <LeonvanKammen> 2:35 PM 14:35 <LeonvanKammen> gc:groundcontrol/live ==> gc:live 14:36 <LeonvanKammen> gc:htg/acc 14:37 <LeonvanKammen> gc:htg/live 14:52 <JoostLubach> `./gc dosomething arg1 arg2` 14:53 <JoostLubach> `./gc server=htg something arg1 arg2` 14:54 <JoostLubach> `./gc server=local something arg1 arg2 server=htg something arg3 arg4` 14:54 <JoostLubach> `./gc server=htg arg2 arg1 something` 14:55 <LeonvanKammen> FOO=1 BAR=1 ./doiets 14:55 <LeonvanKammen> ./gc foo=1 bar=2 doiets foo=2 bar=4 doiets 14:56 <JoostLubach> `./gc sync int_to_acc` (edited) 14:57 <JoostLubach> `./gc` executable 14:57 <> `sync` command 14:57 <> `int_to_acc` argument 14:57 <JoostLubach> `./gc VAR=1 sync int_to_acc` 14:58 <JoostLubach> `./gc`: executable 14:58 <JoostLubach> `VAR=1` env variable 14:58 <JoostLubach> `sync` command 14:58 <JoostLubach> `int_to_acc` argument 15:00 <JoostLubach> `./gc sync int_to_acc` 15:01 <JoostLubach> `./gc sync int_to_acc --stack htg --app mission` (edited) 15:02 <JoostLubach> `fastlane beta arg1 arg2 platform:android` (edited) 15:02 <JoostLubach> `./gc sync int_to_acc --stack htg --app mission` 15:03 <JoostLubach> `Usage: ./gc <command> [--stack=<stack>]` (edited) 15:03 <LeonvanKammen> `./gc sync int_to_acc --stack htg --stack foo --app mission` 15:03 <LeonvanKammen> `./gc ping` 15:03 <LeonvanKammen> `./gc ping --stack htg --stack foo` 15:04 <LeonvanKammen> `./gc sync gc:local gc:live/acc` 15:06 <LeonvanKammen> `./gc push int_to_acc` 15:06 <JoostLubach> `./gc deploy int_to_acc` 15:07 <LeonvanKammen> `./gc pull --stack htg` 15:07 <LeonvanKammen> ^-- boeiend 15:23 <JoostLubach> `./gc hotfix ENV` -> alle stacks, alle apps 15:23 <JoostLubach> `./gc hotfix acc` 15:23 <JoostLubach> `./gc hotfix live` 15:23 <JoostLubach> `./gc hotfix acc --stack=gc --app=mission` 15:24 <JoostLubach> `./gc hotfix live --stack=htg --stack=obm --app=web --app=mission` 15:25 <JoostLubach> `./gc sync int2acc` 15:25 <JoostLubach> `./gc sync acc2live` 15:25 <LeonvanKammen> 2 ipv _to_ ```