forked from ISPsystem/isp-maintenance
		
	Compare commits
	
		
			26 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e87c1679e4 | |||
| 6bbebd5a7a | |||
| 99dd122262 | |||
| b84ef86cd0 | |||
| ba6dd53f6c | |||
| 5815c84b07 | |||
| 6c6df42e7f | |||
| da3e61eccb | |||
| e0de805af7 | |||
| 4cdf3b4539 | |||
| d4de07c340 | |||
| dc6e61dcbe | |||
| f773898b71 | |||
| cdf3a92527 | |||
| 8ad5e2a230 | |||
| 5405679640 | |||
| 72bfeb9193 | |||
| bb3b20e6c8 | |||
| 287216d975 | |||
| 0f96d0f956 | |||
| 34e8118327 | |||
| 45f9204c6c | |||
| 1d72b8d015 | |||
| f9a213fe3e | |||
| 867cd1c022 | |||
| 2bc9b2e94f | 
							
								
								
									
										5
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| docker-compose.yml | ||||
| .gitignore | ||||
| .env | ||||
| .git | ||||
| .cache | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -158,7 +158,9 @@ cython_debug/ | ||||
| #  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore | ||||
| #  and can be added to the global gitignore or merged into this file.  For a more nuclear | ||||
| #  option (not recommended) you can uncomment the following to ignore the entire idea folder. | ||||
| #.idea/ | ||||
| .idea/ | ||||
| .vscode/ | ||||
| 
 | ||||
| # Project specific | ||||
| config.json | ||||
| **/dummy_platform | ||||
|  | ||||
							
								
								
									
										21
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| # Changelog | ||||
| 
 | ||||
| ## [0.1.0] - 2024-06-09 | ||||
| ### Added | ||||
| - mgrctl core mvp | ||||
| - auth apps for vm6/dci6 | ||||
| 
 | ||||
| 
 | ||||
| ## [0.1.1] - 2025-05-07 | ||||
| ### Updated | ||||
| - dependencies | ||||
| - docker hub latest image | ||||
| 
 | ||||
| ### Fixed | ||||
| - dci input container name | ||||
| 
 | ||||
| ### Changed | ||||
| - remove peewee deps | ||||
| - remove data base management | ||||
| - remove mysql container for dev env | ||||
| - remove \__version__ from sub app | ||||
							
								
								
									
										59
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| # app/Dockerfile | ||||
| 
 | ||||
| # pull the official docker image | ||||
| FROM python:3.12-alpine AS poetry-base | ||||
| 
 | ||||
| # default build args | ||||
| ARG APP_VERSION=0.1.1 \ | ||||
|     APP_DIR=/app \ | ||||
|     SRC_DIR=./mgrctl \ | ||||
|     PKG_NAME=mgrctl \ | ||||
|     PKG_VERSION=0.1.1 | ||||
| 
 | ||||
| # set env variables | ||||
| ENV APP_NAME=mgrctl \ | ||||
|     # Python3: | ||||
|     PYTHONFAULTHANDLER=1 \ | ||||
|     PYTHONUNBUFFERED=1 \ | ||||
|     PYTHONHASHSEED=random \ | ||||
|     # Pip: | ||||
|     PIP_NO_CACHE_DIR=on \ | ||||
|     PIP_DISABLE_PIP_VERSION_CHECK=on \ | ||||
|     PIP_ROOT_USER_ACTION=ignore \ | ||||
|     PIP_DEFAULT_TIMEOUT=100 \ | ||||
|     # Poetry: | ||||
|     POETRY_NO_INTERACTION=1 \ | ||||
|     POETRY_VIRTUALENVS_CREATE=false \ | ||||
|     POETRY_CACHE_DIR='/var/cache/pypoetry' \ | ||||
|     POETRY_HOME='/usr/local' \ | ||||
|     POETRY_VERSION=2.1.2 | ||||
| 
 | ||||
| # install system deps | ||||
| RUN apk --no-cache add curl \ | ||||
|     && curl -sSL https://install.python-poetry.org | python3 - \ | ||||
|     && mkdir ${APP_DIR} | ||||
| 
 | ||||
| COPY ./pyproject.toml ./poetry.lock ./README.md ${APP_DIR} | ||||
| COPY ${SRC_DIR} ${APP_DIR}/${PKG_NAME} | ||||
| 
 | ||||
| # set workdir | ||||
| WORKDIR ${APP_DIR} | ||||
| 
 | ||||
| # build pkg whl | ||||
| RUN poetry build --format wheel \ | ||||
|     && pip install ${APP_DIR}/dist/${PKG_NAME}-${PKG_VERSION}-py3-none-any.whl \ | ||||
|     && rm -r /usr/local/venv | ||||
| 
 | ||||
| # now multistage builds | ||||
| FROM python:3.12-alpine | ||||
| 
 | ||||
| # copy app and dependencies | ||||
| COPY --from=poetry-base /usr/local/ /usr/local/ | ||||
| 
 | ||||
| # install bash and mgrctl shell completion | ||||
| RUN apk --no-cache add bash \ | ||||
|     && echo 'eval "$(_MGRCTL_COMPLETE=bash_source mgrctl)"' > ~/.bashrc | ||||
| 
 | ||||
| # "demonize" container | ||||
| # use docker attach mgrctl or docker exec -it mgrctl mgrctl --help for example | ||||
| CMD [ "bash"] | ||||
							
								
								
									
										13
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| build: | ||||
| 	python3 ./scripts/devtools/dev.py builder docker-compose build | ||||
| destroy: | ||||
| 	python3 ./scripts/devtools/dev.py builder docker-compose destroy | ||||
| up: | ||||
| 	python3 ./scripts/devtools/dev.py runner docker-compose up | ||||
| down: | ||||
| 	python3 ./scripts/devtools/dev.py runner docker-compose down | ||||
| restart: | ||||
| 	python3 ./scripts/devtools/dev.py runner docker-compose restart | ||||
| setup: build up | ||||
| 
 | ||||
| .PHONY: exec setup build | ||||
							
								
								
									
										174
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										174
									
								
								README.md
									
									
									
									
									
								
							| @ -5,4 +5,176 @@ Maintenance application for quick access, check and resolve issues VM/DCImanager | ||||
| ### In progress | ||||
| 
 | ||||
| 
 | ||||
| ### See [CONTRIBUTING.md](CONTRIBUTING.md) for a general overview of how to contribute  | ||||
| ### See [CONTRIBUTING.md](CONTRIBUTING.md) for a general overview of how to contribute | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## How to use gogo companion: | ||||
| 
 | ||||
| 
 | ||||
| #### Dependencies | ||||
| 
 | ||||
| ОС: Linux, Mac, Windows | ||||
| Shell: bash | ||||
| 
 | ||||
| 
 | ||||
| #### Installation | ||||
| 
 | ||||
| - download or copy the script from the root of the repository `/scripts/gogo/gogo.sh` | ||||
| - to call the script without specifying the full path, put it in the directory that is in $PATH (in the future, I assume that you will have it `~/.local/bin/`) | ||||
| 
 | ||||
| ```console | ||||
| curl https://git.isptech.ru/ISPsystem/isp-maintenance/raw/branch/main/scripts/gogo/gogo.sh -o ~/.local/bin/gogo && chmod u+x ~/.local/bin/gogo | ||||
| ``` | ||||
| 
 | ||||
| #### Configuration | ||||
| 
 | ||||
| For the script to work, you need a configuration file with settings `~/.config/gogo/gogo.conf` | ||||
| 
 | ||||
| This config contains the following fields that are read every time you start | ||||
| 
 | ||||
| ``` | ||||
| GO_SERVER_ADDR_RUSSIAN= | ||||
| GO_SERVER_ADDR_GERMANY= | ||||
| GO_SERVER_ADDR_TEST= | ||||
| VAULT_SERVER_ADDR= | ||||
| SSH_PRIVATE_KEY_USER= | ||||
| SSH_PRIVATE_KEY_PATH= | ||||
| SSH_PUBLIC_KEY_PATH= | ||||
| SSH_CRT_FILE= | ||||
| MGRCTL_IMAGE=mois3y/mgrctl:latest | ||||
| DEBUG_MODE=false | ||||
| ``` | ||||
| 
 | ||||
| Please fill in the fields with current data, write the path to the keys and certificate in full `/home/username/.ssh/id_ecdsa` and so on. | ||||
| For security reasons, server addresses and paths to keys are not indicated here. | ||||
| 
 | ||||
| For your convenience, the config can be filled out interactively | ||||
| 
 | ||||
| ```console | ||||
| gogo --init | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| #### Usage | ||||
| 
 | ||||
| - Get a temporary ssh certificate | ||||
| 
 | ||||
| ```console | ||||
| gogo --crt | ||||
| ``` | ||||
| 
 | ||||
| - Check your connection to test servers in both locations | ||||
| 
 | ||||
| ```console | ||||
| gogo --test | ||||
| ``` | ||||
| 
 | ||||
| - If the connection is successful, you can use the script. You are beautiful! | ||||
| 
 | ||||
| 
 | ||||
| #### Examples | ||||
| 
 | ||||
| - Connect to BILLmanager 6 via ssh port 22 and interface port 443 | ||||
| 
 | ||||
| ```console | ||||
| gogo --bill my.example.com | ||||
| ``` | ||||
| or | ||||
| ```console | ||||
| gogo --bill my.example.com -p 22 -wp 443 | ||||
| ``` | ||||
| 
 | ||||
| - Connect to BILLmanager 6 again without generating an access key to the interface | ||||
| 
 | ||||
| ```console | ||||
| gogo --bill my.example.com --ssh | ||||
| ``` | ||||
| 
 | ||||
| - Connect to DNSmanager 6 via ssh port 22 and interface port 1501 | ||||
| 
 | ||||
| ```console | ||||
| gogo --dns my.example.com -p 22 -wp 1501 | ||||
| ``` | ||||
| 
 | ||||
| - Connect to DCImanager 6 via ssh port 2222 and interface 443 port | ||||
| 
 | ||||
| ```console | ||||
| gogo --dci vm.example.com -p 2222 | ||||
| ``` | ||||
| 
 | ||||
| - Connect to VMmanager 6 via ssh port 2222 and interface port 443 | ||||
| 
 | ||||
| ```console | ||||
| gogo --vm 228.228.228.228 -p 2222 | ||||
| ``` | ||||
| 
 | ||||
| - Connect to VMmanager 6 via ssh port 22 and interface port 443, indicating the id of a specific user and generate 3 keys | ||||
| 
 | ||||
| ```console | ||||
| gogo --vm vm.example.com --mgrctl auth user access --id 1488 --count 1 | ||||
| ``` | ||||
| 
 | ||||
| - The same thing, just print the command that is executed on the server side into the console, you can run it later simply by copying it | ||||
| 
 | ||||
| ```console | ||||
| gogo --vm vm.example.com --tty --mgrctl auth user access --id 1488 --count 1 | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| Connect to VMmanager 6 via ssh port 22 and interface port 443 via DE go3 server | ||||
| 
 | ||||
| ```console | ||||
| gogo --vm vm.example.com -p 22 --de | ||||
| ``` | ||||
| 
 | ||||
| Connect to DCImanager 6 via ssh port 22 and interface port 443 via the old go method | ||||
| 
 | ||||
| ```console | ||||
| gogo --dci dci.example.com -p 22 --go | ||||
| ``` | ||||
| 
 | ||||
| ##### There are also examples in `help` | ||||
| 
 | ||||
| ```console | ||||
| gogo --help | ||||
| 
 | ||||
| Usage: gogo [options [parameters]] | ||||
| 
 | ||||
| Examples: | ||||
| 
 | ||||
| gogo --init | init config file | ||||
| gogo --crt  | get ssh certificate for go3 connections | ||||
| gogo --test | check go3 connection availability | ||||
| 
 | ||||
| gogo --bill my.example.com | ||||
| gogo --vm my.example.com --de  | connect throw DE go3 server | ||||
| gogo --vm 0.0.0.0 --ssh | only ssh access | ||||
| gogo --vm 0.0.0.0 --tty | use mgrctl interactive | ||||
| 
 | ||||
| gogo --dci 0.0.0.0 --mgrctl auth user access --id 3 --count 5 | ||||
| gogo --dci 0.0.0.0 --mgrctl auth user ls --admins | ||||
| gogo --vm 0.0.0.0 --port 22122 --mgrctl auth user ls --admins | ||||
| gogo --vm 0.0.0.0 --tty --mgrctl auth user ls --admins | ||||
| gogo --dns ns1.example.com --web-port 1501 | ||||
| gogo --dns ns1.example.com --port 22122 --web-port 1501 | ||||
| gogo --bill my.example.com --port 22 --web-port 1501 | ||||
| 
 | ||||
| Options: | ||||
| 
 | ||||
|  --vm[dci|bill|dns|ip] expected ip_addr             required | ||||
|  --port     | -p    ssh port,   default 22 | ||||
|  --web-port | -wp   web port,   default 443 | ||||
|  --go/--go3         go version, default go3 | ||||
|  --de               connect throw DE go3 server | ||||
|  --ssh              open only ssh session | ||||
|  --tty              for vm6/dci6 echo cmd for run container | ||||
|  --mgrctl [args]    for vm6/dci6 customize access params | ||||
| 
 | ||||
| Single options: | ||||
|  --init     | -i    generate configuration | ||||
|  --crt      | -c    generate ssh cert | ||||
|  --test     | -t    check go3 connection availability | ||||
|  --version  | -v    print version | ||||
|  --help     | -h    print this message and exit | ||||
| ``` | ||||
							
								
								
									
										43
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| # ? docker-compose.yml for development environment | ||||
| 
 | ||||
| # ! To start development you need to create a directory ./dummy_platform. | ||||
| # ? Place files from the test platform into it: | ||||
| # ? VM6: | ||||
| # ?    ./dummy_platform/opt/ispsystem/vm/config.json - configuration file | ||||
| # ? DCI6: | ||||
| # ?    ./dummy_platform/opt/ispsystem/dci/config.json - configuration file | ||||
| 
 | ||||
| # ? Create ./.env file and fill it with required vars: | ||||
| # ? PLATFORM_TYPE='vm' or PLATFORM_TYPE='dci' | ||||
| 
 | ||||
| # ? Launch:  | ||||
| # ?     docker-compose up -d --force-recreate | ||||
| # ?     docker attach mgrctl | ||||
| 
 | ||||
| services: | ||||
|   mgrctl: | ||||
|     container_name: mgrctl | ||||
|     restart: unless-stopped | ||||
|     build: | ||||
|       context: . | ||||
|       args: | ||||
|         - APP_VERSION=${APP_VERSION} | ||||
|         - APP_DIR=${APP_DIR} | ||||
|         - SRC_DIR=${SRC_DIR} | ||||
|         - PKG_NAME=${PKG_NAME} | ||||
|         - PKG_VERSION=${PKG_VERSION} | ||||
|     networks: | ||||
|       vm_box_net: null | ||||
|     volumes: | ||||
|       - type: bind | ||||
|         source: ./dummy_platform/opt/ispsystem/${PLATFORM_TYPE}/config.json | ||||
|         target: /opt/ispsystem/${PLATFORM_TYPE}/config.json | ||||
|     env_file: | ||||
|       - ./.env | ||||
|     tty: true | ||||
|     stdin_open: true | ||||
| 
 | ||||
| networks: | ||||
|   vm_box_net: | ||||
|     name: vm_box_net | ||||
|     driver: bridge | ||||
| @ -1,12 +0,0 @@ | ||||
| import click | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='access command for lazy example') | ||||
| @click.option('--debug/--no-debug', default=False) | ||||
| def cli(debug): | ||||
|     click.echo(f"Debug mode is {'on' if debug else 'off'}") | ||||
| 
 | ||||
| 
 | ||||
| @cli.command() | ||||
| def enable(): | ||||
|     click.echo('Access granted') | ||||
| @ -1,13 +0,0 @@ | ||||
| import click | ||||
| 
 | ||||
| from core.cli.lazy_group import LazyGroup | ||||
| from settings.general import INSTALLED_APPS | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands=INSTALLED_APPS['dci6'], | ||||
|     help='dci6 command for lazy example', | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
| @ -1,12 +0,0 @@ | ||||
| import click | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='access command for lazy example') | ||||
| @click.option('--debug/--no-debug', default=False) | ||||
| def cli(debug): | ||||
|     click.echo(f"Debug mode is {'on' if debug else 'off'}") | ||||
| 
 | ||||
| 
 | ||||
| @cli.command() | ||||
| def enable(): | ||||
|     click.echo('Access granted') | ||||
| @ -1,12 +0,0 @@ | ||||
| import click | ||||
| from core.cli.lazy_group import LazyGroup | ||||
| from settings.general import INSTALLED_APPS | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands=INSTALLED_APPS['vm6'], | ||||
|     help='vm6 command for lazy example', | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
| @ -1,13 +0,0 @@ | ||||
| import click | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='nodes command for lazy example') | ||||
| def cli(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @cli.command(name='list') | ||||
| def nodes_list(): | ||||
|     click.echo('NODES LIST: etc...') | ||||
|     for num in range(1, 10): | ||||
|         click.echo(num) | ||||
| @ -1,21 +0,0 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| import click | ||||
| 
 | ||||
| from core.cli.lazy_group import LazyGroup | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={ | ||||
|         'vm6': 'apps.vm6.commands.cli', | ||||
|         'dci6': 'apps.dci6.commands.cli', | ||||
|     }, | ||||
|     help='main CLI command for lazy example', | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     cli() | ||||
| @ -1,15 +0,0 @@ | ||||
| from settings.general import BASE_DIR | ||||
| 
 | ||||
| from settings.platform import ( | ||||
|     PLATFORM_TYPE, | ||||
|     PLATFORM_URL, | ||||
|     PLATFORM_CONFIG | ||||
| ) | ||||
| 
 | ||||
| from settings.db import( | ||||
|     DB_ENGINE, | ||||
|     DB_HOST, | ||||
|     DB_PORT, | ||||
|     DB_USER, | ||||
|     DB_PASSWORD | ||||
| ) | ||||
| @ -1,23 +0,0 @@ | ||||
| from settings.environment import env | ||||
| from settings.platform import PLATFORM_CONFIG | ||||
| 
 | ||||
| 
 | ||||
| # ! Required because some instance use psql db: | ||||
| DB_ENGINE = env.str( | ||||
|     'DB_ENGINE', | ||||
|     PLATFORM_CONFIG.get('DatabaseType', 'mysql') | ||||
| ) | ||||
| 
 | ||||
| # Connection parameters: | ||||
| DB_HOST = env.str( | ||||
|     'DB_HOST', | ||||
|     PLATFORM_CONFIG.get('DatabaseType', 'mysql') | ||||
| ) | ||||
| DB_PORT = env.int('DB_PORT', 3306) | ||||
| DB_USER = env.str('DB_USER', 'root') | ||||
| 
 | ||||
| # ! Do not pass password on production. Use value from config.json | ||||
| DB_PASSWORD = env.str( | ||||
|     'DB_PASSWORD', | ||||
|     PLATFORM_CONFIG.get('MysqlRootPassword', '') | ||||
| ) | ||||
| @ -1,13 +0,0 @@ | ||||
| from settings.environment import env | ||||
| from settings.general import BASE_DIR | ||||
| from utils.helpers import parse_json_file | ||||
| 
 | ||||
| 
 | ||||
| PLATFORM_TYPE = env.str('PLATFORM_TYPE', 'vm') | ||||
| 
 | ||||
| PLATFORM_CONFIG = parse_json_file(f'{BASE_DIR}/config.json') | ||||
| 
 | ||||
| PLATFORM_URL = env.url( | ||||
|     'PLATFORM_URL', | ||||
|     f"https://{PLATFORM_CONFIG.get('DomainName' ,'replace.me')}" | ||||
| ) | ||||
							
								
								
									
										13
									
								
								mgrctl/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								mgrctl/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| # █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀ | ||||
| # █░▀░█ ██▄ ░█░ █▀█ ▄ | ||||
| # -- -- -- -- -- -- - | ||||
| __author__ = "MOIS3Y, a.garaev" | ||||
| __credits__ = [ | ||||
|     "Stepan Zhukovsky", | ||||
|     "Arthur Garaev", | ||||
| ] | ||||
| __license__ = "MIT" | ||||
| __version__ = "0.1.1" | ||||
| __maintainer__ = "Stepan Zhukovsky" | ||||
| __email__ = "stepan@zhukovsky.me" | ||||
| __status__ = "Development" | ||||
							
								
								
									
										150
									
								
								mgrctl/api/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								mgrctl/api/base.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,150 @@ | ||||
| import sys | ||||
| import json | ||||
| import click | ||||
| import urllib | ||||
| import requests | ||||
| 
 | ||||
| from time import sleep | ||||
| from mgrctl.settings.api import ( | ||||
|     API_URL, | ||||
|     API_HEADERS, | ||||
|     API_EMAIL, | ||||
|     API_PASSWORD, | ||||
|     API_VERIFY_SSL, | ||||
|     API_COUNT_TRY_CONNECTIONS | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| class BaseAPI(object): | ||||
|     def __init__(self): | ||||
|         """Announces required parameters""" | ||||
|         self.API_URL = API_URL | ||||
|         self.API_HEADERS = API_HEADERS | ||||
|         self.API_EMAIL = API_EMAIL | ||||
|         self.API_PASSWORD = API_PASSWORD | ||||
|         self.API_VERIFY_SSL = API_VERIFY_SSL | ||||
|         self.API_VERSION = 'v3' | ||||
|         self.API_DEFINITION = 'api' | ||||
| 
 | ||||
|     def _gen_request_url(self, url): | ||||
|         return f'{self.API_URL}/{self.API_DEFINITION}/{self.API_VERSION}{url}' | ||||
| 
 | ||||
|     def call_api(self, url, method='GET', headers={}, data={}): | ||||
|         # set conn params | ||||
|         attempt = API_COUNT_TRY_CONNECTIONS | ||||
|         uri = self._gen_request_url(url) | ||||
|         headers = self.API_HEADERS if not headers else headers | ||||
|         params_str = urllib.parse.urlencode(data, safe="+'()") | ||||
|         # connect | ||||
|         while attempt: | ||||
|             attempt -= 1 | ||||
|             try: | ||||
|                 if method == 'POST': | ||||
|                     api_request = requests.post( | ||||
|                         url=uri, | ||||
|                         json=data, | ||||
|                         headers=headers, | ||||
|                         verify=self.API_VERIFY_SSL | ||||
|                     ) | ||||
|                 if method == 'GET': | ||||
|                     uri = f'{uri}?{params_str}' if params_str else uri | ||||
|                     api_request = requests.get( | ||||
|                         url=uri, | ||||
|                         headers=headers, | ||||
|                         verify=self.API_VERIFY_SSL | ||||
|                     ) | ||||
|             except Exception as error: | ||||
|                 ConnectionError = requests.exceptions.ConnectionError | ||||
|                 if type(error) is ConnectionError: | ||||
|                     if attempt == 0: | ||||
|                         click.echo(f'Error: {type(error).__name__}') | ||||
|                         click.echo(f'mgrctl cannot connect to {self.API_URL}') | ||||
|                         sys.exit() | ||||
|                     else: | ||||
|                         continue | ||||
|                 else: | ||||
|                     click.echo(f'Error: {type(error).__name__}') | ||||
|                     sys.exit() | ||||
| 
 | ||||
|             # Get response: | ||||
|             response = self._parse_response(api_request) | ||||
| 
 | ||||
|             # Validate response: | ||||
|             if self._error_handler(response): | ||||
|                 continue  # new attempt connection | ||||
| 
 | ||||
|             return response | ||||
| 
 | ||||
|     def _parse_response(self, api_request): | ||||
|         try: | ||||
|             response = json.loads(api_request.text) | ||||
|             return response | ||||
|         except json.decoder.JSONDecodeError: | ||||
|             click.echo('Error: Invalid API response') | ||||
|             raise sys.exit() | ||||
| 
 | ||||
|     def _is_error(self, response): | ||||
|         if response.get('error'): | ||||
|             return True | ||||
| 
 | ||||
|     def _is_error_3004(self, error): | ||||
|         if error.get('code') == 3004: | ||||
|             sleep(2)  # wait 2 second timeout | ||||
|             return True | ||||
| 
 | ||||
|     def _error_handler(self, response): | ||||
|         if self._is_error(response): | ||||
|             error = response.get('error') | ||||
|             if self._is_error_3004(error): | ||||
|                 return True | ||||
|             else: | ||||
|                 click.echo(f'Error: API return {response}') | ||||
|                 raise sys.exit() | ||||
| 
 | ||||
| 
 | ||||
| class BaseAuthAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_VERSION = 'v4' | ||||
|         self.API_DEFINITION = 'auth' | ||||
| 
 | ||||
|     def get_auth_token(self, email=None, password=None) -> dict: | ||||
|         email = self.API_EMAIL if not email else email | ||||
|         password = self.API_PASSWORD if not password else password | ||||
|         return self.call_api( | ||||
|             url='/public/token', | ||||
|             method='POST', | ||||
|             data={'email': email, 'password': password} | ||||
|         ) | ||||
| 
 | ||||
|     def get_auth_key(self, token=None, user=None) -> dict: | ||||
|         headers = {} | ||||
|         user = self.API_EMAIL if not user else user | ||||
|         if token: | ||||
|             headers = self.make_auth_header(token) | ||||
|         return self.call_api( | ||||
|             url=f'/user/{user}/key', | ||||
|             method='POST', | ||||
|             headers=headers | ||||
|         ) | ||||
| 
 | ||||
|     def make_auth_header(self, token: str) -> dict: | ||||
|         return {'x-xsrf-token': token} | ||||
| 
 | ||||
|     def whoami(self) -> dict: | ||||
|         return self.call_api( | ||||
|             url='/whoami', | ||||
|             method='GET' | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class BaseIpAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_DEFINITION = 'ip' | ||||
| 
 | ||||
| 
 | ||||
| class BaseDnsProxyAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_DEFINITION = 'dnsproxy' | ||||
							
								
								
									
										51
									
								
								mgrctl/api/dci6.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								mgrctl/api/dci6.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| from mgrctl.api.base import BaseAPI, BaseAuthAPI, BaseDnsProxyAPI, BaseIpAPI | ||||
| 
 | ||||
| 
 | ||||
| class AuthAPI(BaseAuthAPI): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class BackupAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_VERSION = 'v4' | ||||
|         self.API_DEFINITION = 'backup' | ||||
| 
 | ||||
| 
 | ||||
| class DnsProxyAPI(BaseDnsProxyAPI): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class EserviceAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_DEFINITION = 'eservice' | ||||
| 
 | ||||
| 
 | ||||
| class IsoAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_DEFINITION = 'iso' | ||||
| 
 | ||||
| 
 | ||||
| class IpmiAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_DEFINITION = 'ipmiproxy' | ||||
| 
 | ||||
| 
 | ||||
| class IpAPI(BaseIpAPI): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class ReportAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_VERSION = 'v4' | ||||
|         self.API_DEFINITION = 'report' | ||||
| 
 | ||||
| 
 | ||||
| class UpdaterAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_DEFINITION = 'updater' | ||||
							
								
								
									
										19
									
								
								mgrctl/api/vm6.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								mgrctl/api/vm6.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| from mgrctl.api.base import BaseAPI, BaseAuthAPI, BaseDnsProxyAPI, BaseIpAPI | ||||
| 
 | ||||
| 
 | ||||
| class AuthAPI(BaseAuthAPI): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class DnsProxyAPI(BaseDnsProxyAPI): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class IpAPI(BaseIpAPI): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| class VmAPI(BaseAPI): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.API_DEFINITION = 'vm' | ||||
							
								
								
									
										93
									
								
								mgrctl/apps/dci6/auth/commands.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								mgrctl/apps/dci6/auth/commands.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| import click | ||||
| 
 | ||||
| from mgrctl.api.dci6 import AuthAPI | ||||
| from mgrctl.utils.api_users import UserAPI | ||||
| 
 | ||||
| 
 | ||||
| user_cursor = UserAPI(callback_class=AuthAPI) | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='auth cmd for auth in DCImanager 6') | ||||
| def cli(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @cli.group(help='Manage users') | ||||
| def user(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @user.command(help='List users') | ||||
| @click.option( | ||||
|     '--all', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Show all users' | ||||
| ) | ||||
| @click.option( | ||||
|     '--admins', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Show all active admins', | ||||
| ) | ||||
| def ls(all, admins): | ||||
|     if all: | ||||
|         users = user_cursor.get_users(role='all') | ||||
|     elif admins: | ||||
|         users = user_cursor.get_users(role='admin') | ||||
|     else: | ||||
|         users = user_cursor.get_users(role='all') | ||||
|     # print users: | ||||
|     user_cursor.echo_users(users) | ||||
| 
 | ||||
| 
 | ||||
| @user.command( | ||||
|     help='Generate an access key and return auth link(s)', | ||||
|     no_args_is_help=True | ||||
| ) | ||||
| @click.option( | ||||
|     '--id', | ||||
|     '_id', | ||||
|     required=False, | ||||
|     type=int, | ||||
|     help='User id' | ||||
| ) | ||||
| @click.option( | ||||
|     '--count', | ||||
|     required=False, | ||||
|     type=int, | ||||
|     help='Number of access keys generated', | ||||
| ) | ||||
| @click.option( | ||||
|     '--random', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Generate access key for the first available admin' | ||||
| ) | ||||
| @click.option( | ||||
|     '--interactive', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Interactive mode, ignores other keys' | ||||
| ) | ||||
| def access(_id, count, interactive, random): | ||||
|     if _id and not count: | ||||
|         keys = user_cursor.get_access_keys(user=_id, count=1) | ||||
|     elif _id and count: | ||||
|         keys = user_cursor.get_access_keys(user=_id, count=count) | ||||
|     elif random: | ||||
|         admin = user_cursor.get_first_random_admin() | ||||
|         keys = user_cursor.get_access_keys(user=admin.get('id', 3)) | ||||
|     elif interactive: | ||||
|         user_cursor.gen_access_links_interactive() | ||||
|         return  # exit from func | ||||
|     else: | ||||
|         pass | ||||
|     links = user_cursor.gen_access_links(keys) | ||||
|     user_cursor.echo_access_links(links) | ||||
| 
 | ||||
| 
 | ||||
| @user.command(help='Generate API token for mgrctl user') | ||||
| def token(): | ||||
|     token = user_cursor.gen_api_token() | ||||
|     user_cursor.echo_api_token(token) | ||||
							
								
								
									
										13
									
								
								mgrctl/apps/dci6/commands.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								mgrctl/apps/dci6/commands.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| import click | ||||
| 
 | ||||
| from mgrctl.cli.lazy_group import LazyGroup | ||||
| from mgrctl.settings.general import INSTALLED_APPS | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands=INSTALLED_APPS['dci6'], | ||||
|     help='dci6 command for DCI6manager management', | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
							
								
								
									
										93
									
								
								mgrctl/apps/vm6/auth/commands.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								mgrctl/apps/vm6/auth/commands.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| import click | ||||
| 
 | ||||
| from mgrctl.api.vm6 import AuthAPI | ||||
| from mgrctl.utils.api_users import UserAPI | ||||
| 
 | ||||
| 
 | ||||
| user_cursor = UserAPI(callback_class=AuthAPI) | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='auth cmd for auth in VMmanager 6') | ||||
| def cli(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @cli.group(help='Manage users') | ||||
| def user(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @user.command(help='List users') | ||||
| @click.option( | ||||
|     '--all', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Show all users' | ||||
| ) | ||||
| @click.option( | ||||
|     '--admins', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Show all active admins', | ||||
| ) | ||||
| def ls(all, admins): | ||||
|     if all: | ||||
|         users = user_cursor.get_users(role='all') | ||||
|     elif admins: | ||||
|         users = user_cursor.get_users(role='admin') | ||||
|     else: | ||||
|         users = user_cursor.get_users(role='all') | ||||
|     # print users: | ||||
|     user_cursor.echo_users(users) | ||||
| 
 | ||||
| 
 | ||||
| @user.command( | ||||
|     help='Generate an access key and return auth link(s)', | ||||
|     no_args_is_help=True | ||||
| ) | ||||
| @click.option( | ||||
|     '--id', | ||||
|     '_id', | ||||
|     required=False, | ||||
|     type=int, | ||||
|     help='User id' | ||||
| ) | ||||
| @click.option( | ||||
|     '--count', | ||||
|     required=False, | ||||
|     type=int, | ||||
|     help='Number of access keys generated', | ||||
| ) | ||||
| @click.option( | ||||
|     '--random', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Generate access key for the first available admin' | ||||
| ) | ||||
| @click.option( | ||||
|     '--interactive', | ||||
|     is_flag=True, | ||||
|     required=False, | ||||
|     help='Interactive mode, ignores other keys' | ||||
| ) | ||||
| def access(_id, count, interactive, random): | ||||
|     if _id and not count: | ||||
|         keys = user_cursor.get_access_keys(user=_id, count=1) | ||||
|     elif _id and count: | ||||
|         keys = user_cursor.get_access_keys(user=_id, count=count) | ||||
|     elif random: | ||||
|         admin = user_cursor.get_first_random_admin() | ||||
|         keys = user_cursor.get_access_keys(user=admin.get('id', 3)) | ||||
|     elif interactive: | ||||
|         user_cursor.gen_access_links_interactive() | ||||
|         return  # exit from func | ||||
|     else: | ||||
|         pass | ||||
|     links = user_cursor.gen_access_links(keys) | ||||
|     user_cursor.echo_access_links(links) | ||||
| 
 | ||||
| 
 | ||||
| @user.command(help='Generate API token for mgrctl user') | ||||
| def token(): | ||||
|     token = user_cursor.gen_api_token() | ||||
|     user_cursor.echo_api_token(token) | ||||
							
								
								
									
										13
									
								
								mgrctl/apps/vm6/commands.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								mgrctl/apps/vm6/commands.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| import click | ||||
| 
 | ||||
| from mgrctl.cli.lazy_group import LazyGroup | ||||
| from mgrctl.settings.general import INSTALLED_APPS | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands=INSTALLED_APPS['vm6'], | ||||
|     help='vm6 command for VM6manager management', | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
							
								
								
									
										32
									
								
								mgrctl/mgrctl.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								mgrctl/mgrctl.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,32 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| 
 | ||||
| # █▀▄▀█ █▀▀ █▀█ █▀▀ ▀█▀ █░░ ▀ | ||||
| # █░▀░█ █▄█ █▀▄ █▄▄ ░█░ █▄▄ ▄ | ||||
| # -- -- -- -- -- -- -- -- -- | ||||
| 
 | ||||
| import click | ||||
| 
 | ||||
| from mgrctl import __version__ | ||||
| from mgrctl.cli.lazy_group import LazyGroup | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={ | ||||
|         'vm6': 'mgrctl.apps.vm6.commands.cli', | ||||
|         'dci6': 'mgrctl.apps.dci6.commands.cli', | ||||
|     }, | ||||
|     help='main CLI command for mgrctl app', | ||||
| ) | ||||
| @click.version_option( | ||||
|     version=__version__, | ||||
|     package_name='mgrctl', | ||||
|     message=__version__ | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     cli() | ||||
							
								
								
									
										7
									
								
								mgrctl/settings/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								mgrctl/settings/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| from mgrctl.settings.general import BASE_DIR | ||||
| 
 | ||||
| from mgrctl.settings.platform import ( | ||||
|     PLATFORM_TYPE, | ||||
|     PLATFORM_URL, | ||||
|     PLATFORM_CONFIG | ||||
| ) | ||||
							
								
								
									
										47
									
								
								mgrctl/settings/api.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								mgrctl/settings/api.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| from requests.packages import urllib3 | ||||
| 
 | ||||
| from mgrctl.settings.environment import env | ||||
| from mgrctl.settings.platform import ( | ||||
|     PLATFORM_TYPE, | ||||
|     PLATFORM_VERIFY_SSL, | ||||
|     PLATFORM_VERIFY_SSL_WARNING, | ||||
|     PLATFORM_DUMMY, | ||||
|     PLATFORM_DUMMY_API_URL, | ||||
|     PLATFORM_DUMMY_EMAIL, | ||||
|     PLATFORM_DUMMY_PASSWORD, | ||||
|     PLATFORM_DUMMY_TOKEN, | ||||
| ) | ||||
| 
 | ||||
| # Name of nginx container: | ||||
| API_INPUT_HOSTNAME = 'input' | ||||
| 
 | ||||
| # Port that nginx container is listening: | ||||
| API_INPUT_PORT = '1500' | ||||
| 
 | ||||
| # Internal API url: | ||||
| API_URL = f'http://{API_INPUT_HOSTNAME}:{API_INPUT_PORT}' | ||||
| 
 | ||||
| # Headers for internal auth: | ||||
| API_HEADERS = {"Internal-Auth": "on", "Accept": "application/json"} | ||||
| 
 | ||||
| # Alias for import: | ||||
| API_VERIFY_SSL = PLATFORM_VERIFY_SSL | ||||
| 
 | ||||
| # API 3004 Unavailable error handler: | ||||
| API_COUNT_TRY_CONNECTIONS = env.int('API_COUNT_TRY_CONNECTIONS', 3) | ||||
| 
 | ||||
| # Suppress warning from urllib3: | ||||
| if not PLATFORM_VERIFY_SSL_WARNING: | ||||
|     # ! This is not recommended, | ||||
|     # ! the user will not see a message about an untrusted SSL connection | ||||
|     urllib3.disable_warnings( | ||||
|         category=urllib3.exceptions.InsecureRequestWarning | ||||
|     ) | ||||
| 
 | ||||
| # Development mode: | ||||
| if PLATFORM_DUMMY: | ||||
|     API_URL = PLATFORM_DUMMY_API_URL | ||||
|     API_HEADERS = {'x-xsrf-token': PLATFORM_DUMMY_TOKEN} | ||||
| 
 | ||||
| API_EMAIL = PLATFORM_DUMMY_EMAIL | ||||
| API_PASSWORD = PLATFORM_DUMMY_PASSWORD | ||||
| @ -6,10 +6,9 @@ BASE_DIR = pathlib.Path(__file__).resolve().parent.parent | ||||
| 
 | ||||
| INSTALLED_APPS = { | ||||
|     'vm6': { | ||||
|         'access': 'apps.vm6.access.commands.cli', | ||||
|         'nodes': 'apps.vm6.nodes.commands.cli', | ||||
|         'auth': 'mgrctl.apps.vm6.auth.commands.cli', | ||||
|     }, | ||||
|     'dci6': { | ||||
|         'access': 'apps.dci6.access.commands.cli', | ||||
|         'auth': 'mgrctl.apps.dci6.auth.commands.cli', | ||||
|     }, | ||||
| } | ||||
							
								
								
									
										41
									
								
								mgrctl/settings/platform.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								mgrctl/settings/platform.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| from mgrctl.settings.environment import env | ||||
| from mgrctl.utils.helpers import parse_json_file | ||||
| 
 | ||||
| 
 | ||||
| PLATFORM_TYPE = env.str('PLATFORM_TYPE', 'vm') | ||||
| 
 | ||||
| PLATFORM_VERIFY_SSL = env.bool('PLATFORM_VERIFY_SSL', True) | ||||
| PLATFORM_VERIFY_SSL_WARNING = env.bool('PLATFORM_VERIFY_SSL_WARNING', True) | ||||
| 
 | ||||
| PLATFORM_CONFIG = env.str( | ||||
|     'PLATFORM_CONFIG', | ||||
|     f'/opt/ispsystem/{PLATFORM_TYPE}/config.json' | ||||
| ) | ||||
| 
 | ||||
| PLATFORM_CONFIG = parse_json_file(PLATFORM_CONFIG) | ||||
| 
 | ||||
| PLATFORM_URL = env.str( | ||||
|     'PLATFORM_URL', | ||||
|     f"https://{PLATFORM_CONFIG.get('DomainName' ,'replace.me')}" | ||||
| ) | ||||
| 
 | ||||
| # Development mode: | ||||
| PLATFORM_DUMMY = env.bool('PLATFORM_DUMMY', False) | ||||
| 
 | ||||
| if PLATFORM_TYPE == 'vm': | ||||
|     PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_VM6_API_URL', '') | ||||
|     PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_VM6_EMAIL', '') | ||||
|     PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_VM6_PASSWORD', '') | ||||
|     PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_VM6_TOKEN', '') | ||||
| elif PLATFORM_TYPE == 'dci': | ||||
|     PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_DCI6_API_URL', '') | ||||
|     PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_DCI6_EMAIL', '') | ||||
|     PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_DCI6_PASSWORD', '') | ||||
|     PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_DCI6_TOKEN', '') | ||||
| else: | ||||
|     # ? guarantees that constants exist for import | ||||
|     # ? if the user has set the wrong PLATFORM_TYPE: | ||||
|     PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_API_URL', '') | ||||
|     PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_EMAIL', '') | ||||
|     PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_PASSWORD', '') | ||||
|     PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_TOKEN', '') | ||||
							
								
								
									
										92
									
								
								mgrctl/utils/api_users.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								mgrctl/utils/api_users.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| import click | ||||
| from tabulate import tabulate | ||||
| 
 | ||||
| from mgrctl.settings.platform import PLATFORM_URL | ||||
| 
 | ||||
| 
 | ||||
| class UserAPI(object): | ||||
|     def __init__(self, callback_class): | ||||
|         """Announces required parameters""" | ||||
|         self.callback_class = callback_class | ||||
|         self.callback = callback_class() | ||||
| 
 | ||||
|     def get_users(self, role: str) -> list: | ||||
|         data = {} | ||||
|         if role == 'admin': | ||||
|             data = {"where": "((roles+CP+'%@admin%')+AND+(state+EQ+'active'))"} | ||||
|         response = self.callback.call_api( | ||||
|             url='/user', | ||||
|             method='GET', | ||||
|             data=data | ||||
|         ) | ||||
|         users = self._extract_users(users=response) | ||||
|         return users | ||||
| 
 | ||||
|     def _extract_users(self, users: dict) -> list: | ||||
|         return users.get('list', []) | ||||
| 
 | ||||
|     def _format_users(self, users: list) -> list: | ||||
|         output = [] | ||||
|         for user in users: | ||||
|             output.append({ | ||||
|                 'id': user.get('id', ''), | ||||
|                 'email': user.get('email', ''), | ||||
|                 'roles': user.get('roles', []), | ||||
|                 'state': user.get('state', ''), | ||||
|                 # add more fields here... | ||||
|             }) | ||||
|         return output | ||||
| 
 | ||||
|     def get_first_random_admin(self): | ||||
|         users = self.get_users(role='admin') | ||||
|         admin = {} | ||||
|         for user in users: | ||||
|             if '@admin' in user.get('roles', []): | ||||
|                 admin = user | ||||
|                 break | ||||
|         return admin | ||||
| 
 | ||||
|     def echo_users(self, users: list) -> None: | ||||
|         output = self._format_users(users) | ||||
|         click.echo(tabulate(output, headers='keys')) | ||||
| 
 | ||||
|     def get_access_keys(self, user, count=1): | ||||
|         keys = [] | ||||
|         while count >= 1: | ||||
|             count -= 1 | ||||
|             key = self.callback.get_auth_key(user=user) | ||||
|             check = key.get('key', '') | ||||
|             if check: | ||||
|                 keys.append(key) | ||||
|         return keys | ||||
| 
 | ||||
|     def gen_access_links(self, keys: list) -> list: | ||||
|         links = [] | ||||
|         for key in keys: | ||||
|             _id = key.get('id', '') | ||||
|             link = f"{PLATFORM_URL}/auth/key/{key.get('key', '')}" | ||||
|             links.append({'id': _id, 'link': link}) | ||||
|         return links | ||||
| 
 | ||||
|     def echo_access_links(self, links: list) -> None: | ||||
|         click.echo(tabulate(links, headers='keys')) | ||||
| 
 | ||||
|     def gen_access_links_interactive(self) -> None: | ||||
|         users = self.get_users(role='admin') | ||||
|         self.echo_users(users) | ||||
|         try: | ||||
|             click.echo('Choose user id and count of keys') | ||||
|             _id = int(input('User ID: ')) | ||||
|             count = int(input('Count of keys: ')) | ||||
|             keys = self.get_access_keys(user=_id, count=count) | ||||
|             links = self.gen_access_links(keys) | ||||
|             self.echo_access_links(links) | ||||
|         except ValueError: | ||||
|             click.echo('Error: Invalid, value is not a valid integer') | ||||
| 
 | ||||
|     def gen_api_token(self, email=None, password=None): | ||||
|         token = self.callback.get_auth_token(email, password) | ||||
|         return token | ||||
| 
 | ||||
|     def echo_api_token(self, token: dict) -> None: | ||||
|         click.echo(tabulate([token], headers='keys')) | ||||
| @ -1,8 +1,9 @@ | ||||
| import json | ||||
| import sys | ||||
| import click | ||||
| 
 | ||||
| 
 | ||||
| def parse_json_file(file_path):  | ||||
| def parse_json_file(file_path: str) -> dict: | ||||
|     """ | ||||
|     Function read json file as usual config.json then parse it to python dict | ||||
| 
 | ||||
| @ -16,5 +17,7 @@ def parse_json_file(file_path): | ||||
|         with open(file_path, 'r') as f: | ||||
|             return json.load(f) | ||||
|     except Exception as error: | ||||
|         print(error) | ||||
|         click.echo(error) | ||||
|         click.echo("Required: /opt/ispsystem/PLATFORM_TYPE/config.json") | ||||
|         click.echo("Note: don't forget to mount this file into the container") | ||||
|         sys.exit(1) | ||||
							
								
								
									
										1634
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1634
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,22 +1,29 @@ | ||||
| [tool.poetry] | ||||
| name = "isp-maintenance" | ||||
| version = "0.1.0" | ||||
| name = "mgrctl" | ||||
| version = "0.1.1" | ||||
| description = "Maintenance service for ISPsystem platforms" | ||||
| authors = ["MOIS3Y <s.zhukovskii@ispsystem.com>", "Failak3 <v.shmidt@ispsystem.com>", "a.garaev <a.garaev@ispsystem.com>", "Ann_M <a.moskovkina@ispsystem.com>"] | ||||
| authors = [ | ||||
|     "MOIS3Y <s.zhukovskii@ispsystem.com>", | ||||
|     "a.garaev <a.garaev@ispsystem.com>", | ||||
| ] | ||||
| license = "MIT" | ||||
| readme = "README.md" | ||||
| 
 | ||||
| [tool.poetry.dependencies] | ||||
| python = "^3.11" | ||||
| peewee = "^3.17.0" | ||||
| click = "^8.1.7" | ||||
| requests = "^2.31.0" | ||||
| environs = "^10.3.0" | ||||
| environs = "^12.0.0" | ||||
| sh = "^2.0.7" | ||||
| tabulate = "^0.9.0" | ||||
| 
 | ||||
| [tool.poetry.group.dev.dependencies] | ||||
| flake8 = "^7.0.0" | ||||
| poetry-plugin-export = "^1.6.0" | ||||
| 
 | ||||
| [tool.poetry.scripts] | ||||
| mgrctl = 'mgrctl.mgrctl:cli' | ||||
| 
 | ||||
| [build-system] | ||||
| requires = ["poetry-core"] | ||||
| build-backend = "poetry.core.masonry.api" | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										243
									
								
								requirements.txt
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								requirements.txt
									
									
									
									
									
								
							| @ -1,123 +1,126 @@ | ||||
| certifi==2024.2.2 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \ | ||||
|     --hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 | ||||
| charset-normalizer==3.3.2 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ | ||||
|     --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ | ||||
|     --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ | ||||
|     --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ | ||||
|     --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ | ||||
|     --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ | ||||
|     --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ | ||||
|     --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ | ||||
|     --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ | ||||
|     --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ | ||||
|     --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ | ||||
|     --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ | ||||
|     --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ | ||||
|     --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ | ||||
|     --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ | ||||
|     --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ | ||||
|     --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ | ||||
|     --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ | ||||
|     --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ | ||||
|     --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ | ||||
|     --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ | ||||
|     --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ | ||||
|     --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ | ||||
|     --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ | ||||
|     --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ | ||||
|     --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ | ||||
|     --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ | ||||
|     --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ | ||||
|     --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ | ||||
|     --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ | ||||
|     --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ | ||||
|     --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ | ||||
|     --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ | ||||
|     --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ | ||||
|     --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ | ||||
|     --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ | ||||
|     --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ | ||||
|     --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ | ||||
|     --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ | ||||
|     --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ | ||||
|     --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ | ||||
|     --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ | ||||
|     --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ | ||||
|     --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ | ||||
|     --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ | ||||
|     --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ | ||||
|     --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ | ||||
|     --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ | ||||
|     --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ | ||||
|     --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ | ||||
|     --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ | ||||
|     --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ | ||||
|     --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ | ||||
|     --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ | ||||
|     --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ | ||||
|     --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ | ||||
|     --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ | ||||
|     --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ | ||||
|     --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ | ||||
|     --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ | ||||
|     --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ | ||||
|     --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ | ||||
|     --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ | ||||
|     --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ | ||||
|     --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ | ||||
|     --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ | ||||
|     --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ | ||||
|     --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ | ||||
|     --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ | ||||
|     --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ | ||||
|     --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ | ||||
|     --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ | ||||
|     --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ | ||||
|     --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ | ||||
|     --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ | ||||
|     --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ | ||||
|     --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ | ||||
|     --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ | ||||
|     --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ | ||||
|     --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ | ||||
|     --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ | ||||
|     --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ | ||||
|     --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ | ||||
|     --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ | ||||
|     --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ | ||||
|     --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ | ||||
|     --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ | ||||
|     --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ | ||||
|     --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ | ||||
|     --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 | ||||
| click==8.1.7 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ | ||||
|     --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de | ||||
| certifi==2025.4.26 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \ | ||||
|     --hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3 | ||||
| charset-normalizer==3.4.2 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4 \ | ||||
|     --hash=sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45 \ | ||||
|     --hash=sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7 \ | ||||
|     --hash=sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0 \ | ||||
|     --hash=sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7 \ | ||||
|     --hash=sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d \ | ||||
|     --hash=sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d \ | ||||
|     --hash=sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0 \ | ||||
|     --hash=sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184 \ | ||||
|     --hash=sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db \ | ||||
|     --hash=sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b \ | ||||
|     --hash=sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64 \ | ||||
|     --hash=sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b \ | ||||
|     --hash=sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8 \ | ||||
|     --hash=sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff \ | ||||
|     --hash=sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344 \ | ||||
|     --hash=sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58 \ | ||||
|     --hash=sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e \ | ||||
|     --hash=sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471 \ | ||||
|     --hash=sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148 \ | ||||
|     --hash=sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a \ | ||||
|     --hash=sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836 \ | ||||
|     --hash=sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e \ | ||||
|     --hash=sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63 \ | ||||
|     --hash=sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c \ | ||||
|     --hash=sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1 \ | ||||
|     --hash=sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01 \ | ||||
|     --hash=sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366 \ | ||||
|     --hash=sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58 \ | ||||
|     --hash=sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5 \ | ||||
|     --hash=sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c \ | ||||
|     --hash=sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2 \ | ||||
|     --hash=sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a \ | ||||
|     --hash=sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597 \ | ||||
|     --hash=sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b \ | ||||
|     --hash=sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5 \ | ||||
|     --hash=sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb \ | ||||
|     --hash=sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f \ | ||||
|     --hash=sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0 \ | ||||
|     --hash=sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941 \ | ||||
|     --hash=sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0 \ | ||||
|     --hash=sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86 \ | ||||
|     --hash=sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7 \ | ||||
|     --hash=sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7 \ | ||||
|     --hash=sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455 \ | ||||
|     --hash=sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6 \ | ||||
|     --hash=sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4 \ | ||||
|     --hash=sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0 \ | ||||
|     --hash=sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3 \ | ||||
|     --hash=sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1 \ | ||||
|     --hash=sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6 \ | ||||
|     --hash=sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981 \ | ||||
|     --hash=sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c \ | ||||
|     --hash=sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980 \ | ||||
|     --hash=sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645 \ | ||||
|     --hash=sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7 \ | ||||
|     --hash=sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12 \ | ||||
|     --hash=sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa \ | ||||
|     --hash=sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd \ | ||||
|     --hash=sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef \ | ||||
|     --hash=sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f \ | ||||
|     --hash=sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2 \ | ||||
|     --hash=sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d \ | ||||
|     --hash=sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5 \ | ||||
|     --hash=sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02 \ | ||||
|     --hash=sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3 \ | ||||
|     --hash=sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd \ | ||||
|     --hash=sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e \ | ||||
|     --hash=sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214 \ | ||||
|     --hash=sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd \ | ||||
|     --hash=sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a \ | ||||
|     --hash=sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c \ | ||||
|     --hash=sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681 \ | ||||
|     --hash=sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba \ | ||||
|     --hash=sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f \ | ||||
|     --hash=sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a \ | ||||
|     --hash=sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28 \ | ||||
|     --hash=sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691 \ | ||||
|     --hash=sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82 \ | ||||
|     --hash=sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a \ | ||||
|     --hash=sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027 \ | ||||
|     --hash=sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7 \ | ||||
|     --hash=sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518 \ | ||||
|     --hash=sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf \ | ||||
|     --hash=sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b \ | ||||
|     --hash=sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9 \ | ||||
|     --hash=sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544 \ | ||||
|     --hash=sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da \ | ||||
|     --hash=sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509 \ | ||||
|     --hash=sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f \ | ||||
|     --hash=sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a \ | ||||
|     --hash=sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f | ||||
| click==8.1.8 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \ | ||||
|     --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a | ||||
| colorama==0.4.6 ; python_version >= "3.11" and python_version < "4.0" and platform_system == "Windows" \ | ||||
|     --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ | ||||
|     --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 | ||||
| environs==10.3.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:cc421ddb143fa30183568164755aa113a160e555cd19e97e664c478662032c24 \ | ||||
|     --hash=sha256:feeaf28f17fd0499f9cd7c0fcf408c6d82c308e69e335eb92d09322fc9ed8138 | ||||
| idna==3.6 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ | ||||
|     --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f | ||||
| marshmallow==3.20.2 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:4c1daff273513dc5eb24b219a8035559dc573c8f322558ef85f5438ddd1236dd \ | ||||
|     --hash=sha256:c21d4b98fee747c130e6bc8f45c4b3199ea66bc00c12ee1f639f0aeca034d5e9 | ||||
| packaging==23.2 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \ | ||||
|     --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7 | ||||
| peewee==3.17.1 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:e009ac4227c4fdc0058a56e822ad5987684f0a1fbb20fed577200785102581c3 | ||||
| python-dotenv==1.0.1 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \ | ||||
|     --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a | ||||
| requests==2.31.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ | ||||
|     --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 | ||||
| urllib3==2.2.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20 \ | ||||
|     --hash=sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224 | ||||
| environs==12.0.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:152068ba62185b99d87df5f6d6044c0e533261777119037e718c1397fc7d697f \ | ||||
|     --hash=sha256:6150ddeb05562a80cc789b308c650d33b98a5f9c3f4c63d9ed465c433f1cb9e2 | ||||
| idna==3.10 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ | ||||
|     --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 | ||||
| marshmallow==4.0.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:3b6e80aac299a7935cfb97ed01d1854fb90b5079430969af92118ea1b12a8d55 \ | ||||
|     --hash=sha256:e7b0528337e9990fd64950f8a6b3a1baabed09ad17a0dfb844d701151f92d203 | ||||
| python-dotenv==1.1.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5 \ | ||||
|     --hash=sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d | ||||
| requests==2.32.3 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ | ||||
|     --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 | ||||
| sh==2.2.2 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:653227a7c41a284ec5302173fbc044ee817c7bad5e6e4d8d55741b9aeb9eb65b \ | ||||
|     --hash=sha256:e0b15b4ae8ffcd399bc8ffddcbd770a43c7a70a24b16773fbb34c001ad5d52af | ||||
| tabulate==0.9.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ | ||||
|     --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f | ||||
| urllib3==2.4.0 ; python_version >= "3.11" and python_version < "4.0" \ | ||||
|     --hash=sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466 \ | ||||
|     --hash=sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813 | ||||
|  | ||||
							
								
								
									
										10
									
								
								scripts/devtools/cli/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								scripts/devtools/cli/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| # █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀ | ||||
| # █░▀░█ ██▄ ░█░ █▀█ ▄ | ||||
| # -- -- -- -- -- -- - | ||||
| __author__ = "MOIS3Y" | ||||
| __credits__ = ["Stepan Zhukovsky"] | ||||
| __license__ = "MIT" | ||||
| __version__ = "0.1.0" | ||||
| __maintainer__ = "Stepan Zhukovsky" | ||||
| __email__ = "stepan@zhukovsky.me" | ||||
| __status__ = "Development" | ||||
							
								
								
									
										50
									
								
								scripts/devtools/cli/builder.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								scripts/devtools/cli/builder.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| import click | ||||
| import sh | ||||
| 
 | ||||
| from .lazy_group import LazyGroup | ||||
| from .utils import abort_if_false | ||||
| from . import settings | ||||
| 
 | ||||
| 
 | ||||
| @click.group() | ||||
| def cli1(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={'docker-compose': 'cli.builder.docker_compose'}, | ||||
| ) | ||||
| def cli2(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='cmd for build/destroy project in docker containers') | ||||
| def docker_compose(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for build project in docker containers') | ||||
| def build(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'build', _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for destroy project in docker containers') | ||||
| @click.option( | ||||
|     '--yes', | ||||
|     is_flag=True, | ||||
|     callback=abort_if_false, | ||||
|     expose_value=False, | ||||
|     prompt='Are you sure you want to destroy docker containers') | ||||
| def destroy(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'down',  _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| cli = click.CommandCollection( | ||||
|     sources=[cli1, cli2], | ||||
|     help='cmd for building the project' | ||||
| ) | ||||
							
								
								
									
										39
									
								
								scripts/devtools/cli/lazy_group.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								scripts/devtools/cli/lazy_group.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| import importlib | ||||
| import click | ||||
| 
 | ||||
| 
 | ||||
| class LazyGroup(click.Group): | ||||
|     def __init__(self, *args, lazy_subcommands=None, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         # lazy_subcommands is a map of the form: | ||||
|         # | ||||
|         #   {command-name} -> {module-name}.{command-object-name} | ||||
|         # | ||||
|         self.lazy_subcommands = lazy_subcommands or {} | ||||
| 
 | ||||
|     def list_commands(self, ctx): | ||||
|         base = super().list_commands(ctx) | ||||
|         lazy = sorted(self.lazy_subcommands.keys()) | ||||
|         return base + lazy | ||||
| 
 | ||||
|     def get_command(self, ctx, cmd_name): | ||||
|         if cmd_name in self.lazy_subcommands: | ||||
|             return self._lazy_load(cmd_name) | ||||
|         return super().get_command(ctx, cmd_name) | ||||
| 
 | ||||
|     def _lazy_load(self, cmd_name): | ||||
|         # lazily loading a command, | ||||
|         # first get the module name and attribute name | ||||
|         import_path = self.lazy_subcommands[cmd_name] | ||||
|         modname, cmd_object_name = import_path.rsplit(".", 1) | ||||
|         # do the import | ||||
|         mod = importlib.import_module(modname) | ||||
|         # get the Command object from that module | ||||
|         cmd_object = getattr(mod, cmd_object_name) | ||||
|         # check the result to make debugging easier | ||||
|         if not isinstance(cmd_object, click.BaseCommand): | ||||
|             raise ValueError( | ||||
|                 f"Lazy loading of {import_path} failed by returning " | ||||
|                 "a non-command object" | ||||
|             ) | ||||
|         return cmd_object | ||||
							
								
								
									
										57
									
								
								scripts/devtools/cli/runner.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								scripts/devtools/cli/runner.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| import click | ||||
| import sh | ||||
| 
 | ||||
| from .lazy_group import LazyGroup | ||||
| from . import settings | ||||
| 
 | ||||
| 
 | ||||
| @click.group() | ||||
| def cli1(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={'docker-compose': 'cli.runner.docker_compose'}, | ||||
| ) | ||||
| def cli2(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='cmd for run/stop/restart project in docker containers') | ||||
| def docker_compose(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for run project docker containers') | ||||
| def up(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'up', '-d', _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for down project docker containers') | ||||
| def down(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'down', _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for restart project docker containers') | ||||
| def restart(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose( | ||||
|             '-f', | ||||
|             settings.COMPOSE_FILE, | ||||
|             'up', | ||||
|             '-d', | ||||
|             '--build', | ||||
|             '--force-recreate', | ||||
|             _fg=True | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| cli = click.CommandCollection( | ||||
|     sources=[cli1, cli2], | ||||
|     help='cmd for running the project standalone or docker-compose' | ||||
| ) | ||||
							
								
								
									
										18
									
								
								scripts/devtools/cli/settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								scripts/devtools/cli/settings.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| import pathlib | ||||
| from environs import Env | ||||
| 
 | ||||
| 
 | ||||
| # Path: | ||||
| ROOT_DIR = pathlib.Path(__file__).resolve().parent.parent.parent.parent | ||||
| PROJECT_DIR = ROOT_DIR / 'mgrctl' | ||||
| COMPOSE_FILE = ROOT_DIR / 'docker-compose.yml' | ||||
| 
 | ||||
| # Init environment: | ||||
| env = Env() | ||||
| 
 | ||||
| # read .env file, if it exists | ||||
| # reed more about .env file here: https://github.com/sloria/environs | ||||
| env.read_env(path=ROOT_DIR / '.env') | ||||
| 
 | ||||
| # ! insecure save sudo password wherever | ||||
| SUDO_PASSWORD = env.str('SUDO_PASSWORD', None) | ||||
							
								
								
									
										15
									
								
								scripts/devtools/cli/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								scripts/devtools/cli/utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import click | ||||
| 
 | ||||
| from . import __version__ | ||||
| 
 | ||||
| 
 | ||||
| def print_version(ctx, param, value): | ||||
|     if not value or ctx.resilient_parsing: | ||||
|         return | ||||
|     click.echo(__version__) | ||||
|     ctx.exit() | ||||
| 
 | ||||
| 
 | ||||
| def abort_if_false(ctx, param, value): | ||||
|     if not value: | ||||
|         ctx.abort() | ||||
							
								
								
									
										30
									
								
								scripts/devtools/dev.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										30
									
								
								scripts/devtools/dev.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,30 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| import click | ||||
| 
 | ||||
| from cli.lazy_group import LazyGroup | ||||
| from cli.utils import print_version | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={ | ||||
|         'builder': 'cli.builder.cli', | ||||
|         'runner': 'cli.runner.cli', | ||||
|     }, | ||||
|     help='dev.py CLI tool for dev actions', | ||||
| ) | ||||
| @click.option( | ||||
|     '--version', | ||||
|     is_flag=True, | ||||
|     callback=print_version, | ||||
|     expose_value=False, | ||||
|     is_eager=True, | ||||
|     help='Print version and exit' | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     cli() | ||||
							
								
								
									
										512
									
								
								scripts/gogo/gogo.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										512
									
								
								scripts/gogo/gogo.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,512 @@ | ||||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| # █▀▀ █▀█ █▀▀ █▀█ ▀ | ||||
| # █▄█ █▄█ █▄█ █▄█ ▄ | ||||
| # -- -- -- -- -- -- | ||||
| 
 | ||||
| # INIT GLOBAL VARIABLES: | ||||
| _VERSION="0.1.1" | ||||
| _SCRIPT_NAME="$(basename $0)" | ||||
| _GO_CMD="go3" | ||||
| _DEBUG_MODE=false | ||||
| 
 | ||||
| _CONFIG_DIR="${HOME}/.config/gogo" | ||||
| _CONFIG="${_CONFIG_DIR}/gogo.conf" | ||||
| 
 | ||||
| _IS_TTY=false | ||||
| _IS_SSH_ONLY=false | ||||
| _IS_MGRCTL_ARGS=false | ||||
| _MGRCTL_ARGS="" | ||||
| _MGRCTL_BIN="mgrctl" | ||||
| _MGRCTL_CMD="" | ||||
| _MGRCTL_RUN="" | ||||
| _MGRCTL_KEY="" | ||||
| 
 | ||||
| _PLATFORM_TYPE="" | ||||
| _PLATFORM_GENERATION=6 | ||||
| _PLATFORM_SSH_PORT=22 | ||||
| _PLATFORM_WEB_PORT=443 | ||||
| _PLATFORM_IP_ADDR="" | ||||
| _PLATFORM_CONFIG_FILE="" | ||||
| _PLATFORM_NETWORK_NAME="" | ||||
| 
 | ||||
| _SSH_CONNECT_CMD="" | ||||
| _SSH_REMOTE_CMD="" | ||||
| 
 | ||||
| _ACCESS_LINK="" | ||||
| 
 | ||||
| 
 | ||||
| # Colorize output | ||||
| # Usage - $(colorize CYAN "Hello, friend!") | ||||
| colorize() { | ||||
| 	local RED="\033[0;31m" | ||||
| 	local GREEN="\033[0;32m"  # <-- [0 means not bold | ||||
| 	local YELLOW="\033[1;33m" # <-- [1 means bold | ||||
| 	local BLUE="\033[0;34m" | ||||
| 	local MAGNETA="\033[0;35" | ||||
| 	local CYAN="\033[1;36m" | ||||
| 	# ... Add more colors if you like | ||||
| 
 | ||||
| 	local NC="\033[0m" # No Color | ||||
| 
 | ||||
| 	# printf "${(P)1}${2} ${NC}\n" # <-- zsh | ||||
| 	# printf "${!1}${2} ${NC}\n"   # <-- bash | ||||
| 	echo -e "${!1}${2}${NC}"       # <-- all-purpose | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # Print help message how used it script | ||||
| help() { | ||||
| 	# colorize value | ||||
| 	local script=$(colorize GREEN "$_SCRIPT_NAME") | ||||
| 	local required=$(colorize RED "required") | ||||
| 	# help message | ||||
| 	printf "Usage: $script [options [parameters]]                              \n" | ||||
| 	printf "                                                                   \n" | ||||
| 	printf "Examples:                                                          \n" | ||||
| 	printf "                                                                   \n" | ||||
| 	printf "${script} --init | init config file                                \n" | ||||
| 	printf "${script} --crt  | get ssh certificate for go3 connections         \n" | ||||
| 	printf "${script} --test | check go3 connection availability               \n" | ||||
| 	printf "                                                                   \n" | ||||
| 	printf "${script} --bill my.example.com                                    \n" | ||||
| 	printf "${script} --vm my.example.com --de  | connect throw DE go3 server  \n" | ||||
| 	printf "${script} --vm 0.0.0.0 --ssh | only ssh access                     \n" | ||||
| 	printf "${script} --vm 0.0.0.0 --tty | use mgrctl interactive              \n" | ||||
| 	printf "                                                                   \n" | ||||
| 	printf "${script} --dci 0.0.0.0 --mgrctl auth user access --id 3 --count 5 \n" | ||||
| 	printf "${script} --dci 0.0.0.0 --mgrctl auth user ls --admins             \n" | ||||
| 	printf "${script} --vm 0.0.0.0 --port 22122 --mgrctl auth user ls --admins \n" | ||||
| 	printf "${script} --vm 0.0.0.0 --tty --mgrctl auth user ls --admins        \n" | ||||
| 	printf "${script} --dns ns1.example.com --web-port 1501                    \n" | ||||
| 	printf "${script} --dns ns1.example.com --port 22122 --web-port 1501       \n" | ||||
| 	printf "${script} --bill my.example.com --port 22 --web-port 1501          \n" | ||||
| 	printf "                                                                   \n" | ||||
| 	printf "Options:                                                           \n" | ||||
| 	printf "                                                                   \n" | ||||
| 	printf " --vm[dci|bill|dns|ip] expected ip_addr             $required      \n" | ||||
| 	printf " --port     | -p    ssh port,   default 22                         \n" | ||||
| 	printf " --web-port | -wp   web port,   default 443                        \n" | ||||
| 	printf " --go/--go3         go version, default go3                        \n" | ||||
| 	printf " --de               connect throw DE go3 server                    \n" | ||||
| 	printf " --ssh              open only ssh session                          \n" | ||||
| 	printf " --tty              for vm6/dci6 echo cmd for run container        \n" | ||||
| 	printf " --mgrctl [args]    for vm6/dci6 customize access params           \n" | ||||
| 	printf "                                                                   \n" | ||||
| 	printf "Single options:                                                    \n" | ||||
| 	printf " --init     | -i    generate configuration                         \n" | ||||
| 	printf " --crt      | -c    generate ssh cert                              \n" | ||||
| 	printf " --test     | -t    check go3 connection availability              \n" | ||||
| 	printf " --version  | -v    print version                                  \n" | ||||
| 	printf " --help     | -h    print this message and exit                    \n" | ||||
| } | ||||
| 
 | ||||
| # Ask confirmation user if No - exit with 1 state | ||||
| continue_handler() { | ||||
| 	read -p "Continue? (Y/N): " confirm \ | ||||
| 	&& [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]] || exit 1 | ||||
| } | ||||
| 
 | ||||
| # Init script configuration file: | ||||
| init_config() { | ||||
| 	# Lables: | ||||
| 	local warning=$(colorize RED "WARNING!") | ||||
| 	local success=$(colorize GREEN "SUCCESS!") | ||||
| 	local script_name=$(colorize GREEN "${_SCRIPT_NAME}") | ||||
| 	# check if config file exists: | ||||
| 	if [ -f $_CONFIG ]; then | ||||
| 		echo "${warning} Config file is already exists" | ||||
| 		echo "New initialization rewrites current config" | ||||
| 		continue_handler | ||||
| 	fi | ||||
| 	# get user unputs: | ||||
| 	read -p "Enter russian go server address: "    _GO_SERVER_ADDR_RUSSIAN | ||||
| 	read -p "Enter germany go server address: "    _GO_SERVER_ADDR_GERMANY | ||||
| 	read -p "Enter test go server address: "       _GO_SERVER_ADDR_TEST | ||||
| 	read -p "Enter vault server address: "         _VAULT_SERVER_ADDR | ||||
| 	read -p "Enter username: "                     _SSH_PRIVATE_KEY_USER | ||||
| 	read -p "Enter full path to ssh private key: " _SSH_PRIVATE_KEY_PATH | ||||
| 	read -p "Enter full path to ssh public key: "  _SSH_PUBLIC_KEY_PATH | ||||
| 	read -p "Enter full path to ssh certificate: " _SSH_CRT_FILE | ||||
| 	read -p "Enter mgrctl image name: "            _MGRCTL_IMAGE | ||||
| 	# save config: | ||||
| 	mkdir -p $_CONFIG_DIR | ||||
| 	cat << EOF > "${_CONFIG}" | ||||
| GO_SERVER_ADDR_RUSSIAN=$_GO_SERVER_ADDR_RUSSIAN | ||||
| GO_SERVER_ADDR_GERMANY=$_GO_SERVER_ADDR_GERMANY | ||||
| GO_SERVER_ADDR_TEST=$_GO_SERVER_ADDR_TEST | ||||
| VAULT_SERVER_ADDR=$_VAULT_SERVER_ADDR | ||||
| SSH_PRIVATE_KEY_USER=$_SSH_PRIVATE_KEY_USER | ||||
| SSH_PRIVATE_KEY_PATH=$_SSH_PRIVATE_KEY_PATH | ||||
| SSH_PUBLIC_KEY_PATH=$_SSH_PUBLIC_KEY_PATH | ||||
| SSH_CRT_FILE=$_SSH_CRT_FILE | ||||
| MGRCTL_IMAGE=$_MGRCTL_IMAGE | ||||
| DEBUG_MODE=false | ||||
| EOF | ||||
| 	echo "" | ||||
| 	echo "${success} Config file was created, run ${script_name} again" | ||||
| 	echo "" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # Read config file that contains key=value params | ||||
| load_config() { | ||||
| 	local file="$_CONFIG" | ||||
| 
 | ||||
| 	if ! [ -f $_CONFIG ]; then | ||||
| 		help | ||||
| 		local warning=$(colorize RED "WARNING!") | ||||
| 		echo "" | ||||
| 		echo "${warning} Config file doesn't exist" | ||||
| 		echo "Init new config: ${_CONFIG}" | ||||
| 		continue_handler | ||||
| 		init_config | ||||
| 	fi | ||||
| 	 | ||||
| 	while IFS="=" read -r key value; do | ||||
| 		case "$key" in | ||||
| 			"GO_SERVER_ADDR_RUSSIAN") | ||||
| 				_GO_SERVER_ADDR_RUSSIAN="$value" | ||||
| 				_GO_SERVER_ADDR="$value" | ||||
| 				;; | ||||
| 			"GO_SERVER_ADDR_GERMANY") | ||||
| 				_GO_SERVER_ADDR_GERMANY="$value" | ||||
| 				;; | ||||
| 			"GO_SERVER_ADDR_TEST") | ||||
| 				_GO_SERVER_ADDR_TEST="$value" | ||||
| 				;; | ||||
| 			"VAULT_SERVER_ADDR") | ||||
| 				_VAULT_SERVER_ADDR="$value" | ||||
| 				;; | ||||
| 			"SSH_PRIVATE_KEY_USER") | ||||
| 				_SSH_PRIVATE_KEY_USER="$value" | ||||
| 				;; | ||||
| 			"SSH_PRIVATE_KEY_PATH") | ||||
| 				_SSH_PRIVATE_KEY_PATH="$value" | ||||
| 				;; | ||||
| 			"SSH_PUBLIC_KEY_PATH") | ||||
| 				_SSH_PUBLIC_KEY_PATH="$value" | ||||
| 				_VAULT_SSH_PUBLIC_KEY="@$value"  # @ sybol is important | ||||
| 				;; | ||||
| 			"SSH_CRT_FILE") | ||||
| 				_SSH_CRT_FILE="$value" | ||||
| 				;; | ||||
| 			"MGRCTL_IMAGE") | ||||
| 				_MGRCTL_IMAGE="$value" | ||||
| 				;; | ||||
| 			"DEBUG_MODE") | ||||
| 				_DEBUG_MODE="$value" | ||||
| 				;; | ||||
| 		esac | ||||
| 	done < "$file" | ||||
| } | ||||
| 
 | ||||
| # Generate key for coremgr based platrorms access link: | ||||
| gen_random_key() { | ||||
| 	_MGRCTL_KEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| gen_coremgr_access_params() { | ||||
| 	# get opt name: | ||||
| 	local opt=$1 | ||||
| 	# gen access key: | ||||
| 	gen_random_key | ||||
| 	# fill current parametrs: | ||||
| 	_PLATFORM_TYPE=$(sed 's~[^[:alpha:]/]\+~~g' <<< "$opt") | ||||
| 	_PLATFORM_GENERATION=5 | ||||
| 	_MGRCTL_BIN="/usr/local/mgr5/sbin/mgrctl" | ||||
| 	_MGRCTL_ARGS="-m ${_PLATFORM_TYPE}mgr session.newkey key=$_MGRCTL_KEY"	 | ||||
| 
 | ||||
| 	# override _PLATFORM_GENERATION for bill6 or dns6 | ||||
| 	if [[ $opt == "--bill" ]] || [[ $opt == "--dns" ]]; then | ||||
| 		_PLATFORM_GENERATION=6 | ||||
| 	fi | ||||
| 	# override _MGRCTL_BIN _MGRCTL_ARGS for dns6 | ||||
| 	if [[ $opt == "--dns" ]]; then | ||||
| 		_MGRCTL_BIN="/opt/ispsystem/${_PLATFORM_TYPE}manager6/sbin/mgrctl" | ||||
| 		_MGRCTL_ARGS="-m ${_PLATFORM_TYPE}mgr session.newkey key=$_MGRCTL_KEY"	 | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| gen_docker_access_params(){ | ||||
| 	# get opt name: | ||||
| 	local opt=$1 | ||||
| 	# fill current parametrs: | ||||
| 	_PLATFORM_TYPE=$(sed 's~[^[:alpha:]/]\+~~g' <<< "$opt") | ||||
| 	_PLATFORM_GENERATION=6 | ||||
| 	_PLATFORM_CONFIG_FILE="/opt/ispsystem/${_PLATFORM_TYPE}/config.json" | ||||
| 	# set platform docker network name: | ||||
| 	if [[ $_PLATFORM_TYPE == "vm" ]]; then | ||||
| 		_PLATFORM_NETWORK_NAME="vm_vm_box_net" | ||||
| 	else | ||||
| 		_PLATFORM_NETWORK_NAME="dci_auth" | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| gen_ssh_connect_cmd(){ | ||||
| 	# get params: | ||||
| 	local go_server="${_GO_SERVER_ADDR}" | ||||
| 	local go_cmd="${_GO_CMD}" | ||||
| 	local address="${_PLATFORM_IP_ADDR}" | ||||
| 	local port="${_PLATFORM_SSH_PORT}" | ||||
| 	local key_path="${_SSH_PRIVATE_KEY_PATH}" | ||||
| 	local key_user="${_SSH_PRIVATE_KEY_USER}" | ||||
| 	local ssh_args="${key_user}@${go_server} ${go_cmd} ${address} -p ${port}" | ||||
| 	# generate cmd: | ||||
| 	_SSH_CONNECT_CMD="ssh -A -t -i ${key_path} ${ssh_args}" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| gen_ssh_remote_cmd() { | ||||
| 	# ? VMmanager6 || DCImanager6: | ||||
| 	if [[ $_PLATFORM_TYPE == "vm" ]] || \ | ||||
| 		[[ $_PLATFORM_TYPE == "dci" ]] && \ | ||||
| 		[[ $_PLATFORM_GENERATION -eq 6 ]]; then | ||||
| 		# use default mgrctl cmd if not set args: | ||||
| 		if [ -z "${_MGRCTL_ARGS}" ]; then | ||||
| 			_MGRCTL_ARGS="${_PLATFORM_TYPE}6 auth user access --random" | ||||
| 			_MGRCTL_CMD="${_MGRCTL_BIN} ${_MGRCTL_ARGS}" | ||||
| 		else | ||||
| 			_MGRCTL_CMD="${_MGRCTL_BIN} ${_PLATFORM_TYPE}6 ${_MGRCTL_ARGS}" | ||||
| 		fi | ||||
| 		# silent mode: | ||||
| 		local hide_output=">> /dev/null" | ||||
| 		if $_DEBUG_MODE; then | ||||
| 			hide_output="" | ||||
| 		fi | ||||
| 		# image: | ||||
| 		local image=${_MGRCTL_IMAGE} | ||||
| 		# docker cmd: | ||||
| 		local docker_bin="/usr/bin/docker" | ||||
| 		local docker_pull="${docker_bin} pull ${image} ${hide_output}" | ||||
| 		local docker_rm="${docker_bin} image rm -f ${image} ${hide_output}" | ||||
| 		local docker_run="${docker_bin} run" | ||||
| 		# mount config: | ||||
| 		local mount_src="source=${_PLATFORM_CONFIG_FILE}" | ||||
| 		local mount_trg="target=${_PLATFORM_CONFIG_FILE}" | ||||
| 		local mount_opt="type=bind,${mount_src},${mount_trg},readonly" | ||||
| 		local mount="--mount ${mount_opt}" | ||||
| 		# network config: | ||||
| 		local network="--network=${_PLATFORM_NETWORK_NAME}" | ||||
| 		# environment config: | ||||
| 		local envs="-e PLATFORM_TYPE=${_PLATFORM_TYPE}" | ||||
| 		# container args: | ||||
| 		local args="${_MGRCTL_CMD}" | ||||
| 		# mgrctl container params: | ||||
| 		local container="${network} ${mount} ${envs} --rm ${image} ${args}" | ||||
| 		# docker commands: | ||||
| 		local cmd="${docker_pull} && ${docker_run} ${container} && ${docker_rm}" | ||||
| 		# final cmd: | ||||
| 		_SSH_REMOTE_CMD="${cmd}" | ||||
| 		# set cmd for manual start container: | ||||
| 		if $_IS_TTY; then | ||||
| 			# override parammetrs if DEBUG_MODE=false add -it flag: | ||||
| 			docker_pull="${docker_bin} pull ${image}" | ||||
| 			docker_rm="${docker_bin} image rm -f ${image}" | ||||
| 			container="${network} ${mount} ${envs} --rm -i -t ${image}" | ||||
| 			cmd="${docker_pull} && ${docker_run} ${container} && ${docker_rm}" | ||||
| 			_MGRCTL_RUN="${cmd}" | ||||
| 		fi | ||||
| 	# ? BILLmanager6 ||  DNSmanager6 || IP/DNS/DCI/VMmanager5: | ||||
| 	else  | ||||
| 		# final cmd: | ||||
| 		_SSH_REMOTE_CMD="${_MGRCTL_BIN} ${_MGRCTL_ARGS}" | ||||
| 		echo_access_link | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| gen_access_link() { | ||||
| 	local url="https://${_PLATFORM_IP_ADDR}" | ||||
| 	local port="${_PLATFORM_WEB_PORT}" | ||||
| 	local platform="${_PLATFORM_TYPE}mgr" | ||||
| 	local func="func=auth&key=${_MGRCTL_KEY}" | ||||
| 	_ACCESS_LINK="${url}:${port}/${platform}?${func}" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| echo_access_link() { | ||||
| 	gen_access_link | ||||
| 	echo "mgr    link" | ||||
| 	echo "-----  -------------------------------------------------------------" | ||||
| 	echo "${_PLATFORM_TYPE}${_PLATFORM_GENERATION}  ${_ACCESS_LINK}" | ||||
| 	echo "" | ||||
| } | ||||
| 
 | ||||
| echo_mgrctl_run_msg() { | ||||
| 	echo "--------------------------------------------------------------------" | ||||
| 	echo "To run the mgrctl container manually on the client server:"  | ||||
| 	echo "copy and paste the command into the terminal." | ||||
| 	echo "This will download the image and run the container interactively." | ||||
| 	echo "After exiting the container and its image will be deleted." | ||||
| 	echo "--------------------------------------------------------------------" | ||||
| 	echo "${_MGRCTL_RUN}" | ||||
| 	echo "--------------------------------------------------------------------" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| get_access() { | ||||
| 	gen_ssh_connect_cmd | ||||
| 	if $_IS_SSH_ONLY; then | ||||
| 		# run connection: | ||||
| 		$_SSH_CONNECT_CMD | ||||
| 	else | ||||
| 		gen_ssh_remote_cmd | ||||
| 		# run connection send remote cmd: | ||||
| 		$_SSH_CONNECT_CMD "${_SSH_REMOTE_CMD}" | ||||
| 		if [[ $_PLATFORM_TYPE == "vm" ]] || \ | ||||
| 			[[ $_PLATFORM_TYPE == "dci" ]] && \ | ||||
| 			[[ $_PLATFORM_GENERATION -eq 6 ]] && \ | ||||
| 			$_IS_TTY; then | ||||
| 			echo_mgrctl_run_msg | ||||
| 		fi | ||||
| 		# use default mgrctl cmd if not set args: | ||||
| 		# run connection again for ssh tty session: | ||||
| 		$_SSH_CONNECT_CMD | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| get_vault_crt() { | ||||
| 	local public_key=$1 | ||||
| 	local crt_file=$2 | ||||
| 	vault login -method=oidc | ||||
| 	if [ ! -f $crt_file ]; then | ||||
| 		touch $crt_file | ||||
| 	fi | ||||
| 	vault write -field=signed_key ssh/sign/support \ | ||||
| 	public_key=$public_key valid_principals=root > $crt_file | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| set_ssh_agent() { | ||||
| 	local secret_key=$1 | ||||
| 	ssh-add -D | ||||
| 	ssh-add $secret_key | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| renewal_crt() { | ||||
| 	export VAULT_ADDR=$_VAULT_SERVER_ADDR | ||||
| 	get_vault_crt $_VAULT_SSH_PUBLIC_KEY $_SSH_CRT_FILE | ||||
| 	set_ssh_agent $_SSH_PRIVATE_KEY_PATH | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| test_go3_connection() { | ||||
| 	# force only ssh connections without platform features: | ||||
| 	_IS_SSH_ONLY=true | ||||
| 	# set fake client address: | ||||
| 	_PLATFORM_IP_ADDR="${_GO_SERVER_ADDR_TEST}" | ||||
| 	_PLATFORM_SSH_PORT=22 | ||||
| 
 | ||||
| 	echo "Run TEST: $_GO_SERVER_ADDR_RUSSIAN connection" | ||||
| 	get_access | ||||
| 
 | ||||
| 	echo "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --" | ||||
| 
 | ||||
| 	echo "Run TEST: $_GO_SERVER_ADDR_GERMANY connection" | ||||
| 	_GO_SERVER_ADDR="${_GO_SERVER_ADDR_GERMANY}" | ||||
| 	get_access | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # Parse user options | ||||
| optparser() { | ||||
| 	# count user-passed options: | ||||
| 	local count_options=$# | ||||
| 	# run help if empty and exit: | ||||
| 	if [[ count_options -eq 0 ]]; then | ||||
| 		help | ||||
| 		exit 2 | ||||
| 	fi | ||||
| 	# run init config if flag --init and exit: | ||||
| 	if [[ "$1" == "--init" ]]; then | ||||
| 		init_config | ||||
| 		exit 0 | ||||
| 	fi | ||||
| 	# load config from config file: | ||||
| 	load_config | ||||
| 	# parse opts: | ||||
| 	while [ ! -z "$1" ]; do | ||||
| 		case "$1" in | ||||
| 			--vm|--dci) | ||||
| 				gen_docker_access_params "$1" | ||||
| 				shift | ||||
| 				_PLATFORM_IP_ADDR="$1" | ||||
| 				;; | ||||
| 			--bill|--dns|--bill5|--ip5|--dns5|--vm5|--dci5) | ||||
| 				gen_coremgr_access_params "$1" | ||||
| 				shift | ||||
| 				_PLATFORM_IP_ADDR="$1" | ||||
| 				;; | ||||
| 			--port|-p) | ||||
| 				shift | ||||
| 				_PLATFORM_SSH_PORT="$1" | ||||
| 				;; | ||||
| 			--web-port|-wp) | ||||
| 				shift | ||||
| 				_PLATFORM_WEB_PORT="$1" | ||||
| 				;; | ||||
| 			--go|--go3) | ||||
| 				_GO_CMD=$(sed 's~[^[:alnum:]/]\+~~g' <<< "$1") | ||||
| 				;; | ||||
| 			--de) | ||||
| 				_GO_SERVER_ADDR="${_GO_SERVER_ADDR_GERMANY}" | ||||
| 				;; | ||||
| 			--mgrctl|--tty|--ssh) | ||||
| 				if [[ "$1" == "--mgrctl" ]]; then | ||||
| 					_IS_MGRCTL_ARGS=true | ||||
| 					shift | ||||
| 					_MGRCTL_ARGS=$@ | ||||
| 				elif [[ "$1" == "--tty" ]]; then | ||||
| 					if $_IS_MGRCTL_ARGS; then | ||||
| 						local error=$(colorize RED "ERROR!") | ||||
| 						echo "${error} $1 must be in before --mgrctl not after" | ||||
| 						exit 1 | ||||
| 					fi | ||||
| 					_IS_TTY=true | ||||
| 				elif [[ "$1" == "--ssh" ]]; then | ||||
| 					_IS_SSH_ONLY=true | ||||
| 				fi | ||||
| 				;; | ||||
| 			--crt|-c) | ||||
| 				renewal_crt | ||||
| 				exit 0 | ||||
| 				;; | ||||
| 			--test|-t) | ||||
| 				test_go3_connection | ||||
| 				exit 0 | ||||
| 				;; | ||||
| 			--help|-h) | ||||
| 				help | ||||
| 				exit 0 | ||||
| 				;; | ||||
| 			--version|-v) | ||||
| 				printf "$_VERSION\n" | ||||
| 				exit 0 | ||||
| 				;; | ||||
| 			*) | ||||
| 				if ! $_IS_MGRCTL_ARGS; then | ||||
| 					help | ||||
| 					exit 1 | ||||
| 				fi | ||||
| 				;; | ||||
| 		esac | ||||
| 	shift | ||||
| 	done | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # Entrypoint: | ||||
| main() { | ||||
| 	optparser $@ | ||||
| 	get_access | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # RUN IT: | ||||
| main $@ | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user