Compare commits

...

9 Commits

Author SHA1 Message Date
6bbebd5a7a feat!(mgrctl) new release 0.1.1
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
2025-05-07 16:17:20 +09:00
99dd122262 docs: add gogo usage guide 2024-12-12 23:45:19 +09:00
b84ef86cd0 docs: add --de into help msg 2024-12-12 22:54:47 +09:00
ba6dd53f6c update: new config support DE go server and --test option 2024-12-12 21:29:22 +09:00
5815c84b07 Fix: help msg missing auth subcommand 2024-07-22 21:36:20 +09:00
6c6df42e7f Fix: help message, init func and ssh-add cmd in --crt 2024-06-09 16:43:31 +09:00
da3e61eccb Hotfix: some instances use dashes rather than underscores in container names 2024-06-09 16:41:55 +09:00
e0de805af7 Add: gogo.sh script for quick access from employee side 2024-06-08 16:47:12 +09:00
4cdf3b4539 Fix: platform_dummy import bugs 2024-06-08 14:40:36 +09:00
31 changed files with 1952 additions and 5710 deletions

21
CHANGELOG.md Normal file
View 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

View File

@ -1,7 +1,7 @@
# app/Dockerfile # app/Dockerfile
# pull the official docker image # pull the official docker image
FROM python:3.11-alpine as poetry-base FROM python:3.12-alpine as poetry-base
# default build args # default build args
ARG APP_VERSION=0.1.0 \ ARG APP_VERSION=0.1.0 \
@ -45,7 +45,7 @@ RUN poetry build --format wheel \
&& rm -r /usr/local/venv && rm -r /usr/local/venv
# now multistage builds # now multistage builds
FROM python:3.11-alpine FROM python:3.12-alpine
# copy app and dependences # copy app and dependences
COPY --from=poetry-base /usr/local/ /usr/local/ COPY --from=poetry-base /usr/local/ /usr/local/

174
README.md
View File

@ -5,4 +5,176 @@ Maintenance application for quick access, check and resolve issues VM/DCImanager
### In progress ### 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
```

View File

@ -4,16 +4,11 @@
# ? Place files from the test platform into it: # ? Place files from the test platform into it:
# ? VM6: # ? VM6:
# ? ./dummy_platform/opt/ispsystem/vm/config.json - configuration file # ? ./dummy_platform/opt/ispsystem/vm/config.json - configuration file
# ? ./dummy_platform/opt/ispsystem/vm/mysql - database directory
# ? DCI6: # ? DCI6:
# ? ./dummy_platform/opt/ispsystem/dci/config.json - configuration file # ? ./dummy_platform/opt/ispsystem/dci/config.json - configuration file
# ? ./dummy_platform/opt/ispsystem/dci/mysql - database directory
# ? Create ./.env file and fill it with required vars: # ? Create ./.env file and fill it with required vars:
# ? PLATFORM_TYPE='vm' # ? PLATFORM_TYPE='vm' or PLATFORM_TYPE='dci'
# ? Database container:
# ? MYSQL_DATABASE="database name"
# ? MYSQL_ROOT_PASSWORD="super secret password from config.json"
# ? Launch: # ? Launch:
# ? docker-compose up -d --force-recreate # ? docker-compose up -d --force-recreate
@ -41,18 +36,6 @@ services:
- ./.env - ./.env
tty: true tty: true
stdin_open: true stdin_open: true
mysql:
container_name: mysql
image: docker-registry.ispsystem.com/mysql:5
volumes:
- ./dummy_platform/opt/ispsystem/${PLATFORM_TYPE}/mysql:/var/lib/mysql
env_file:
- ./.env
labels:
autoconf_mysql: "true"
networks:
vm_box_net: null
command: --group-concat-max-len=131072 --max-connections=1000 --optimizer-search-depth=0
networks: networks:
vm_box_net: vm_box_net:

View File

@ -1,15 +1,13 @@
# █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀ # █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀
# █░▀░█ ██▄ ░█░ █▀█ ▄ # █░▀░█ ██▄ ░█░ █▀█ ▄
# -- -- -- -- -- -- - # -- -- -- -- -- -- -
__author__ = "MOIS3Y, a.garaev, Failak3, Ann_M" __author__ = "MOIS3Y, a.garaev"
__credits__ = [ __credits__ = [
"Stepan Zhukovsky", "Stepan Zhukovsky",
"Arthur Garaev", "Arthur Garaev",
"Vladislav Shmidt",
"Anna Moskovkina"
] ]
__license__ = "MIT" __license__ = "MIT"
__version__ = "0.1.0" __version__ = "0.1.1"
__maintainer__ = "Stepan Zhukovsky" __maintainer__ = "Stepan Zhukovsky"
__email__ = "stepan@zhukovsky.me" __email__ = "stepan@zhukovsky.me"
__status__ = "Development" __status__ = "Development"

View File

@ -5,7 +5,6 @@ import urllib
import requests import requests
from time import sleep from time import sleep
from mgrctl.settings.api import ( from mgrctl.settings.api import (
API_URL, API_URL,
API_HEADERS, API_HEADERS,
@ -31,12 +30,15 @@ class BaseAPI(object):
return f'{self.API_URL}/{self.API_DEFINITION}/{self.API_VERSION}{url}' return f'{self.API_URL}/{self.API_DEFINITION}/{self.API_VERSION}{url}'
def call_api(self, url, method='GET', headers={}, data={}): def call_api(self, url, method='GET', headers={}, data={}):
# set conn params
attempt = API_COUNT_TRY_CONNECTIONS 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: while attempt:
attempt -= 1
try: try:
uri = self._gen_request_url(url)
headers = self.API_HEADERS if not headers else headers
params_str = urllib.parse.urlencode(data, safe="+'()")
if method == 'POST': if method == 'POST':
api_request = requests.post( api_request = requests.post(
url=uri, url=uri,
@ -52,16 +54,23 @@ class BaseAPI(object):
verify=self.API_VERIFY_SSL verify=self.API_VERIFY_SSL
) )
except Exception as error: except Exception as error:
click.echo(f'Error: {type(error).__name__}') ConnectionError = requests.exceptions.ConnectionError
sys.exit() 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: # Get response:
response = self._parse_response(api_request) response = self._parse_response(api_request)
# Validate response: # Validate response:
if self._error_handler(response): if self._error_handler(response):
attempt -= 1
sleep(2) # wait 2 second timeout
continue # new attempt connection continue # new attempt connection
return response return response
@ -80,6 +89,7 @@ class BaseAPI(object):
def _is_error_3004(self, error): def _is_error_3004(self, error):
if error.get('code') == 3004: if error.get('code') == 3004:
sleep(2) # wait 2 second timeout
return True return True
def _error_handler(self, response): def _error_handler(self, response):

View File

@ -1,15 +0,0 @@
# █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀
# █░▀░█ ██▄ ░█░ █▀█ ▄
# -- -- -- -- -- -- -
__author__ = "MOIS3Y, a.garaev, Failak3, Ann_M"
__credits__ = [
"Stepan Zhukovsky",
"Arthur Garaev",
"Vladislav Shmidt",
"Anna Moskovkina"
]
__license__ = "MIT"
__version__ = "0.1.0"
__maintainer__ = "Stepan Zhukovsky"
__email__ = "stepan@zhukovsky.me"
__status__ = "Development"

View File

@ -1,15 +0,0 @@
# █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀
# █░▀░█ ██▄ ░█░ █▀█ ▄
# -- -- -- -- -- -- -
__author__ = "MOIS3Y, a.garaev, Failak3, Ann_M"
__credits__ = [
"Stepan Zhukovsky",
"Arthur Garaev",
"Vladislav Shmidt",
"Anna Moskovkina"
]
__license__ = "MIT"
__version__ = "0.1.0"
__maintainer__ = "Stepan Zhukovsky"
__email__ = "stepan@zhukovsky.me"
__status__ = "Development"

View File

@ -1,10 +0,0 @@
# █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀
# █░▀░█ ██▄ ░█░ █▀█ ▄
# -- -- -- -- -- -- -
__author__ = "MOIS3Y"
__credits__ = ["Stepan Zhukovsky"]
__license__ = "MIT"
__version__ = "0.1.0"
__maintainer__ = "Stepan Zhukovsky"
__email__ = "stepan@zhukovsky.me"
__status__ = "Development"

View File

@ -1,6 +1,5 @@
import click import click
from mgrctl.apps.dci6.auth import __version__
from mgrctl.api.dci6 import AuthAPI from mgrctl.api.dci6 import AuthAPI
from mgrctl.utils.api_users import UserAPI from mgrctl.utils.api_users import UserAPI
@ -9,11 +8,6 @@ user_cursor = UserAPI(callback_class=AuthAPI)
@click.group(help='auth cmd for auth in DCImanager 6') @click.group(help='auth cmd for auth in DCImanager 6')
@click.version_option(
version=__version__,
package_name='mgrctl.apps.dci6.auth',
message=__version__
)
def cli(): def cli():
pass pass

View File

@ -1,15 +0,0 @@
# █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀
# █░▀░█ ██▄ ░█░ █▀█ ▄
# -- -- -- -- -- -- -
__author__ = "MOIS3Y, a.garaev, Failak3, Ann_M"
__credits__ = [
"Stepan Zhukovsky",
"Arthur Garaev",
"Vladislav Shmidt",
"Anna Moskovkina"
]
__license__ = "MIT"
__version__ = "0.1.0"
__maintainer__ = "Stepan Zhukovsky"
__email__ = "stepan@zhukovsky.me"
__status__ = "Development"

View File

@ -1,10 +0,0 @@
# █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀
# █░▀░█ ██▄ ░█░ █▀█ ▄
# -- -- -- -- -- -- -
__author__ = "MOIS3Y"
__credits__ = ["Stepan Zhukovsky"]
__license__ = "MIT"
__version__ = "0.1.0"
__maintainer__ = "Stepan Zhukovsky"
__email__ = "stepan@zhukovsky.me"
__status__ = "Development"

View File

@ -1,6 +1,5 @@
import click import click
from mgrctl.apps.vm6.auth import __version__
from mgrctl.api.vm6 import AuthAPI from mgrctl.api.vm6 import AuthAPI
from mgrctl.utils.api_users import UserAPI from mgrctl.utils.api_users import UserAPI
@ -9,11 +8,6 @@ user_cursor = UserAPI(callback_class=AuthAPI)
@click.group(help='auth cmd for auth in VMmanager 6') @click.group(help='auth cmd for auth in VMmanager 6')
@click.version_option(
version=__version__,
package_name='mgrctl.apps.vm6.auth',
message=__version__
)
def cli(): def cli():
pass pass

View File

@ -2,7 +2,6 @@ import click
from mgrctl.cli.lazy_group import LazyGroup from mgrctl.cli.lazy_group import LazyGroup
from mgrctl.settings.general import INSTALLED_APPS from mgrctl.settings.general import INSTALLED_APPS
from mgrctl.apps.vm6 import __version__
@click.group( @click.group(
@ -10,10 +9,5 @@ from mgrctl.apps.vm6 import __version__
lazy_subcommands=INSTALLED_APPS['vm6'], lazy_subcommands=INSTALLED_APPS['vm6'],
help='vm6 command for VM6manager management', help='vm6 command for VM6manager management',
) )
@click.version_option(
version=__version__,
package_name='mgrctl',
message=__version__
)
def cli(): def cli():
pass pass

View File

View File

@ -1,20 +0,0 @@
import json
from peewee import TextField
class JSONField(TextField):
"""
Class to "fake" a JSON field with a text field.
Not efficient but works nicely
"""
def db_value(self, value):
"""Convert the python value for storage in the database."""
return value if value is None else json.dumps(value)
def python_value(self, value):
"""Convert the database value to a pythonic value."""
return value if value is None else json.loads(value)
class UnknownField(object):
def __init__(self, *_, **__): pass

View File

@ -1,46 +0,0 @@
from peewee import MySQLDatabase, PostgresqlDatabase
from mgrctl.settings.db import (
DB_ENGINE,
DB_HOST,
DB_PORT,
DB_USER,
DB_PASSWORD
)
def guess_database(db_name):
"""
function checks DB_ENGINE and set correct connection class
with connection params. Expected database name in input.
Args:
db_name (_str_): database name
Returns:
(_MySQLDatabase_or_PostgresqlDatabase_ class):
contains db connection params
"""
if DB_ENGINE == 'mysql':
return MySQLDatabase(
db_name, **{
'charset': 'utf8',
'sql_mode': 'PIPES_AS_CONCAT',
'use_unicode': True,
'host': DB_HOST,
'port': DB_PORT,
'user': DB_USER,
'password': DB_PASSWORD
}
)
if DB_ENGINE == 'psql':
return PostgresqlDatabase(
db_name, **{
'charset': 'utf8',
'sql_mode': 'PIPES_AS_CONCAT',
'use_unicode': True,
'host': DB_HOST,
'port': DB_PORT,
'user': DB_USER,
'password': DB_PASSWORD
}
)

View File

@ -1,9 +0,0 @@
from mgrctl.db.connection import guess_database
# The variable will contain an object of
# the MySQLDatabase or PostgresqlDatabase class as well as all connection data
# If in the future there will be more databases in the platform,
# they should be added here
auth_database = guess_database('auth')
dci_1_database = guess_database('dci_1')

View File

@ -1,980 +0,0 @@
from peewee import (
AutoField,
BigIntegerField,
CharField,
CompositeKey,
DateTimeField,
FloatField,
ForeignKeyField,
IntegerField,
Model,
TextField,
SQL
)
from mgrctl.db.common import UnknownField
from mgrctl.db.dci6.databases import auth_database
class BaseModel(Model):
class Meta:
database = auth_database
class AlertSetting(BaseModel):
channel = UnknownField(null=True) # json
enabled = IntegerField(constraints=[SQL("DEFAULT 1")])
metric = UnknownField(null=True) # json
metric_id = CharField(null=True)
name = CharField(null=True)
class Meta:
table_name = 'alert_setting'
class AuthAcl(BaseModel):
ip_list = UnknownField() # json
name = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
class Meta:
table_name = 'auth_acl'
class AuthUser(BaseModel):
auth_source = CharField(constraints=[SQL("DEFAULT 'local'")])
avatar = TextField(null=True)
avatar_content_type = CharField(null=True)
avatar_filename = CharField(null=True)
created_date = DateTimeField(null=True)
email = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
email_confirm = IntegerField(constraints=[SQL("DEFAULT 0")])
full_name = CharField(null=True)
ip_list = UnknownField(null=True) # json
lang = CharField(constraints=[SQL("DEFAULT 'en'")])
password = CharField(null=True)
phone_number = CharField(null=True)
property = UnknownField(null=True) # json
reserve_codes = UnknownField(null=True) # json
roles = UnknownField() # json
ssh_priv_key = TextField(null=True)
ssh_pub_key = TextField(null=True)
state = CharField(constraints=[SQL("DEFAULT 'active'")])
timezone = CharField(null=True)
totp = CharField(null=True)
uuid = CharField(null=True, unique=True)
class Meta:
table_name = 'auth_user'
class AuthConfirmToken(BaseModel):
expires_at = DateTimeField(null=True)
resend_token_after = DateTimeField(null=True)
token = CharField(null=True, unique=True)
user = ForeignKeyField(
column_name='user',
field='id',
model=AuthUser,
null=True,
unique=True
)
class Meta:
table_name = 'auth_confirm_token'
class AuthGdprDoc(BaseModel):
change_date = DateTimeField(null=True)
desc_condition = CharField(null=True)
entry_date = DateTimeField(null=True)
locale = CharField(null=True)
name = CharField(unique=True)
required = IntegerField(constraints=[SQL("DEFAULT 0")])
state = CharField()
url = CharField(null=True)
class Meta:
table_name = 'auth_gdpr_doc'
class AuthGdprJournal(BaseModel):
action_date = DateTimeField(null=True)
action_type = CharField()
doc = ForeignKeyField(
column_name='doc',
field='id',
model=AuthGdprDoc,
null=True
)
ip = CharField(null=True)
user_email = CharField()
class Meta:
table_name = 'auth_gdpr_journal'
class AuthGeneratedSshkey(BaseModel):
generation_date = DateTimeField(null=True)
privkey = TextField(null=True)
pubkey = TextField(null=True)
class Meta:
table_name = 'auth_generated_sshkey'
class AuthProduct(BaseModel):
docker_compose_file = TextField(null=True)
name = CharField(null=True)
script = TextField(null=True)
version = CharField(null=True)
class Meta:
table_name = 'auth_product'
indexes = (
(('name', 'version'), True),
)
class AuthInstance(BaseModel):
conn_params = UnknownField(null=True) # json
dbkey = TextField(null=True)
demo = IntegerField(constraints=[SQL("DEFAULT 0")])
failure_reason = UnknownField(null=True) # json
limits = UnknownField(null=True) # json
name = CharField(null=True)
owner = ForeignKeyField(
column_name='owner',
field='id',
model=AuthUser,
null=True
)
product = ForeignKeyField(
column_name='product',
field='id',
model=AuthProduct,
null=True
)
roles = UnknownField(null=True) # json
started = DateTimeField(null=True)
status = CharField()
class Meta:
table_name = 'auth_instance'
class AuthInstanceHistory(BaseModel):
create_time = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")])
event_info = UnknownField(null=True) # json
event_type = CharField(null=True)
prev_time = DateTimeField(null=True)
ref = ForeignKeyField(
column_name='ref',
field='id',
model=AuthInstance,
null=True
)
request_id = CharField(null=True)
request_ip = CharField(null=True)
request_owner = CharField(null=True)
request_user = CharField(null=True)
class Meta:
table_name = 'auth_instance_history'
class AuthKey(BaseModel):
expires_at = DateTimeField(null=True)
name = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
user = ForeignKeyField(column_name='user', field='id', model=AuthUser)
class Meta:
table_name = 'auth_key'
class AuthLicense(BaseModel):
instance = ForeignKeyField(
column_name='instance',
field='id',
model=AuthInstance,
null=True,
unique=True
)
last_update = DateTimeField(null=True)
lic_data = UnknownField(null=True) # json
lic_request = UnknownField(null=True) # json
product = CharField(null=True)
signature_expire_date = DateTimeField(null=True)
status = CharField()
class Meta:
table_name = 'auth_license'
class AuthPermission(BaseModel):
data = UnknownField() # json
plugin = CharField(constraints=[SQL("DEFAULT ''")])
service = CharField(constraints=[SQL("DEFAULT ''")])
class Meta:
table_name = 'auth_permission'
indexes = (
(('service', 'plugin'), True),
)
class AuthPricelist(BaseModel):
bill_id = IntegerField(null=True, unique=True)
name = CharField(null=True)
params = UnknownField(null=True) # json
class Meta:
table_name = 'auth_pricelist'
class AuthRestrictions(BaseModel):
attempts_counting_duration = BigIntegerField()
attempts_max_count = IntegerField(null=True)
role = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
time_between_attempts = BigIntegerField()
time_to_unban = BigIntegerField()
class Meta:
table_name = 'auth_restrictions'
class AuthRestrictionsBans(BaseModel):
banned_until = DateTimeField()
user = ForeignKeyField(column_name='user', field='id', model=AuthUser)
user_ip = CharField(null=True)
class Meta:
table_name = 'auth_restrictions_bans'
indexes = (
(('user', 'user_ip'), True),
)
class AuthRole(BaseModel):
data = UnknownField() # json
human_descr = CharField(null=True)
human_name = CharField(null=True)
name = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
class Meta:
table_name = 'auth_role'
class AuthServer(BaseModel):
demo = IntegerField(constraints=[SQL("DEFAULT 0")])
host = CharField(null=True)
instance = ForeignKeyField(
column_name='instance',
field='id',
model=AuthInstance,
null=True,
unique=True
)
login = CharField(null=True)
machine_id = CharField(null=True)
password = CharField(null=True)
port = IntegerField(null=True)
class Meta:
table_name = 'auth_server'
indexes = (
(('host', 'port'), True),
)
class AuthService(BaseModel):
bill_id = IntegerField(null=True, unique=True)
info = UnknownField(null=True) # json
instance = ForeignKeyField(
column_name='instance',
field='id',
model=AuthInstance,
null=True,
unique=True
)
params = UnknownField(null=True) # json
payment_form = TextField(null=True)
status = CharField(null=True)
class Meta:
table_name = 'auth_service'
indexes = (
(('instance', 'bill_id'), True),
)
class AuthServiceDbkey(BaseModel):
dbkey = TextField(null=True)
name = CharField(null=True, unique=True)
class Meta:
table_name = 'auth_service_dbkey'
class AuthSession(BaseModel):
expires_at = DateTimeField(null=True)
is_internal = IntegerField(constraints=[SQL("DEFAULT 0")])
name = CharField(null=True, unique=True)
owner = ForeignKeyField(
column_name='owner',
field='id',
model=AuthUser,
null=True
)
trustee = ForeignKeyField(
backref='auth_user_trustee_set',
column_name='trustee',
field='id',
model=AuthUser,
null=True
)
updated_at = DateTimeField(null=True)
xsrf_token = CharField(null=True)
class Meta:
table_name = 'auth_session'
class AuthToken(BaseModel):
client_ip = CharField(null=True)
description = CharField(constraints=[SQL("DEFAULT ''")])
expires_at = DateTimeField(null=True)
last_used = DateTimeField()
name = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
need_2fa = IntegerField(constraints=[SQL("DEFAULT 0")])
owner = ForeignKeyField(column_name='owner', field='id', model=AuthUser)
trustee = ForeignKeyField(
backref='auth_user_trustee_set',
column_name='trustee',
field='id',
model=AuthUser
)
class Meta:
table_name = 'auth_token'
class AuthTrusteeUser(BaseModel):
instance = ForeignKeyField(
column_name='instance',
field='id',
model=AuthInstance,
null=True
)
role = CharField(null=True)
trustee = ForeignKeyField(
column_name='trustee',
field='id',
model=AuthUser,
null=True
)
user = ForeignKeyField(
backref='auth_user_user_set',
column_name='user',
field='id',
model=AuthUser,
null=True
)
class Meta:
table_name = 'auth_trustee_user'
indexes = (
(('user', 'trustee', 'instance'), True),
)
class AuthUser2Acl(BaseModel):
acl = ForeignKeyField(column_name='acl', field='id', model=AuthAcl)
user = ForeignKeyField(column_name='user', field='id', model=AuthUser)
class Meta:
table_name = 'auth_user2acl'
indexes = (
(('user', 'acl'), True),
)
class AuthUserRole(BaseModel):
instance = ForeignKeyField(
column_name='instance',
field='id',
model=AuthInstance,
null=True
)
roles = UnknownField() # json
state = CharField(constraints=[SQL("DEFAULT 'active'")])
trustee = ForeignKeyField(
column_name='trustee',
field='id',
model=AuthUser
)
user = ForeignKeyField(
backref='auth_user_user_set',
column_name='user',
field='id',
model=AuthUser
)
class Meta:
table_name = 'auth_user_role'
indexes = (
(('user', 'trustee', 'instance'), True),
)
class AuthUserSetting(BaseModel):
data = UnknownField(null=True) # json
instance = ForeignKeyField(
column_name='instance',
field='id',
model=AuthInstance,
null=True
)
name = CharField(null=True)
user = ForeignKeyField(
column_name='user',
field='id',
model=AuthUser
)
class Meta:
table_name = 'auth_user_setting'
indexes = (
(('user', 'name', 'instance'), True),
)
class AuthUserSshkey(BaseModel):
name = CharField(constraints=[SQL("DEFAULT ''")])
owner = ForeignKeyField(
column_name='owner',
field='id',
model=AuthUser,
null=True
)
ssh_pub_key = TextField()
class Meta:
table_name = 'auth_user_sshkey'
indexes = (
(('name', 'owner'), True),
)
class AuthUsersLocks(BaseModel):
description = CharField(constraints=[SQL("DEFAULT ''")])
service_name = CharField()
user = ForeignKeyField(column_name='user', field='id', model=AuthUser)
class Meta:
table_name = 'auth_users_locks'
indexes = (
(('user', 'service_name'), True),
)
primary_key = CompositeKey('service_name', 'user')
class BackupAlembicVersion(BaseModel):
version_num = CharField(primary_key=True)
class Meta:
table_name = 'backup_alembic_version'
class BackupTask(BaseModel):
connection_params = TextField()
cron_expression = CharField()
enabled = IntegerField()
limit_count = IntegerField()
limit_size_mib = IntegerField(null=True)
name = CharField()
note = TextField()
schedule_type = CharField()
storage_type = CharField()
class Meta:
table_name = 'backup_task'
class BackupFile(BaseModel):
date = DateTimeField()
downloadable = IntegerField()
name = CharField()
size = FloatField()
storage_type = CharField()
task = ForeignKeyField(
column_name='task',
field='id',
model=BackupTask,
null=True
)
class Meta:
table_name = 'backup_file'
class CsDocuments(BaseModel):
lang = CharField(constraints=[SQL("DEFAULT ''")])
name = CharField(constraints=[SQL("DEFAULT ''")])
product = CharField(constraints=[SQL("DEFAULT ''")])
required = IntegerField(constraints=[SQL("DEFAULT 0")])
url = CharField(constraints=[SQL("DEFAULT ''")])
class Meta:
table_name = 'cs_documents'
indexes = (
(('product', 'lang', 'name'), True),
)
class CsSettings(BaseModel):
lang = CharField(constraints=[SQL("DEFAULT ''")])
product = CharField(constraints=[SQL("DEFAULT ''")])
prop_key = CharField(constraints=[SQL("DEFAULT ''")])
prop_value = CharField(constraints=[SQL("DEFAULT ''")])
class Meta:
table_name = 'cs_settings'
indexes = (
(('product', 'lang', 'prop_key'), True),
)
class EserviceAlembicVersion(BaseModel):
version_num = CharField(primary_key=True)
class Meta:
table_name = 'eservice_alembic_version'
class EserviceCustomEquipment(BaseModel):
data = TextField(null=True)
device_type = CharField()
features = UnknownField(null=True) # json
handler = CharField(unique=True)
handler_import = CharField(null=True)
name = CharField(unique=True)
protocol = UnknownField(null=True) # json
update_time = DateTimeField()
version = CharField()
class Meta:
table_name = 'eservice_custom_equipment'
class EserviceIpmiFru(BaseModel):
fru_info = UnknownField(null=True) # json
ipmi_id = AutoField()
update_time = DateTimeField()
class Meta:
table_name = 'eservice_ipmi_fru'
class EserviceIpmiInfo(BaseModel):
ipmi_id = AutoField()
model = CharField()
class Meta:
table_name = 'eservice_ipmi_info'
class EserviceIpmiSensors(BaseModel):
ipmi_id = AutoField()
sensors_info = UnknownField(null=True) # json
update_time = DateTimeField()
class Meta:
table_name = 'eservice_ipmi_sensors'
class IpmiProxyLocation(BaseModel):
docker_compose = TextField(null=True)
instance = IntegerField(null=True)
location = IntegerField(null=True)
status = CharField(constraints=[SQL("DEFAULT 'setting_up'")])
status_info = UnknownField(null=True) # json
supported_ipmi_consoles = UnknownField(null=True) # json
class Meta:
table_name = 'ipmi_proxy_location'
indexes = (
(('instance', 'location'), True),
)
class IpmiProxyConnection(BaseModel):
close_time = DateTimeField(null=True)
connection_data = UnknownField(null=True) # json
device_data = UnknownField(null=True) # json
intel_amt = IntegerField(null=True)
ipmi = IntegerField(null=True)
listen_web_port = IntegerField(null=True, unique=True)
location = ForeignKeyField(
column_name='location_id',
field='id',
model=IpmiProxyLocation
)
type = CharField(constraints=[SQL("DEFAULT 'web'")])
user = IntegerField(null=True)
vnc_port = IntegerField(null=True)
class Meta:
table_name = 'ipmi_proxy_connection'
class IpmiProxyJavaAgreement(BaseModel):
instance = IntegerField(null=True, unique=True)
java_agree = IntegerField(constraints=[SQL("DEFAULT 1")])
class Meta:
table_name = 'ipmi_proxy_java_agreement'
class IpmiProxyPlugin(BaseModel):
instance = IntegerField(null=True, unique=True)
class Meta:
table_name = 'ipmi_proxy_plugin'
class IspSettings(BaseModel):
name = CharField(primary_key=True)
value = TextField()
class Meta:
table_name = 'isp_settings'
class JournalAlembicVersion(BaseModel):
version_num = CharField(primary_key=True)
class Meta:
table_name = 'journal_alembic_version'
class JournalEvents(BaseModel):
data = UnknownField(null=True) # json
date_time = DateTimeField(
constraints=[SQL("DEFAULT CURRENT_TIMESTAMP(3)")]
)
entity_id = IntegerField()
entity_name = CharField()
entity_owner = IntegerField()
entity_type = CharField()
ip = CharField()
roles = UnknownField(null=True) # json
trustee_email = CharField(index=True)
trustee_id = IntegerField()
type = CharField()
user_email = CharField(index=True)
user_id = IntegerField()
class Meta:
table_name = 'journal_events'
class MsgsChannel(BaseModel):
comment = TextField(null=True)
creation_date = DateTimeField(null=True)
delivery_method = CharField()
enabled = IntegerField(constraints=[SQL("DEFAULT 1")])
language = CharField()
name = CharField()
params = UnknownField(null=True) # json
state = CharField(null=True)
class Meta:
table_name = 'msgs_channel'
class MsgsDeliveryMethod(BaseModel):
delivery_method = CharField(primary_key=True)
dm_params = UnknownField(null=True) # json
class Meta:
table_name = 'msgs_delivery_method'
class MsgsMessageDesign(BaseModel):
design = CharField(primary_key=True)
class Meta:
table_name = 'msgs_message_design'
class MsgsMessageDesignVariant(BaseModel):
delivery_method = CharField()
design = CharField()
design_content = TextField(null=True)
language = CharField()
class Meta:
table_name = 'msgs_message_design_variant'
indexes = (
(('design', 'delivery_method', 'language'), True),
(('design', 'delivery_method', 'language'), True),
)
primary_key = CompositeKey('delivery_method', 'design', 'language')
class MsgsNoticeReceiver(BaseModel):
delivery_method = CharField()
receivers = UnknownField(null=True) # json
user = IntegerField(null=True)
class Meta:
table_name = 'msgs_notice_receiver'
indexes = (
(('user', 'delivery_method'), True),
)
class MsgsTemplate(BaseModel):
priority = CharField()
template = CharField(primary_key=True)
class Meta:
table_name = 'msgs_template'
class MsgsTemplate2Category(BaseModel):
category = CharField()
template = CharField()
class Meta:
table_name = 'msgs_template2category'
indexes = (
(('template', 'category'), True),
(('template', 'category'), True),
)
primary_key = CompositeKey('category', 'template')
class MsgsTemplateVariant(BaseModel):
delivery_method = CharField()
language = CharField()
template = CharField()
tv_params = UnknownField(null=True) # json
class Meta:
table_name = 'msgs_template_variant'
indexes = (
(('template', 'delivery_method', 'language'), True),
(('template', 'delivery_method', 'language'), True),
)
primary_key = CompositeKey('delivery_method', 'language', 'template')
class MsgsUser(BaseModel):
language = CharField()
user = AutoField()
class Meta:
table_name = 'msgs_user'
class MsgsUser2DeliveryMethod(BaseModel):
delivery_method = CharField()
u2dm_params = UnknownField(null=True) # json
user = IntegerField()
class Meta:
table_name = 'msgs_user2delivery_method'
indexes = (
(('user', 'delivery_method'), True),
(('user', 'delivery_method'), True),
)
primary_key = CompositeKey('delivery_method', 'user')
class MsgsUserSubscription(BaseModel):
category = CharField()
delivery_method = CharField()
user = IntegerField()
class Meta:
table_name = 'msgs_user_subscription'
indexes = (
(('user', 'delivery_method', 'category'), True),
)
primary_key = CompositeKey('category', 'delivery_method', 'user')
class NcNotice(BaseModel):
create_timestamp = IntegerField(null=True)
entity = UnknownField(null=True) # json
params = UnknownField(null=True) # json
status = CharField(constraints=[SQL("DEFAULT 'sended'")])
timestamp = IntegerField(null=True)
type = CharField(null=True)
class Meta:
table_name = 'nc_notice'
class NcUser(BaseModel):
last_notice_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")])
read_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")])
class Meta:
table_name = 'nc_user'
class NcNotice2User(BaseModel):
notice = ForeignKeyField(
column_name='notice',
field='id',
model=NcNotice,
null=True
)
read_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")])
user = ForeignKeyField(
column_name='user',
field='id',
model=NcUser,
null=True
)
class Meta:
table_name = 'nc_notice2user'
indexes = (
(('user', 'notice'), True),
)
class NotifierNotify(BaseModel):
additional_info = UnknownField() # json
description = UnknownField() # json
instance_id = IntegerField(null=True)
modify_index = BigIntegerField()
name = CharField(null=True)
notify_type = CharField()
owner = IntegerField(null=True)
request_id = CharField(null=True)
request_ip = CharField(null=True)
time = DateTimeField(
constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")],
index=True
)
trustee = IntegerField(null=True)
class Meta:
table_name = 'notifier_notify'
class PsPlugin(BaseModel):
content = TextField()
current_version = CharField(null=True)
deprecated = IntegerField(constraints=[SQL("DEFAULT 0")])
filename = CharField(null=True)
intname = CharField(null=True, unique=True)
metadata = UnknownField() # json
name = CharField(null=True, unique=True)
obsoletes = UnknownField(null=True) # json
plugin_requirement = UnknownField(null=True) # json
product = CharField()
remote = IntegerField(constraints=[SQL("DEFAULT 0")])
status = CharField(constraints=[SQL("DEFAULT 'disabled'")])
version = CharField(null=True)
class Meta:
table_name = 'ps_plugin'
class PsPluginLicense(BaseModel):
instance = IntegerField(null=True)
license = UnknownField(null=True) # json
plugin = IntegerField(null=True)
class Meta:
table_name = 'ps_plugin_license'
indexes = (
(('instance', 'plugin'), True),
)
class ReportAlembicVersion(BaseModel):
version_num = CharField(primary_key=True)
class Meta:
table_name = 'report_alembic_version'
class ReportFile(BaseModel):
additional_info = UnknownField(null=True) # json
content = TextField(null=True)
create_datetime = DateTimeField()
entity = CharField()
entity_ids = UnknownField() # json
filename = CharField(null=True)
is_read = IntegerField()
status = CharField()
status_info = UnknownField(null=True) # json
type = CharField()
class Meta:
table_name = 'report_file'
class TaskmgrTask(BaseModel):
before_execute = UnknownField(null=True) # json
bin_args = UnknownField(null=True) # json
bin_path = CharField(constraints=[SQL("DEFAULT ''")])
callback_params = UnknownField(null=True) # json
defer_resolve = UnknownField(null=True) # json
defer_wait = UnknownField(null=True) # json
depends_on = UnknownField(null=True) # json
env = UnknownField(null=True) # json
instance_id = CharField(null=True)
lock_tag = UnknownField(null=True) # json
name = CharField(constraints=[SQL("DEFAULT ''")])
notify = UnknownField(null=True) # json
on_start = UnknownField(null=True) # json
output = TextField()
queue = UnknownField(null=True) # json
registration_time = DateTimeField(
constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")]
)
request_info = UnknownField(null=True) # json
return_code = IntegerField()
service = CharField(constraints=[SQL("DEFAULT ''")])
status = CharField(constraints=[SQL("DEFAULT 'created'")], index=True)
stdin = UnknownField(null=True) # json
ttl = IntegerField()
work_dir = CharField(constraints=[SQL("DEFAULT ''")])
worker_id = CharField(null=True)
class Meta:
table_name = 'taskmgr_task'
class Vault(BaseModel):
key = CharField(unique=True)
value = TextField()
class Meta:
table_name = 'vault'
class VaultAlembicVersion(BaseModel):
version_num = CharField(primary_key=True)
class Meta:
table_name = 'vault_alembic_version'
class VaultQueryLog(BaseModel):
date = DateTimeField()
owner_email = CharField()
owner_id = IntegerField()
request_id = CharField()
request_ip = CharField()
service = CharField()
trustee_id = IntegerField()
class Meta:
table_name = 'vault_query_log'

View File

@ -1,8 +0,0 @@
from mgrctl.db.connection import guess_database
# The variable will contain an object of
# the MySQLDatabase or PostgresqlDatabase class as well as all connection data
# If in the future there will be more databases in the platform,
# they should be added here
isp_database = guess_database('isp')

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,3 @@ from mgrctl.settings.platform import (
PLATFORM_URL, PLATFORM_URL,
PLATFORM_CONFIG PLATFORM_CONFIG
) )
from mgrctl.settings.db import(
DB_ENGINE,
DB_HOST,
DB_PORT,
DB_USER,
DB_PASSWORD
)

View File

@ -13,7 +13,7 @@ from mgrctl.settings.platform import (
) )
# Name of nginx container: # Name of nginx container:
API_INPUT_HOSTNAME = 'input' if PLATFORM_TYPE == 'vm' else 'dci_input_1' API_INPUT_HOSTNAME = 'input'
# Port that nginx container is listening: # Port that nginx container is listening:
API_INPUT_PORT = '1500' API_INPUT_PORT = '1500'
@ -42,5 +42,6 @@ if not PLATFORM_VERIFY_SSL_WARNING:
if PLATFORM_DUMMY: if PLATFORM_DUMMY:
API_URL = PLATFORM_DUMMY_API_URL API_URL = PLATFORM_DUMMY_API_URL
API_HEADERS = {'x-xsrf-token': PLATFORM_DUMMY_TOKEN} API_HEADERS = {'x-xsrf-token': PLATFORM_DUMMY_TOKEN}
API_EMAIL = PLATFORM_DUMMY_EMAIL
API_PASSWORD = PLATFORM_DUMMY_PASSWORD API_EMAIL = PLATFORM_DUMMY_EMAIL
API_PASSWORD = PLATFORM_DUMMY_PASSWORD

View File

@ -1,23 +0,0 @@
from mgrctl.settings.environment import env
from mgrctl.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', '')
)

View File

@ -22,14 +22,20 @@ PLATFORM_URL = env.str(
# Development mode: # Development mode:
PLATFORM_DUMMY = env.bool('PLATFORM_DUMMY', False) PLATFORM_DUMMY = env.bool('PLATFORM_DUMMY', False)
if PLATFORM_DUMMY: if PLATFORM_TYPE == 'vm':
if PLATFORM_TYPE == 'vm': PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_VM6_API_URL', '')
PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_VM6_API_URL', '') PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_VM6_EMAIL', '')
PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_VM6_EMAIL', '') PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_VM6_PASSWORD', '')
PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_VM6_PASSWORD', '') PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_VM6_TOKEN', '')
PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_VM6_TOKEN', '') elif PLATFORM_TYPE == 'dci':
if PLATFORM_TYPE == 'dci': PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_DCI6_API_URL', '')
PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_DCI6_API_URL', '') PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_DCI6_EMAIL', '')
PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_DCI6_EMAIL', '') PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_DCI6_PASSWORD', '')
PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_DCI6_PASSWORD', '') PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_DCI6_TOKEN', '')
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', '')

1807
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +1,25 @@
[tool.poetry] [tool.poetry]
name = "mgrctl" name = "mgrctl"
version = "0.1.0" version = "0.1.1"
description = "Maintenance service for ISPsystem platforms" description = "Maintenance service for ISPsystem platforms"
authors = [ authors = [
"MOIS3Y <s.zhukovskii@ispsystem.com>", "MOIS3Y <s.zhukovskii@ispsystem.com>",
"Failak3 <v.shmidt@ispsystem.com>",
"a.garaev <a.garaev@ispsystem.com>", "a.garaev <a.garaev@ispsystem.com>",
"Ann_M <a.moskovkina@ispsystem.com>"
] ]
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.11" python = "^3.11"
peewee = "^3.17.0"
click = "^8.1.7" click = "^8.1.7"
requests = "^2.31.0" requests = "^2.31.0"
environs = "^10.3.0" environs = "^12.0.0"
pymysql = {extras = ["rsa"], version = "^1.1.0"}
poetry-plugin-export = "^1.6.0"
sh = "^2.0.7" sh = "^2.0.7"
tabulate = "^0.9.0" tabulate = "^0.9.0"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
flake8 = "^7.0.0" flake8 = "^7.0.0"
poetry-plugin-export = "^1.6.0"
[tool.poetry.scripts] [tool.poetry.scripts]
mgrctl = 'mgrctl.mgrctl:cli' mgrctl = 'mgrctl.mgrctl:cli'

View File

@ -1,599 +1,126 @@
build==1.0.3 ; python_version >= "3.11" and python_version < "4.0" \ certifi==2025.4.26 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b \ --hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \
--hash=sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f --hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3
cachecontrol[filecache]==0.13.1 ; python_version >= "3.11" and python_version < "4.0" \ charset-normalizer==3.4.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:95dedbec849f46dda3137866dc28b9d133fc9af55f5b805ab1291833e4457aa4 \ --hash=sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4 \
--hash=sha256:f012366b79d2243a6118309ce73151bf52a38d4a5dac8ea57f09bd29087e506b --hash=sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45 \
certifi==2024.2.2 ; python_version >= "3.11" and python_version < "4.0" \ --hash=sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7 \
--hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \ --hash=sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0 \
--hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 --hash=sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7 \
cffi==1.16.0 ; python_version >= "3.11" and python_version < "4.0" and (platform_python_implementation != "PyPy" or sys_platform == "darwin") \ --hash=sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d \
--hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ --hash=sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d \
--hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ --hash=sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0 \
--hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \ --hash=sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184 \
--hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \ --hash=sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db \
--hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \ --hash=sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b \
--hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \ --hash=sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64 \
--hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \ --hash=sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b \
--hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \ --hash=sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8 \
--hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \ --hash=sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff \
--hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \ --hash=sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344 \
--hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \ --hash=sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58 \
--hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \ --hash=sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e \
--hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \ --hash=sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471 \
--hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \ --hash=sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148 \
--hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \ --hash=sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a \
--hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \ --hash=sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836 \
--hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \ --hash=sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e \
--hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \ --hash=sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63 \
--hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \ --hash=sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c \
--hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \ --hash=sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1 \
--hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \ --hash=sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01 \
--hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \ --hash=sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366 \
--hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \ --hash=sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58 \
--hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \ --hash=sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5 \
--hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \ --hash=sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c \
--hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \ --hash=sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2 \
--hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \ --hash=sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a \
--hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \ --hash=sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597 \
--hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \ --hash=sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b \
--hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \ --hash=sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5 \
--hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \ --hash=sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb \
--hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \ --hash=sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f \
--hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \ --hash=sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0 \
--hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \ --hash=sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941 \
--hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \ --hash=sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0 \
--hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \ --hash=sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86 \
--hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \ --hash=sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7 \
--hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \ --hash=sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7 \
--hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \ --hash=sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455 \
--hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \ --hash=sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6 \
--hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \ --hash=sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4 \
--hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \ --hash=sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0 \
--hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \ --hash=sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3 \
--hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \ --hash=sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1 \
--hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \ --hash=sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6 \
--hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \ --hash=sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981 \
--hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \ --hash=sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c \
--hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \ --hash=sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980 \
--hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \ --hash=sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645 \
--hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \ --hash=sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7 \
--hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ --hash=sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12 \
--hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 --hash=sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa \
charset-normalizer==3.3.2 ; python_version >= "3.11" and python_version < "4.0" \ --hash=sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd \
--hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ --hash=sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef \
--hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ --hash=sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f \
--hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ --hash=sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2 \
--hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ --hash=sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d \
--hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ --hash=sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5 \
--hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ --hash=sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02 \
--hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ --hash=sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3 \
--hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ --hash=sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd \
--hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ --hash=sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e \
--hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ --hash=sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214 \
--hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ --hash=sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd \
--hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ --hash=sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a \
--hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ --hash=sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c \
--hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ --hash=sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681 \
--hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ --hash=sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba \
--hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ --hash=sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f \
--hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ --hash=sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a \
--hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ --hash=sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28 \
--hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ --hash=sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691 \
--hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ --hash=sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82 \
--hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ --hash=sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a \
--hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ --hash=sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027 \
--hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ --hash=sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7 \
--hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ --hash=sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518 \
--hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ --hash=sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf \
--hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ --hash=sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b \
--hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ --hash=sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9 \
--hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ --hash=sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544 \
--hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ --hash=sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da \
--hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ --hash=sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509 \
--hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ --hash=sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f \
--hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ --hash=sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a \
--hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ --hash=sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f
--hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ click==8.1.8 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \
--hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a
--hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ colorama==0.4.6 ; python_version >= "3.11" and python_version < "4.0" and platform_system == "Windows" \
--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
cleo==2.1.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0b2c880b5d13660a7ea651001fb4acb527696c01f15c9ee650f377aa543fd523 \
--hash=sha256:4a31bd4dd45695a64ee3c4758f583f134267c2bc518d8ae9a29cf237d009b07e
click==8.1.7 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
colorama==0.4.6 ; python_version >= "3.11" and python_version < "4.0" and (platform_system == "Windows" or os_name == "nt") \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
crashtest==0.4.1 ; python_version >= "3.11" and python_version < "4.0" \ environs==12.0.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:80d7b1f316ebfbd429f648076d6275c877ba30ba48979de4191714a75266f0ce \ --hash=sha256:152068ba62185b99d87df5f6d6044c0e533261777119037e718c1397fc7d697f \
--hash=sha256:8d23eac5fa660409f57472e3851dab7ac18aba459a8d19cbbba86d3d5aecd2a5 --hash=sha256:6150ddeb05562a80cc789b308c650d33b98a5f9c3f4c63d9ed465c433f1cb9e2
cryptography==42.0.2 ; python_version >= "3.11" and python_version < "4.0" \ idna==3.10 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:087887e55e0b9c8724cf05361357875adb5c20dec27e5816b653492980d20380 \ --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
--hash=sha256:09a77e5b2e8ca732a19a90c5bca2d124621a1edb5438c5daa2d2738bfeb02589 \ --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
--hash=sha256:130c0f77022b2b9c99d8cebcdd834d81705f61c68e91ddd614ce74c657f8b3ea \ marshmallow==4.0.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65 \ --hash=sha256:3b6e80aac299a7935cfb97ed01d1854fb90b5079430969af92118ea1b12a8d55 \
--hash=sha256:28cb2c41f131a5758d6ba6a0504150d644054fd9f3203a1e8e8d7ac3aea7f73a \ --hash=sha256:e7b0528337e9990fd64950f8a6b3a1baabed09ad17a0dfb844d701151f92d203
--hash=sha256:2f9f14185962e6a04ab32d1abe34eae8a9001569ee4edb64d2304bf0d65c53f3 \ python-dotenv==1.1.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008 \ --hash=sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5 \
--hash=sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1 \ --hash=sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d
--hash=sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2 \ requests==2.32.3 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
--hash=sha256:4383b47f45b14459cab66048d384614019965ba6c1a1a141f11b5a551cace1b2 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
--hash=sha256:44c95c0e96b3cb628e8452ec060413a49002a247b2b9938989e23a2c8291fc90 \ sh==2.2.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee \ --hash=sha256:653227a7c41a284ec5302173fbc044ee817c7bad5e6e4d8d55741b9aeb9eb65b \
--hash=sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a \ --hash=sha256:e0b15b4ae8ffcd399bc8ffddcbd770a43c7a70a24b16773fbb34c001ad5d52af
--hash=sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242 \
--hash=sha256:5ef9bc3d046ce83c4bbf4c25e1e0547b9c441c01d30922d812e887dc5f125c12 \
--hash=sha256:5fa82a26f92871eca593b53359c12ad7949772462f887c35edaf36f87953c0e2 \
--hash=sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d \
--hash=sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be \
--hash=sha256:841ec8af7a8491ac76ec5a9522226e287187a3107e12b7d686ad354bb78facee \
--hash=sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6 \
--hash=sha256:8e88bb9eafbf6a4014d55fb222e7360eef53e613215085e65a13290577394529 \
--hash=sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929 \
--hash=sha256:a047682d324ba56e61b7ea7c7299d51e61fd3bca7dad2ccc39b72bd0118d60a1 \
--hash=sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6 \
--hash=sha256:ad28cff53f60d99a928dfcf1e861e0b2ceb2bc1f08a074fdd601b314e1cc9e0a \
--hash=sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446 \
--hash=sha256:b97fe7d7991c25e6a31e5d5e795986b18fbbb3107b873d5f3ae6dc9a103278e9 \
--hash=sha256:e0ec52ba3c7f1b7d813cd52649a5b3ef1fc0d433219dc8c93827c57eab6cf888 \
--hash=sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4 \
--hash=sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33 \
--hash=sha256:fbeb725c9dc799a574518109336acccaf1303c30d45c075c665c0793c2f79a7f
distlib==0.3.8 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 \
--hash=sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64
dulwich==0.21.7 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0fc3078a1ba04c588fabb0969d3530efd5cd1ce2cf248eefb6baf7cbc15fc285 \
--hash=sha256:10893105c6566fc95bc2a67b61df7cc1e8f9126d02a1df6a8b2b82eb59db8ab9 \
--hash=sha256:12d61334a575474e707614f2e93d6ed4cdae9eb47214f9277076d9e5615171d3 \
--hash=sha256:2590e9b431efa94fc356ae33b38f5e64f1834ec3a94a6ac3a64283b206d07aa3 \
--hash=sha256:25c3ab8fb2e201ad2031ddd32e4c68b7c03cb34b24a5ff477b7a7dcef86372f5 \
--hash=sha256:274c18ec3599a92a9b67abaf110e4f181a4f779ee1aaab9e23a72e89d71b2bd9 \
--hash=sha256:29bb5c1d70eba155ded41ed8a62be2f72edbb3c77b08f65b89c03976292f6d1b \
--hash=sha256:2bc12697f0918bee324c18836053644035362bb3983dc1b210318f2fed1d7132 \
--hash=sha256:2e2c66888207b71cd1daa2acb06d3984a6bc13787b837397a64117aa9fc5936a \
--hash=sha256:404b8edeb3c3a86c47c0a498699fc064c93fa1f8bab2ffe919e8ab03eafaaad3 \
--hash=sha256:40dcbd29ba30ba2c5bfbab07a61a5f20095541d5ac66d813056c122244df4ac0 \
--hash=sha256:460b3849d5c3d3818a80743b4f7a0094c893c559f678e56a02fff570b49a644a \
--hash=sha256:460ba74bdb19f8d498786ae7776745875059b1178066208c0fd509792d7f7bfc \
--hash=sha256:4637cbd8ed1012f67e1068aaed19fcc8b649bcf3e9e26649826a303298c89b9d \
--hash=sha256:471305af74790827fcbafe330fc2e8bdcee4fb56ca1177c8c481b1c8f806c4a4 \
--hash=sha256:4a043b90958cec866b4edc6aef5fe3c2c96a664d0b357e1682a46f6c477273c4 \
--hash=sha256:4b09bc3a64fb70132ec14326ecbe6e0555381108caff3496898962c4136a48c6 \
--hash=sha256:4bc4c5366eaf26dda3fdffe160a3b515666ed27c2419f1d483da285ac1411de0 \
--hash=sha256:4c51058ec4c0b45dc5189225b9e0c671b96ca9713c1daf71d622c13b0ab07681 \
--hash=sha256:4f18f0a311fb7734b033a3101292b932158cade54b74d1c44db519e42825e5a2 \
--hash=sha256:61e3451bd3d3844f2dca53f131982553be4d1b1e1ebd9db701843dd76c4dba31 \
--hash=sha256:62bfb26bdce869cd40be443dfd93143caea7089b165d2dcc33de40f6ac9d812a \
--hash=sha256:675a612ce913081beb0f37b286891e795d905691dfccfb9bf73721dca6757cde \
--hash=sha256:6bd69921fdd813b7469a3c77bc75c1783cc1d8d72ab15a406598e5a3ba1a1503 \
--hash=sha256:6c589468e5c0cd84e97eb7ec209ab005a2cb69399e8c5861c3edfe38989ac3a8 \
--hash=sha256:6de6f8de4a453fdbae8062a6faa652255d22a3d8bce0cd6d2d6701305c75f2b3 \
--hash=sha256:739b191f61e1c4ce18ac7d520e7a7cbda00e182c3489552408237200ce8411ad \
--hash=sha256:74700e4c7d532877355743336c36f51b414d01e92ba7d304c4f8d9a5946dbc81 \
--hash=sha256:7836da3f4110ce684dcd53489015fb7fa94ed33c5276e3318b8b1cbcb5b71e08 \
--hash=sha256:7bca4b86e96d6ef18c5bc39828ea349efb5be2f9b1f6ac9863f90589bac1084d \
--hash=sha256:7d8ab29c660125db52106775caa1f8f7f77a69ed1fe8bc4b42bdf115731a25bf \
--hash=sha256:808e8b9cc0aa9ac74870b49db4f9f39a52fb61694573f84b9c0613c928d4caf8 \
--hash=sha256:817822f970e196e757ae01281ecbf21369383285b9f4a83496312204cf889b8c \
--hash=sha256:8278835e168dd097089f9e53088c7a69c6ca0841aef580d9603eafe9aea8c358 \
--hash=sha256:858842b30ad6486aacaa607d60bab9c9a29e7c59dc2d9cb77ae5a94053878c08 \
--hash=sha256:869eb7be48243e695673b07905d18b73d1054a85e1f6e298fe63ba2843bb2ca1 \
--hash=sha256:8869fc8ec3dda743e03d06d698ad489b3705775fe62825e00fa95aa158097fc0 \
--hash=sha256:8929c37986c83deb4eb500c766ee28b6670285b512402647ee02a857320e377c \
--hash=sha256:a0650ec77d89cb947e3e4bbd4841c96f74e52b4650830112c3057a8ca891dc2f \
--hash=sha256:a7b5624b02ef808cdc62dabd47eb10cd4ac15e8ac6df9e2e88b6ac6b40133673 \
--hash=sha256:a9e9c66833cea580c3ac12927e4b9711985d76afca98da971405d414de60e968 \
--hash=sha256:b0d2e4485b98695bf95350ce9d38b1bb0aaac2c34ad00a0df789aa33c934469b \
--hash=sha256:c01a735b9a171dcb634a97a3cec1b174cfbfa8e840156870384b633da0460f18 \
--hash=sha256:c3a539b4696a42fbdb7412cb7b66a4d4d332761299d3613d90a642923c7560e1 \
--hash=sha256:c3d1685f320907a52c40fd5890627945c51f3a5fa4bcfe10edb24fec79caadec \
--hash=sha256:c92e72c43c9e9e936b01a57167e0ea77d3fd2d82416edf9489faa87278a1cdf7 \
--hash=sha256:cc1e11be527ac06316539b57a7688bcb1b6a3e53933bc2f844397bc50734e9ae \
--hash=sha256:ce8db196e79c1f381469410d26fb1d8b89c6b87a4e7f00ff418c22a35121405c \
--hash=sha256:d05d3c781bc74e2c2a2a8f4e4e2ed693540fbe88e6ac36df81deac574a6dad99 \
--hash=sha256:d097e963eb6b9fa53266146471531ad9c6765bf390849230311514546ed64db2 \
--hash=sha256:d4a2d76c96426e791556836ef43542b639def81be4f1d6d4322cd886c115eae1 \
--hash=sha256:d4c0110798099bb7d36a110090f2688050703065448895c4f53ade808d889dd3 \
--hash=sha256:d54c9d0e845be26f65f954dff13a1cd3f2b9739820c19064257b8fd7435ab263 \
--hash=sha256:d5882e70b74ac3c736a42d3fdd4f5f2e6570637f59ad5d3e684760290b58f041 \
--hash=sha256:d62446797163317a397a10080c6397ffaaca51a7804c0120b334f8165736c56a \
--hash=sha256:d96ca5e0dde49376fbcb44f10eddb6c30284a87bd03bb577c59bb0a1f63903fa \
--hash=sha256:e0064363bd5e814359657ae32517fa8001e8573d9d040bd997908d488ab886ed \
--hash=sha256:e138d516baa6b5bafbe8f030eccc544d0d486d6819b82387fc0e285e62ef5261 \
--hash=sha256:e1957b65f96e36c301e419d7adaadcff47647c30eb072468901bb683b1000bc5 \
--hash=sha256:e25953c7acbbe4e19650d0225af1c0c0e6882f8bddd2056f75c1cc2b109b88ad \
--hash=sha256:e274cebaf345f0b1e3b70197f2651de92b652386b68020cfd3bf61bc30f6eaaa \
--hash=sha256:e598d743c6c0548ebcd2baf94aa9c8bfacb787ea671eeeb5828cfbd7d56b552f \
--hash=sha256:e84cc606b1f581733df4350ca4070e6a8b30be3662bbb81a590b177d0c996c91 \
--hash=sha256:ecd315847dea406a4decfa39d388a2521e4e31acde3bd9c2609c989e817c6d62 \
--hash=sha256:ed60d1f610ef6437586f7768254c2a93820ccbd4cfdac7d182cf2d6e615969bb \
--hash=sha256:f34bf9b9fa9308376263fd9ac43143c7c09da9bc75037bb75c6c2423a151b92c \
--hash=sha256:f6c88acb60a1f4d31bd6d13bfba465853b3df940ee4a0f2a3d6c7a0778c705b7 \
--hash=sha256:fa4d14767cf7a49c9231c2e52cb2a3e90d0c83f843eb6a2ca2b5d81d254cf6b9 \
--hash=sha256:ffc27fb063f740712e02b4d2f826aee8bbed737ed799962fef625e2ce56e2d29
environs==10.3.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:cc421ddb143fa30183568164755aa113a160e555cd19e97e664c478662032c24 \
--hash=sha256:feeaf28f17fd0499f9cd7c0fcf408c6d82c308e69e335eb92d09322fc9ed8138
fastjsonschema==2.19.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0 \
--hash=sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d
filelock==3.13.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e \
--hash=sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c
idna==3.6 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
--hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
importlib-metadata==7.0.1 ; python_version >= "3.11" and python_version < "3.12" \
--hash=sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e \
--hash=sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc
installer==0.7.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53 \
--hash=sha256:a26d3e3116289bb08216e0d0f7d925fcef0b0194eedfa0c944bcaaa106c4b631
jaraco-classes==3.3.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:86b534de565381f6b3c1c830d13f931d7be1a75f0081c57dff615578676e2206 \
--hash=sha256:cb28a5ebda8bc47d8c8015307d93163464f9f2b91ab4006e09ff0ce07e8bfb30
jeepney==0.8.0 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "linux" \
--hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \
--hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755
keyring==24.3.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:4446d35d636e6a10b8bce7caa66913dd9eca5fd222ca03a3d42c38608ac30836 \
--hash=sha256:e730ecffd309658a08ee82535a3b5ec4b4c8669a9be11efb66249d8e0aeb9a25
marshmallow==3.20.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:4c1daff273513dc5eb24b219a8035559dc573c8f322558ef85f5438ddd1236dd \
--hash=sha256:c21d4b98fee747c130e6bc8f45c4b3199ea66bc00c12ee1f639f0aeca034d5e9
more-itertools==10.2.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684 \
--hash=sha256:8fccb480c43d3e99a00087634c06dd02b0d50fbf088b380de5a41a015ec239e1
msgpack==1.0.7 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862 \
--hash=sha256:0bfdd914e55e0d2c9e1526de210f6fe8ffe9705f2b1dfcc4aecc92a4cb4b533d \
--hash=sha256:1dc93e8e4653bdb5910aed79f11e165c85732067614f180f70534f056da97db3 \
--hash=sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672 \
--hash=sha256:235a31ec7db685f5c82233bddf9858748b89b8119bf4538d514536c485c15fe0 \
--hash=sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9 \
--hash=sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee \
--hash=sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46 \
--hash=sha256:36e17c4592231a7dbd2ed09027823ab295d2791b3b1efb2aee874b10548b7524 \
--hash=sha256:384d779f0d6f1b110eae74cb0659d9aa6ff35aaf547b3955abf2ab4c901c4819 \
--hash=sha256:38949d30b11ae5f95c3c91917ee7a6b239f5ec276f271f28638dec9156f82cfc \
--hash=sha256:3967e4ad1aa9da62fd53e346ed17d7b2e922cba5ab93bdd46febcac39be636fc \
--hash=sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1 \
--hash=sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82 \
--hash=sha256:484ae3240666ad34cfa31eea7b8c6cd2f1fdaae21d73ce2974211df099a95d81 \
--hash=sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6 \
--hash=sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d \
--hash=sha256:4e71bc4416de195d6e9b4ee93ad3f2f6b2ce11d042b4d7a7ee00bbe0358bd0c2 \
--hash=sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c \
--hash=sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87 \
--hash=sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84 \
--hash=sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e \
--hash=sha256:5b6ccc0c85916998d788b295765ea0e9cb9aac7e4a8ed71d12e7d8ac31c23c95 \
--hash=sha256:5ed82f5a7af3697b1c4786053736f24a0efd0a1b8a130d4c7bfee4b9ded0f08f \
--hash=sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b \
--hash=sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93 \
--hash=sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf \
--hash=sha256:822ea70dc4018c7e6223f13affd1c5c30c0f5c12ac1f96cd8e9949acddb48a61 \
--hash=sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c \
--hash=sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8 \
--hash=sha256:8dd178c4c80706546702c59529ffc005681bd6dc2ea234c450661b205445a34d \
--hash=sha256:8f5b234f567cf76ee489502ceb7165c2a5cecec081db2b37e35332b537f8157c \
--hash=sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4 \
--hash=sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba \
--hash=sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415 \
--hash=sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee \
--hash=sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d \
--hash=sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9 \
--hash=sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075 \
--hash=sha256:bfef2bb6ef068827bbd021017a107194956918ab43ce4d6dc945ffa13efbc25f \
--hash=sha256:cab3db8bab4b7e635c1c97270d7a4b2a90c070b33cbc00c99ef3f9be03d3e1f7 \
--hash=sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681 \
--hash=sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329 \
--hash=sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1 \
--hash=sha256:dc43f1ec66eb8440567186ae2f8c447d91e0372d793dfe8c222aec857b81a8cf \
--hash=sha256:dd632777ff3beaaf629f1ab4396caf7ba0bdd075d948a69460d13d44357aca4c \
--hash=sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5 \
--hash=sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b \
--hash=sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5 \
--hash=sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e \
--hash=sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b \
--hash=sha256:f26a07a6e877c76a88e3cecac8531908d980d3d5067ff69213653649ec0f60ad \
--hash=sha256:f64e376cd20d3f030190e8c32e1c64582eba56ac6dc7d5b0b49a9d44021b52fd \
--hash=sha256:f6ffbc252eb0d229aeb2f9ad051200668fc3a9aaa8994e49f0cb2ffe2b7867e7 \
--hash=sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002 \
--hash=sha256:ff1d0899f104f3921d94579a5638847f783c9b04f2d5f229392ca77fba5b82fc
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
pexpect==4.9.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523 \
--hash=sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f
pkginfo==1.9.6 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546 \
--hash=sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046
platformdirs==3.11.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3 \
--hash=sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e
poetry-core==1.8.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:194832b24f3283e01c5402eae71a6aae850ecdfe53f50a979c76bf7aa5010ffa \
--hash=sha256:67a76c671da2a70e55047cddda83566035b701f7e463b32a2abfeac6e2a16376
poetry-plugin-export==1.6.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:091939434984267a91abf2f916a26b00cff4eee8da63ec2a24ba4b17cf969a59 \
--hash=sha256:2dce6204c9318f1f6509a11a03921fb3f461b201840b59f1c237b6ab454dabcf
poetry==1.7.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:03d3807a0fb3bc1028cc3707dfd646aae629d58e476f7e7f062437680741c561 \
--hash=sha256:b348a70e7d67ad9c0bd3d0ea255bc6df84c24cf4b16f8d104adb30b425d6ff32
ptyprocess==0.7.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \
--hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220
pycparser==2.21 ; python_version >= "3.11" and python_version < "4.0" and (platform_python_implementation != "PyPy" or sys_platform == "darwin") \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
pymysql[rsa]==1.1.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:4f13a7df8bf36a51e81dd9f3605fede45a4878fe02f9236349fd82a3f0612f96 \
--hash=sha256:8969ec6d763c856f7073c4c64662882675702efcb114b4bcbb955aea3a069fa7
pyproject-hooks==1.0.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8 \
--hash=sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5
python-dotenv==1.0.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
--hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
pywin32-ctypes==0.2.2 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "win32" \
--hash=sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60 \
--hash=sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7
rapidfuzz==3.6.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:01835d02acd5d95c1071e1da1bb27fe213c84a013b899aba96380ca9962364bc \
--hash=sha256:01eb03cd880a294d1bf1a583fdd00b87169b9cc9c9f52587411506658c864d73 \
--hash=sha256:03f73b381bdeccb331a12c3c60f1e41943931461cdb52987f2ecf46bfc22f50d \
--hash=sha256:0402f1629e91a4b2e4aee68043a30191e5e1b7cd2aa8dacf50b1a1bcf6b7d3ab \
--hash=sha256:060bd7277dc794279fa95522af355034a29c90b42adcb7aa1da358fc839cdb11 \
--hash=sha256:064c1d66c40b3a0f488db1f319a6e75616b2e5fe5430a59f93a9a5e40a656d15 \
--hash=sha256:06e98ff000e2619e7cfe552d086815671ed09b6899408c2c1b5103658261f6f3 \
--hash=sha256:08b6fb47dd889c69fbc0b915d782aaed43e025df6979b6b7f92084ba55edd526 \
--hash=sha256:0a9fc714b8c290261669f22808913aad49553b686115ad0ee999d1cb3df0cd66 \
--hash=sha256:0bbfae35ce4de4c574b386c43c78a0be176eeddfdae148cb2136f4605bebab89 \
--hash=sha256:12ff8eaf4a9399eb2bebd838f16e2d1ded0955230283b07376d68947bbc2d33d \
--hash=sha256:1936d134b6c513fbe934aeb668b0fee1ffd4729a3c9d8d373f3e404fbb0ce8a0 \
--hash=sha256:1c47d592e447738744905c18dda47ed155620204714e6df20eb1941bb1ba315e \
--hash=sha256:1dfc557c0454ad22382373ec1b7df530b4bbd974335efe97a04caec936f2956a \
--hash=sha256:1e12319c6b304cd4c32d5db00b7a1e36bdc66179c44c5707f6faa5a889a317c0 \
--hash=sha256:23de71e7f05518b0bbeef55d67b5dbce3bcd3e2c81e7e533051a2e9401354eb0 \
--hash=sha256:266dd630f12696ea7119f31d8b8e4959ef45ee2cbedae54417d71ae6f47b9848 \
--hash=sha256:2963f4a3f763870a16ee076796be31a4a0958fbae133dbc43fc55c3968564cf5 \
--hash=sha256:2a791168e119cfddf4b5a40470620c872812042f0621e6a293983a2d52372db0 \
--hash=sha256:2b155e67fff215c09f130555002e42f7517d0ea72cbd58050abb83cb7c880cec \
--hash=sha256:2b19795b26b979c845dba407fe79d66975d520947b74a8ab6cee1d22686f7967 \
--hash=sha256:2e03038bfa66d2d7cffa05d81c2f18fd6acbb25e7e3c068d52bb7469e07ff382 \
--hash=sha256:3028ee8ecc48250607fa8a0adce37b56275ec3b1acaccd84aee1f68487c8557b \
--hash=sha256:35660bee3ce1204872574fa041c7ad7ec5175b3053a4cb6e181463fc07013de7 \
--hash=sha256:3c772d04fb0ebeece3109d91f6122b1503023086a9591a0b63d6ee7326bd73d9 \
--hash=sha256:3c84294f4470fcabd7830795d754d808133329e0a81d62fcc2e65886164be83b \
--hash=sha256:40cced1a8852652813f30fb5d4b8f9b237112a0bbaeebb0f4cc3611502556764 \
--hash=sha256:4243a9c35667a349788461aae6471efde8d8800175b7db5148a6ab929628047f \
--hash=sha256:42f211e366e026de110a4246801d43a907cd1a10948082f47e8a4e6da76fef52 \
--hash=sha256:4381023fa1ff32fd5076f5d8321249a9aa62128eb3f21d7ee6a55373e672b261 \
--hash=sha256:484759b5dbc5559e76fefaa9170147d1254468f555fd9649aea3bad46162a88b \
--hash=sha256:49b9ed2472394d306d5dc967a7de48b0aab599016aa4477127b20c2ed982dbf9 \
--hash=sha256:53251e256017e2b87f7000aee0353ba42392c442ae0bafd0f6b948593d3f68c6 \
--hash=sha256:588c4b20fa2fae79d60a4e438cf7133d6773915df3cc0a7f1351da19eb90f720 \
--hash=sha256:5a2f3e9df346145c2be94e4d9eeffb82fab0cbfee85bd4a06810e834fe7c03fa \
--hash=sha256:5d82b9651e3d34b23e4e8e201ecd3477c2baa17b638979deeabbb585bcb8ba74 \
--hash=sha256:5dd95b6b7bfb1584f806db89e1e0c8dbb9d25a30a4683880c195cc7f197eaf0c \
--hash=sha256:692c9a50bea7a8537442834f9bc6b7d29d8729a5b6379df17c31b6ab4df948c2 \
--hash=sha256:6b0ccc2ec1781c7e5370d96aef0573dd1f97335343e4982bdb3a44c133e27786 \
--hash=sha256:6dede83a6b903e3ebcd7e8137e7ff46907ce9316e9d7e7f917d7e7cdc570ee05 \
--hash=sha256:7142ee354e9c06e29a2636b9bbcb592bb00600a88f02aa5e70e4f230347b373e \
--hash=sha256:7183157edf0c982c0b8592686535c8b3e107f13904b36d85219c77be5cefd0d8 \
--hash=sha256:7420e801b00dee4a344ae2ee10e837d603461eb180e41d063699fb7efe08faf0 \
--hash=sha256:757dfd7392ec6346bd004f8826afb3bf01d18a723c97cbe9958c733ab1a51791 \
--hash=sha256:76c23ceaea27e790ddd35ef88b84cf9d721806ca366199a76fd47cfc0457a81b \
--hash=sha256:7fec74c234d3097612ea80f2a80c60720eec34947066d33d34dc07a3092e8105 \
--hash=sha256:82300e5f8945d601c2daaaac139d5524d7c1fdf719aa799a9439927739917460 \
--hash=sha256:841eafba6913c4dfd53045835545ba01a41e9644e60920c65b89c8f7e60c00a9 \
--hash=sha256:8d7a072f10ee57c8413c8ab9593086d42aaff6ee65df4aa6663eecdb7c398dca \
--hash=sha256:8e4da90e4c2b444d0a171d7444ea10152e07e95972bb40b834a13bdd6de1110c \
--hash=sha256:96cd19934f76a1264e8ecfed9d9f5291fde04ecb667faef5f33bdbfd95fe2d1f \
--hash=sha256:a03863714fa6936f90caa7b4b50ea59ea32bb498cc91f74dc25485b3f8fccfe9 \
--hash=sha256:a1788ebb5f5b655a15777e654ea433d198f593230277e74d51a2a1e29a986283 \
--hash=sha256:a3ee4f8f076aa92184e80308fc1a079ac356b99c39408fa422bbd00145be9854 \
--hash=sha256:a490cd645ef9d8524090551016f05f052e416c8adb2d8b85d35c9baa9d0428ab \
--hash=sha256:a553cc1a80d97459d587529cc43a4c7c5ecf835f572b671107692fe9eddf3e24 \
--hash=sha256:a59472b43879012b90989603aa5a6937a869a72723b1bf2ff1a0d1edee2cc8e6 \
--hash=sha256:ac434fc71edda30d45db4a92ba5e7a42c7405e1a54cb4ec01d03cc668c6dcd40 \
--hash=sha256:ad9d74ef7c619b5b0577e909582a1928d93e07d271af18ba43e428dc3512c2a1 \
--hash=sha256:ae598a172e3a95df3383634589660d6b170cc1336fe7578115c584a99e0ba64d \
--hash=sha256:b2ef4c0fd3256e357b70591ffb9e8ed1d439fb1f481ba03016e751a55261d7c1 \
--hash=sha256:b3e5af946f419c30f5cb98b69d40997fe8580efe78fc83c2f0f25b60d0e56efb \
--hash=sha256:b53137d81e770c82189e07a8f32722d9e4260f13a0aec9914029206ead38cac3 \
--hash=sha256:b7e3375e4f2bfec77f907680328e4cd16cc64e137c84b1886d547ab340ba6928 \
--hash=sha256:bcc957c0a8bde8007f1a8a413a632a1a409890f31f73fe764ef4eac55f59ca87 \
--hash=sha256:be156f51f3a4f369e758505ed4ae64ea88900dcb2f89d5aabb5752676d3f3d7e \
--hash=sha256:be368573255f8fbb0125a78330a1a40c65e9ba3c5ad129a426ff4289099bfb41 \
--hash=sha256:c1a23eee225dfb21c07f25c9fcf23eb055d0056b48e740fe241cbb4b22284379 \
--hash=sha256:c65f92881753aa1098c77818e2b04a95048f30edbe9c3094dc3707d67df4598b \
--hash=sha256:ca3dfcf74f2b6962f411c33dd95b0adf3901266e770da6281bc96bb5a8b20de9 \
--hash=sha256:cd4ba4c18b149da11e7f1b3584813159f189dc20833709de5f3df8b1342a9759 \
--hash=sha256:d056e342989248d2bdd67f1955bb7c3b0ecfa239d8f67a8dfe6477b30872c607 \
--hash=sha256:d2f0274595cc5b2b929c80d4e71b35041104b577e118cf789b3fe0a77b37a4c5 \
--hash=sha256:d73dcfe789d37c6c8b108bf1e203e027714a239e50ad55572ced3c004424ed3b \
--hash=sha256:d79aec8aeee02ab55d0ddb33cea3ecd7b69813a48e423c966a26d7aab025cdfe \
--hash=sha256:da3e8c9f7e64bb17faefda085ff6862ecb3ad8b79b0f618a6cf4452028aa2222 \
--hash=sha256:dad55a514868dae4543ca48c4e1fc0fac704ead038dafedf8f1fc0cc263746c1 \
--hash=sha256:dec307b57ec2d5054d77d03ee4f654afcd2c18aee00c48014cb70bfed79597d6 \
--hash=sha256:e06c4242a1354cf9d48ee01f6f4e6e19c511d50bb1e8d7d20bcadbb83a2aea90 \
--hash=sha256:e19d519386e9db4a5335a4b29f25b8183a1c3f78cecb4c9c3112e7f86470e37f \
--hash=sha256:e49b9575d16c56c696bc7b06a06bf0c3d4ef01e89137b3ddd4e2ce709af9fe06 \
--hash=sha256:ebcfb5bfd0a733514352cfc94224faad8791e576a80ffe2fd40b2177bf0e7198 \
--hash=sha256:ed0f712e0bb5fea327e92aec8a937afd07ba8de4c529735d82e4c4124c10d5a0 \
--hash=sha256:edf97c321fd641fea2793abce0e48fa4f91f3c202092672f8b5b4e781960b891 \
--hash=sha256:eef8b346ab331bec12bbc83ac75641249e6167fab3d84d8f5ca37fd8e6c7a08c \
--hash=sha256:f056ba42fd2f32e06b2c2ba2443594873cfccc0c90c8b6327904fc2ddf6d5799 \
--hash=sha256:f382f7ffe384ce34345e1c0b2065451267d3453cadde78946fbd99a59f0cc23c \
--hash=sha256:f59d19078cc332dbdf3b7b210852ba1f5db8c0a2cd8cc4c0ed84cc00c76e6802 \
--hash=sha256:fbc07e2e4ac696497c5f66ec35c21ddab3fc7a406640bffed64c26ab2f7ce6d6 \
--hash=sha256:fde9b14302a31af7bdafbf5cfbb100201ba21519be2b9dedcf4f1048e4fbe65d
requests-toolbelt==1.0.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6 \
--hash=sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06
requests==2.31.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
--hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
secretstorage==3.3.3 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "linux" \
--hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \
--hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99
sh==2.0.7 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:029d45198902bfb967391eccfd13a88d92f7cebd200411e93f99ebacc6afbb35 \
--hash=sha256:2f2f79a65abd00696cf2e9ad26508cf8abb6dba5745f40255f1c0ded2876926d
shellingham==1.5.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \
--hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de
tabulate==0.9.0 ; python_version >= "3.11" and python_version < "4.0" \ tabulate==0.9.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
--hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
tomlkit==0.12.3 ; python_version >= "3.11" and python_version < "4.0" \ urllib3==2.4.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4 \ --hash=sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466 \
--hash=sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba --hash=sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813
trove-classifiers==2024.1.31 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:854aba3358f3cf10e5c0916aa533f5a39e27aadd8ade26a54cdc2a93257e39c4 \
--hash=sha256:bfdfe60bbf64985c524416afb637ecc79c558e0beb4b7f52b0039e01044b0229
urllib3==2.2.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20 \
--hash=sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224
virtualenv==20.25.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3 \
--hash=sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b
xattr==0.10.1 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "darwin" \
--hash=sha256:042ad818cda6013162c0bfd3816f6b74b7700e73c908cde6768da824686885f8 \
--hash=sha256:0aedf55b116beb6427e6f7958ccd80a8cbc80e82f87a4cd975ccb61a8d27b2ee \
--hash=sha256:0e14bd5965d3db173d6983abdc1241c22219385c22df8b0eb8f1846c15ce1fee \
--hash=sha256:13279fe8f7982e3cdb0e088d5cb340ce9cbe5ef92504b1fd80a0d3591d662f68 \
--hash=sha256:148466e5bb168aba98f80850cf976e931469a3c6eb11e9880d9f6f8b1e66bd06 \
--hash=sha256:16a660a883e703b311d1bbbcafc74fa877585ec081cd96e8dd9302c028408ab1 \
--hash=sha256:183ad611a2d70b5a3f5f7aadef0fcef604ea33dcf508228765fd4ddac2c7321d \
--hash=sha256:199b20301b6acc9022661412346714ce764d322068ef387c4de38062474db76c \
--hash=sha256:1dc9b9f580ef4b8ac5e2c04c16b4d5086a611889ac14ecb2e7e87170623a0b75 \
--hash=sha256:1e2973e72faa87ca29d61c23b58c3c89fe102d1b68e091848b0e21a104123503 \
--hash=sha256:1f0563196ee54756fe2047627d316977dc77d11acd7a07970336e1a711e934db \
--hash=sha256:209fb84c09b41c2e4cf16dd2f481bb4a6e2e81f659a47a60091b9bcb2e388840 \
--hash=sha256:2677d40b95636f3482bdaf64ed9138fb4d8376fb7933f434614744780e46e42d \
--hash=sha256:295b3ab335fcd06ca0a9114439b34120968732e3f5e9d16f456d5ec4fa47a0a2 \
--hash=sha256:3725746a6502f40f72ef27e0c7bfc31052a239503ff3eefa807d6b02a249be22 \
--hash=sha256:3e5825b5fc99ecdd493b0cc09ec35391e7a451394fdf623a88b24726011c950d \
--hash=sha256:3e739d624491267ec5bb740f4eada93491de429d38d2fcdfb97b25efe1288eca \
--hash=sha256:3ff0dbe4a6ce2ce065c6de08f415bcb270ecfd7bf1655a633ddeac695ce8b250 \
--hash=sha256:40039f1532c4456fd0f4c54e9d4e01eb8201248c321c6c6856262d87e9a99593 \
--hash=sha256:436e1aaf23c07e15bed63115f1712d2097e207214fc6bcde147c1efede37e2c5 \
--hash=sha256:46c32cd605673606b9388a313b0050ee7877a0640d7561eea243ace4fa2cc5a6 \
--hash=sha256:475c38da0d3614cc5564467c4efece1e38bd0705a4dbecf8deeb0564a86fb010 \
--hash=sha256:485539262c2b1f5acd6b6ea56e0da2bc281a51f74335c351ea609c23d82c9a79 \
--hash=sha256:49626096ddd72dcc1654aadd84b103577d8424f26524a48d199847b5d55612d0 \
--hash=sha256:4abef557028c551d59cf2fb3bf63f2a0c89f00d77e54c1c15282ecdd56943496 \
--hash=sha256:5267e5f9435c840d2674194150b511bef929fa7d3bc942a4a75b9eddef18d8d8 \
--hash=sha256:5b49d591cf34cda2079fd7a5cb2a7a1519f54dc2e62abe3e0720036f6ed41a85 \
--hash=sha256:5bc40570155beb85e963ae45300a530223d9822edfdf09991b880e69625ba38a \
--hash=sha256:5dc6099e76e33fa3082a905fe59df766b196534c705cf7a2e3ad9bed2b8a180e \
--hash=sha256:636ebdde0277bce4d12d2ef2550885804834418fee0eb456b69be928e604ecc4 \
--hash=sha256:6b8705ac6791426559c1a5c2b88bb2f0e83dc5616a09b4500899bfff6a929302 \
--hash=sha256:6b905e808df61b677eb972f915f8a751960284358b520d0601c8cbc476ba2df6 \
--hash=sha256:7298455ccf3a922d403339781b10299b858bb5ec76435445f2da46fb768e31a5 \
--hash=sha256:772b22c4ff791fe5816a7c2a1c9fcba83f9ab9bea138eb44d4d70f34676232b4 \
--hash=sha256:7880c8a54c18bc091a4ce0adc5c6d81da1c748aec2fe7ac586d204d6ec7eca5b \
--hash=sha256:789bd406d1aad6735e97b20c6d6a1701e1c0661136be9be862e6a04564da771f \
--hash=sha256:7f9be588a4b6043b03777d50654c6079af3da60cc37527dbb80d36ec98842b1e \
--hash=sha256:80638d1ce7189dc52f26c234cee3522f060fadab6a8bc3562fe0ddcbe11ba5a4 \
--hash=sha256:8068df3ebdfa9411e58d5ae4a05d807ec5994645bb01af66ec9f6da718b65c5b \
--hash=sha256:827b5a97673b9997067fde383a7f7dc67342403093b94ea3c24ae0f4f1fec649 \
--hash=sha256:89c93b42c3ba8aedbc29da759f152731196c2492a2154371c0aae3ef8ba8301b \
--hash=sha256:8faaacf311e2b5cc67c030c999167a78a9906073e6abf08eaa8cf05b0416515c \
--hash=sha256:925284a4a28e369459b2b7481ea22840eed3e0573a4a4c06b6b0614ecd27d0a7 \
--hash=sha256:986c2305c6c1a08f78611eb38ef9f1f47682774ce954efb5a4f3715e8da00d5f \
--hash=sha256:9d4c306828a45b41b76ca17adc26ac3dc00a80e01a5ba85d71df2a3e948828f2 \
--hash=sha256:a126eb38e14a2f273d584a692fe36cff760395bf7fc061ef059224efdb4eb62c \
--hash=sha256:a3878e1aff8eca64badad8f6d896cb98c52984b1e9cd9668a3ab70294d1ef92d \
--hash=sha256:a5ea974930e876bc5c146f54ac0f85bb39b7b5de2b6fc63f90364712ae368ebe \
--hash=sha256:a606280b0c9071ef52572434ecd3648407b20df3d27af02c6592e84486b05894 \
--hash=sha256:a9a7a807ab538210ff8532220d8fc5e2d51c212681f63dbd4e7ede32543b070f \
--hash=sha256:aa32f1b45fed9122bed911de0fcc654da349e1f04fa4a9c8ef9b53e1cc98b91e \
--hash=sha256:b0e919c24f5b74428afa91507b15e7d2ef63aba98e704ad13d33bed1288dca81 \
--hash=sha256:b27dfc13b193cb290d5d9e62f806bb9a99b00cd73bb6370d556116ad7bb5dc12 \
--hash=sha256:b34df5aad035d0343bd740a95ca30db99b776e2630dca9cc1ba8e682c9cc25ea \
--hash=sha256:b7bc4ae264aa679aacf964abf3ea88e147eb4a22aea6af8c6d03ebdebd64cfd6 \
--hash=sha256:c0cd2d02ef2fb45ecf2b0da066a58472d54682c6d4f0452dfe7ae2f3a76a42ea \
--hash=sha256:c12e7d81ffaa0605b3ac8c22c2994a8e18a9cf1c59287a1b7722a2289c952ec5 \
--hash=sha256:c3024a9ff157247c8190dd0eb54db4a64277f21361b2f756319d9d3cf20e475f \
--hash=sha256:c4120090dac33eddffc27e487f9c8f16b29ff3f3f8bcb2251b2c6c3f974ca1e1 \
--hash=sha256:c5d3d0e728bace64b74c475eb4da6148cd172b2d23021a1dcd055d92f17619ac \
--hash=sha256:cc6b8d5ca452674e1a96e246a3d2db5f477aecbc7c945c73f890f56323e75203 \
--hash=sha256:ceaa26bef8fcb17eb59d92a7481c2d15d20211e217772fb43c08c859b01afc6a \
--hash=sha256:d1ef954d0655f93a34d07d0cc7e02765ec779ff0b59dc898ee08c6326ad614d5 \
--hash=sha256:d60c27922ec80310b45574351f71e0dd3a139c5295e8f8b19d19c0010196544f \
--hash=sha256:e31d062cfe1aaeab6ba3db6bd255f012d105271018e647645941d6609376af18 \
--hash=sha256:e8c014c371391f28f8cd27d73ea59f42b30772cd640b5a2538ad4f440fd9190b \
--hash=sha256:ec0956a8ab0f0d3f9011ba480f1e1271b703d11542375ef73eb8695a6bd4b78b \
--hash=sha256:f1be6e733e9698f645dbb98565bb8df9b75e80e15a21eb52787d7d96800e823b \
--hash=sha256:f24a7c04ff666d0fe905dfee0a84bc899d624aeb6dccd1ea86b5c347f15c20c1 \
--hash=sha256:f55a2dd73a12a1ae5113c5d9cd4b4ab6bf7950f4d76d0a1a0c0c4264d50da61d \
--hash=sha256:fc354f086f926a1c7f04886f97880fed1a26d20e3bc338d0d965fd161dbdb8ab \
--hash=sha256:ffcb57ca1be338d69edad93cf59aac7c6bb4dbb92fd7bf8d456c69ea42f7e6d2
zipp==3.17.0 ; python_version >= "3.11" and python_version < "3.12" \
--hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \
--hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0

512
scripts/gogo/gogo.sh Executable file
View 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 $@