Compare commits

..

No commits in common. "main" and "dev" have entirely different histories.
main ... dev

68 changed files with 313 additions and 3208 deletions

View File

@ -1,5 +0,0 @@
docker-compose.yml
.gitignore
.env
.git
.cache

1
.gitignore vendored
View File

@ -163,4 +163,3 @@ cython_debug/
# Project specific # Project specific
config.json config.json
**/dummy_platform

View File

@ -1,59 +1,10 @@
# app/Dockerfile
# pull the official docker image
FROM python:3.11-alpine as poetry-base
# default build args
ARG APP_VERSION=0.1.0 \
APP_DIR=/app \
SRC_DIR=./mgrctl \
PKG_NAME=mgrctl \
PKG_VERSION=0.1.0
# set env variables
ENV APP_NAME=mgrctl \
# Python3:
PYTHONFAULTHANDLER=1 \
PYTHONUNBUFFERED=1 \
PYTHONHASHSEED=random \
# Pip:
PIP_NO_CACHE_DIR=on \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_ROOT_USER_ACTION=ignore \
PIP_DEFAULT_TIMEOUT=100 \
# Poetry:
POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_CREATE=false \
POETRY_CACHE_DIR='/var/cache/pypoetry' \
POETRY_HOME='/usr/local' \
POETRY_VERSION=1.7.1
# install system deps
RUN apk --no-cache add curl \
&& curl -sSL https://install.python-poetry.org | python3 - \
&& mkdir ${APP_DIR}
COPY ./pyproject.toml ./poetry.lock ./README.md ${APP_DIR}
COPY ${SRC_DIR} ${APP_DIR}/${PKG_NAME}
# set workdir
WORKDIR ${APP_DIR}
# build pkg whl
RUN poetry build --format wheel \
&& pip install ${APP_DIR}/dist/${PKG_NAME}-${PKG_VERSION}-py3-none-any.whl \
&& rm -r /usr/local/venv
# now multistage builds
FROM python:3.11-alpine FROM python:3.11-alpine
# copy app and dependences WORKDIR /app
COPY --from=poetry-base /usr/local/ /usr/local/
# install bash and mgrctl shell completion COPY requirements.txt ./
RUN apk --no-cache add bash \ RUN pip install --no-cache-dir --root-user-action=ignore -r requirements.txt
&& echo 'eval "$(_MGRCTL_COMPLETE=bash_source mgrctl)"' > ~/.bashrc
# "demonize" container COPY main.py .
# use docker attach mgrctl or docker exec -it mgrctl mgrctl --help for example
CMD [ "bash"] CMD [ "python", "-u", "main.py" ]

View File

@ -1,13 +0,0 @@
build:
python3 ./scripts/devtools/dev.py builder docker-compose build
destroy:
python3 ./scripts/devtools/dev.py builder docker-compose destroy
up:
python3 ./scripts/devtools/dev.py runner docker-compose up
down:
python3 ./scripts/devtools/dev.py runner docker-compose down
restart:
python3 ./scripts/devtools/dev.py runner docker-compose restart
setup: build up
.PHONY: exec setup build

174
README.md
View File

@ -5,176 +5,4 @@ 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

@ -1,60 +0,0 @@
# ? docker-compose.yml for development environment
# ! To start development you need to create a directory ./dummy_platform.
# ? Place files from the test platform into it:
# ? VM6:
# ? ./dummy_platform/opt/ispsystem/vm/config.json - configuration file
# ? ./dummy_platform/opt/ispsystem/vm/mysql - database directory
# ? DCI6:
# ? ./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:
# ? PLATFORM_TYPE='vm'
# ? Database container:
# ? MYSQL_DATABASE="database name"
# ? MYSQL_ROOT_PASSWORD="super secret password from config.json"
# ? Launch:
# ? docker-compose up -d --force-recreate
# ? docker attach mgrctl
services:
mgrctl:
container_name: mgrctl
restart: unless-stopped
build:
context: .
args:
- APP_VERSION=${APP_VERSION}
- APP_DIR=${APP_DIR}
- SRC_DIR=${SRC_DIR}
- PKG_NAME=${PKG_NAME}
- PKG_VERSION=${PKG_VERSION}
networks:
vm_box_net: null
volumes:
- type: bind
source: ./dummy_platform/opt/ispsystem/${PLATFORM_TYPE}/config.json
target: /opt/ispsystem/${PLATFORM_TYPE}/config.json
env_file:
- ./.env
tty: true
stdin_open: true
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:
vm_box_net:
name: vm_box_net
driver: bridge

View File

@ -0,0 +1,12 @@
import click
@click.group(help='access command for lazy example')
@click.option('--debug/--no-debug', default=False)
def cli(debug):
click.echo(f"Debug mode is {'on' if debug else 'off'}")
@cli.command()
def enable():
click.echo('Access granted')

View File

@ -0,0 +1,13 @@
import click
from core.cli.lazy_group import LazyGroup
from settings.general import INSTALLED_APPS
@click.group(
cls=LazyGroup,
lazy_subcommands=INSTALLED_APPS['dci6'],
help='dci6 command for lazy example',
)
def cli():
pass

View File

@ -0,0 +1,12 @@
import click
@click.group(help='access command for lazy example')
@click.option('--debug/--no-debug', default=False)
def cli(debug):
click.echo(f"Debug mode is {'on' if debug else 'off'}")
@cli.command()
def enable():
click.echo('Access granted')

View File

@ -0,0 +1,12 @@
import click
from core.cli.lazy_group import LazyGroup
from settings.general import INSTALLED_APPS
@click.group(
cls=LazyGroup,
lazy_subcommands=INSTALLED_APPS['vm6'],
help='vm6 command for lazy example',
)
def cli():
pass

View File

@ -0,0 +1,13 @@
import click
@click.group(help='nodes command for lazy example')
def cli():
pass
@cli.command(name='list')
def nodes_list():
click.echo('NODES LIST: etc...')
for num in range(1, 10):
click.echo(num)

View File

View File

View File

View File

@ -0,0 +1,6 @@
class UnknownField(object):
def __init__(self, *_, **__): pass
class BaseModel(Model):
class Meta:
database = db

View File

View File

@ -1,24 +1,11 @@
from peewee import ( 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 UnknownField(object):
def __init__(self, *_, **__): pass
class BaseModel(Model): class BaseModel(Model):
class Meta: class Meta:
database = auth_database database = database
class AlertSetting(BaseModel): class AlertSetting(BaseModel):
channel = UnknownField(null=True) # json channel = UnknownField(null=True) # json
@ -30,7 +17,6 @@ class AlertSetting(BaseModel):
class Meta: class Meta:
table_name = 'alert_setting' table_name = 'alert_setting'
class AuthAcl(BaseModel): class AuthAcl(BaseModel):
ip_list = UnknownField() # json ip_list = UnknownField() # json
name = CharField(constraints=[SQL("DEFAULT ''")], unique=True) name = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
@ -38,7 +24,6 @@ class AuthAcl(BaseModel):
class Meta: class Meta:
table_name = 'auth_acl' table_name = 'auth_acl'
class AuthUser(BaseModel): class AuthUser(BaseModel):
auth_source = CharField(constraints=[SQL("DEFAULT 'local'")]) auth_source = CharField(constraints=[SQL("DEFAULT 'local'")])
avatar = TextField(null=True) avatar = TextField(null=True)
@ -65,23 +50,15 @@ class AuthUser(BaseModel):
class Meta: class Meta:
table_name = 'auth_user' table_name = 'auth_user'
class AuthConfirmToken(BaseModel): class AuthConfirmToken(BaseModel):
expires_at = DateTimeField(null=True) expires_at = DateTimeField(null=True)
resend_token_after = DateTimeField(null=True) resend_token_after = DateTimeField(null=True)
token = CharField(null=True, unique=True) token = CharField(null=True, unique=True)
user = ForeignKeyField( user = ForeignKeyField(column_name='user', field='id', model=AuthUser, null=True, unique=True)
column_name='user',
field='id',
model=AuthUser,
null=True,
unique=True
)
class Meta: class Meta:
table_name = 'auth_confirm_token' table_name = 'auth_confirm_token'
class AuthGdprDoc(BaseModel): class AuthGdprDoc(BaseModel):
change_date = DateTimeField(null=True) change_date = DateTimeField(null=True)
desc_condition = CharField(null=True) desc_condition = CharField(null=True)
@ -95,23 +72,16 @@ class AuthGdprDoc(BaseModel):
class Meta: class Meta:
table_name = 'auth_gdpr_doc' table_name = 'auth_gdpr_doc'
class AuthGdprJournal(BaseModel): class AuthGdprJournal(BaseModel):
action_date = DateTimeField(null=True) action_date = DateTimeField(null=True)
action_type = CharField() action_type = CharField()
doc = ForeignKeyField( doc = ForeignKeyField(column_name='doc', field='id', model=AuthGdprDoc, null=True)
column_name='doc',
field='id',
model=AuthGdprDoc,
null=True
)
ip = CharField(null=True) ip = CharField(null=True)
user_email = CharField() user_email = CharField()
class Meta: class Meta:
table_name = 'auth_gdpr_journal' table_name = 'auth_gdpr_journal'
class AuthGeneratedSshkey(BaseModel): class AuthGeneratedSshkey(BaseModel):
generation_date = DateTimeField(null=True) generation_date = DateTimeField(null=True)
privkey = TextField(null=True) privkey = TextField(null=True)
@ -120,7 +90,6 @@ class AuthGeneratedSshkey(BaseModel):
class Meta: class Meta:
table_name = 'auth_generated_sshkey' table_name = 'auth_generated_sshkey'
class AuthProduct(BaseModel): class AuthProduct(BaseModel):
docker_compose_file = TextField(null=True) docker_compose_file = TextField(null=True)
name = CharField(null=True) name = CharField(null=True)
@ -133,7 +102,6 @@ class AuthProduct(BaseModel):
(('name', 'version'), True), (('name', 'version'), True),
) )
class AuthInstance(BaseModel): class AuthInstance(BaseModel):
conn_params = UnknownField(null=True) # json conn_params = UnknownField(null=True) # json
dbkey = TextField(null=True) dbkey = TextField(null=True)
@ -141,18 +109,8 @@ class AuthInstance(BaseModel):
failure_reason = UnknownField(null=True) # json failure_reason = UnknownField(null=True) # json
limits = UnknownField(null=True) # json limits = UnknownField(null=True) # json
name = CharField(null=True) name = CharField(null=True)
owner = ForeignKeyField( owner = ForeignKeyField(column_name='owner', field='id', model=AuthUser, null=True)
column_name='owner', product = ForeignKeyField(column_name='product', field='id', model=AuthProduct, null=True)
field='id',
model=AuthUser,
null=True
)
product = ForeignKeyField(
column_name='product',
field='id',
model=AuthProduct,
null=True
)
roles = UnknownField(null=True) # json roles = UnknownField(null=True) # json
started = DateTimeField(null=True) started = DateTimeField(null=True)
status = CharField() status = CharField()
@ -160,18 +118,12 @@ class AuthInstance(BaseModel):
class Meta: class Meta:
table_name = 'auth_instance' table_name = 'auth_instance'
class AuthInstanceHistory(BaseModel): class AuthInstanceHistory(BaseModel):
create_time = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")]) create_time = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")])
event_info = UnknownField(null=True) # json event_info = UnknownField(null=True) # json
event_type = CharField(null=True) event_type = CharField(null=True)
prev_time = DateTimeField(null=True) prev_time = DateTimeField(null=True)
ref = ForeignKeyField( ref = ForeignKeyField(column_name='ref', field='id', model=AuthInstance, null=True)
column_name='ref',
field='id',
model=AuthInstance,
null=True
)
request_id = CharField(null=True) request_id = CharField(null=True)
request_ip = CharField(null=True) request_ip = CharField(null=True)
request_owner = CharField(null=True) request_owner = CharField(null=True)
@ -180,7 +132,6 @@ class AuthInstanceHistory(BaseModel):
class Meta: class Meta:
table_name = 'auth_instance_history' table_name = 'auth_instance_history'
class AuthKey(BaseModel): class AuthKey(BaseModel):
expires_at = DateTimeField(null=True) expires_at = DateTimeField(null=True)
name = CharField(constraints=[SQL("DEFAULT ''")], unique=True) name = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
@ -189,15 +140,8 @@ class AuthKey(BaseModel):
class Meta: class Meta:
table_name = 'auth_key' table_name = 'auth_key'
class AuthLicense(BaseModel): class AuthLicense(BaseModel):
instance = ForeignKeyField( instance = ForeignKeyField(column_name='instance', field='id', model=AuthInstance, null=True, unique=True)
column_name='instance',
field='id',
model=AuthInstance,
null=True,
unique=True
)
last_update = DateTimeField(null=True) last_update = DateTimeField(null=True)
lic_data = UnknownField(null=True) # json lic_data = UnknownField(null=True) # json
lic_request = UnknownField(null=True) # json lic_request = UnknownField(null=True) # json
@ -208,7 +152,6 @@ class AuthLicense(BaseModel):
class Meta: class Meta:
table_name = 'auth_license' table_name = 'auth_license'
class AuthPermission(BaseModel): class AuthPermission(BaseModel):
data = UnknownField() # json data = UnknownField() # json
plugin = CharField(constraints=[SQL("DEFAULT ''")]) plugin = CharField(constraints=[SQL("DEFAULT ''")])
@ -220,7 +163,6 @@ class AuthPermission(BaseModel):
(('service', 'plugin'), True), (('service', 'plugin'), True),
) )
class AuthPricelist(BaseModel): class AuthPricelist(BaseModel):
bill_id = IntegerField(null=True, unique=True) bill_id = IntegerField(null=True, unique=True)
name = CharField(null=True) name = CharField(null=True)
@ -229,7 +171,6 @@ class AuthPricelist(BaseModel):
class Meta: class Meta:
table_name = 'auth_pricelist' table_name = 'auth_pricelist'
class AuthRestrictions(BaseModel): class AuthRestrictions(BaseModel):
attempts_counting_duration = BigIntegerField() attempts_counting_duration = BigIntegerField()
attempts_max_count = IntegerField(null=True) attempts_max_count = IntegerField(null=True)
@ -240,7 +181,6 @@ class AuthRestrictions(BaseModel):
class Meta: class Meta:
table_name = 'auth_restrictions' table_name = 'auth_restrictions'
class AuthRestrictionsBans(BaseModel): class AuthRestrictionsBans(BaseModel):
banned_until = DateTimeField() banned_until = DateTimeField()
user = ForeignKeyField(column_name='user', field='id', model=AuthUser) user = ForeignKeyField(column_name='user', field='id', model=AuthUser)
@ -252,7 +192,6 @@ class AuthRestrictionsBans(BaseModel):
(('user', 'user_ip'), True), (('user', 'user_ip'), True),
) )
class AuthRole(BaseModel): class AuthRole(BaseModel):
data = UnknownField() # json data = UnknownField() # json
human_descr = CharField(null=True) human_descr = CharField(null=True)
@ -262,17 +201,10 @@ class AuthRole(BaseModel):
class Meta: class Meta:
table_name = 'auth_role' table_name = 'auth_role'
class AuthServer(BaseModel): class AuthServer(BaseModel):
demo = IntegerField(constraints=[SQL("DEFAULT 0")]) demo = IntegerField(constraints=[SQL("DEFAULT 0")])
host = CharField(null=True) host = CharField(null=True)
instance = ForeignKeyField( instance = ForeignKeyField(column_name='instance', field='id', model=AuthInstance, null=True, unique=True)
column_name='instance',
field='id',
model=AuthInstance,
null=True,
unique=True
)
login = CharField(null=True) login = CharField(null=True)
machine_id = CharField(null=True) machine_id = CharField(null=True)
password = CharField(null=True) password = CharField(null=True)
@ -284,17 +216,10 @@ class AuthServer(BaseModel):
(('host', 'port'), True), (('host', 'port'), True),
) )
class AuthService(BaseModel): class AuthService(BaseModel):
bill_id = IntegerField(null=True, unique=True) bill_id = IntegerField(null=True, unique=True)
info = UnknownField(null=True) # json info = UnknownField(null=True) # json
instance = ForeignKeyField( instance = ForeignKeyField(column_name='instance', field='id', model=AuthInstance, null=True, unique=True)
column_name='instance',
field='id',
model=AuthInstance,
null=True,
unique=True
)
params = UnknownField(null=True) # json params = UnknownField(null=True) # json
payment_form = TextField(null=True) payment_form = TextField(null=True)
status = CharField(null=True) status = CharField(null=True)
@ -305,7 +230,6 @@ class AuthService(BaseModel):
(('instance', 'bill_id'), True), (('instance', 'bill_id'), True),
) )
class AuthServiceDbkey(BaseModel): class AuthServiceDbkey(BaseModel):
dbkey = TextField(null=True) dbkey = TextField(null=True)
name = CharField(null=True, unique=True) name = CharField(null=True, unique=True)
@ -313,31 +237,18 @@ class AuthServiceDbkey(BaseModel):
class Meta: class Meta:
table_name = 'auth_service_dbkey' table_name = 'auth_service_dbkey'
class AuthSession(BaseModel): class AuthSession(BaseModel):
expires_at = DateTimeField(null=True) expires_at = DateTimeField(null=True)
is_internal = IntegerField(constraints=[SQL("DEFAULT 0")]) is_internal = IntegerField(constraints=[SQL("DEFAULT 0")])
name = CharField(null=True, unique=True) name = CharField(null=True, unique=True)
owner = ForeignKeyField( owner = ForeignKeyField(column_name='owner', field='id', model=AuthUser, null=True)
column_name='owner', trustee = ForeignKeyField(backref='auth_user_trustee_set', column_name='trustee', field='id', model=AuthUser, null=True)
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) updated_at = DateTimeField(null=True)
xsrf_token = CharField(null=True) xsrf_token = CharField(null=True)
class Meta: class Meta:
table_name = 'auth_session' table_name = 'auth_session'
class AuthToken(BaseModel): class AuthToken(BaseModel):
client_ip = CharField(null=True) client_ip = CharField(null=True)
description = CharField(constraints=[SQL("DEFAULT ''")]) description = CharField(constraints=[SQL("DEFAULT ''")])
@ -346,38 +257,16 @@ class AuthToken(BaseModel):
name = CharField(constraints=[SQL("DEFAULT ''")], unique=True) name = CharField(constraints=[SQL("DEFAULT ''")], unique=True)
need_2fa = IntegerField(constraints=[SQL("DEFAULT 0")]) need_2fa = IntegerField(constraints=[SQL("DEFAULT 0")])
owner = ForeignKeyField(column_name='owner', field='id', model=AuthUser) owner = ForeignKeyField(column_name='owner', field='id', model=AuthUser)
trustee = ForeignKeyField( trustee = ForeignKeyField(backref='auth_user_trustee_set', column_name='trustee', field='id', model=AuthUser)
backref='auth_user_trustee_set',
column_name='trustee',
field='id',
model=AuthUser
)
class Meta: class Meta:
table_name = 'auth_token' table_name = 'auth_token'
class AuthTrusteeUser(BaseModel): class AuthTrusteeUser(BaseModel):
instance = ForeignKeyField( instance = ForeignKeyField(column_name='instance', field='id', model=AuthInstance, null=True)
column_name='instance',
field='id',
model=AuthInstance,
null=True
)
role = CharField(null=True) role = CharField(null=True)
trustee = ForeignKeyField( trustee = ForeignKeyField(column_name='trustee', field='id', model=AuthUser, null=True)
column_name='trustee', user = ForeignKeyField(backref='auth_user_user_set', column_name='user', field='id', model=AuthUser, null=True)
field='id',
model=AuthUser,
null=True
)
user = ForeignKeyField(
backref='auth_user_user_set',
column_name='user',
field='id',
model=AuthUser,
null=True
)
class Meta: class Meta:
table_name = 'auth_trustee_user' table_name = 'auth_trustee_user'
@ -385,7 +274,6 @@ class AuthTrusteeUser(BaseModel):
(('user', 'trustee', 'instance'), True), (('user', 'trustee', 'instance'), True),
) )
class AuthUser2Acl(BaseModel): class AuthUser2Acl(BaseModel):
acl = ForeignKeyField(column_name='acl', field='id', model=AuthAcl) acl = ForeignKeyField(column_name='acl', field='id', model=AuthAcl)
user = ForeignKeyField(column_name='user', field='id', model=AuthUser) user = ForeignKeyField(column_name='user', field='id', model=AuthUser)
@ -396,27 +284,12 @@ class AuthUser2Acl(BaseModel):
(('user', 'acl'), True), (('user', 'acl'), True),
) )
class AuthUserRole(BaseModel): class AuthUserRole(BaseModel):
instance = ForeignKeyField( instance = ForeignKeyField(column_name='instance', field='id', model=AuthInstance, null=True)
column_name='instance',
field='id',
model=AuthInstance,
null=True
)
roles = UnknownField() # json roles = UnknownField() # json
state = CharField(constraints=[SQL("DEFAULT 'active'")]) state = CharField(constraints=[SQL("DEFAULT 'active'")])
trustee = ForeignKeyField( trustee = ForeignKeyField(column_name='trustee', field='id', model=AuthUser)
column_name='trustee', user = ForeignKeyField(backref='auth_user_user_set', column_name='user', field='id', model=AuthUser)
field='id',
model=AuthUser
)
user = ForeignKeyField(
backref='auth_user_user_set',
column_name='user',
field='id',
model=AuthUser
)
class Meta: class Meta:
table_name = 'auth_user_role' table_name = 'auth_user_role'
@ -424,21 +297,11 @@ class AuthUserRole(BaseModel):
(('user', 'trustee', 'instance'), True), (('user', 'trustee', 'instance'), True),
) )
class AuthUserSetting(BaseModel): class AuthUserSetting(BaseModel):
data = UnknownField(null=True) # json data = UnknownField(null=True) # json
instance = ForeignKeyField( instance = ForeignKeyField(column_name='instance', field='id', model=AuthInstance, null=True)
column_name='instance',
field='id',
model=AuthInstance,
null=True
)
name = CharField(null=True) name = CharField(null=True)
user = ForeignKeyField( user = ForeignKeyField(column_name='user', field='id', model=AuthUser)
column_name='user',
field='id',
model=AuthUser
)
class Meta: class Meta:
table_name = 'auth_user_setting' table_name = 'auth_user_setting'
@ -446,15 +309,9 @@ class AuthUserSetting(BaseModel):
(('user', 'name', 'instance'), True), (('user', 'name', 'instance'), True),
) )
class AuthUserSshkey(BaseModel): class AuthUserSshkey(BaseModel):
name = CharField(constraints=[SQL("DEFAULT ''")]) name = CharField(constraints=[SQL("DEFAULT ''")])
owner = ForeignKeyField( owner = ForeignKeyField(column_name='owner', field='id', model=AuthUser, null=True)
column_name='owner',
field='id',
model=AuthUser,
null=True
)
ssh_pub_key = TextField() ssh_pub_key = TextField()
class Meta: class Meta:
@ -463,7 +320,6 @@ class AuthUserSshkey(BaseModel):
(('name', 'owner'), True), (('name', 'owner'), True),
) )
class AuthUsersLocks(BaseModel): class AuthUsersLocks(BaseModel):
description = CharField(constraints=[SQL("DEFAULT ''")]) description = CharField(constraints=[SQL("DEFAULT ''")])
service_name = CharField() service_name = CharField()
@ -476,14 +332,12 @@ class AuthUsersLocks(BaseModel):
) )
primary_key = CompositeKey('service_name', 'user') primary_key = CompositeKey('service_name', 'user')
class BackupAlembicVersion(BaseModel): class BackupAlembicVersion(BaseModel):
version_num = CharField(primary_key=True) version_num = CharField(primary_key=True)
class Meta: class Meta:
table_name = 'backup_alembic_version' table_name = 'backup_alembic_version'
class BackupTask(BaseModel): class BackupTask(BaseModel):
connection_params = TextField() connection_params = TextField()
cron_expression = CharField() cron_expression = CharField()
@ -498,24 +352,17 @@ class BackupTask(BaseModel):
class Meta: class Meta:
table_name = 'backup_task' table_name = 'backup_task'
class BackupFile(BaseModel): class BackupFile(BaseModel):
date = DateTimeField() date = DateTimeField()
downloadable = IntegerField() downloadable = IntegerField()
name = CharField() name = CharField()
size = FloatField() size = FloatField()
storage_type = CharField() storage_type = CharField()
task = ForeignKeyField( task = ForeignKeyField(column_name='task', field='id', model=BackupTask, null=True)
column_name='task',
field='id',
model=BackupTask,
null=True
)
class Meta: class Meta:
table_name = 'backup_file' table_name = 'backup_file'
class CsDocuments(BaseModel): class CsDocuments(BaseModel):
lang = CharField(constraints=[SQL("DEFAULT ''")]) lang = CharField(constraints=[SQL("DEFAULT ''")])
name = CharField(constraints=[SQL("DEFAULT ''")]) name = CharField(constraints=[SQL("DEFAULT ''")])
@ -529,7 +376,6 @@ class CsDocuments(BaseModel):
(('product', 'lang', 'name'), True), (('product', 'lang', 'name'), True),
) )
class CsSettings(BaseModel): class CsSettings(BaseModel):
lang = CharField(constraints=[SQL("DEFAULT ''")]) lang = CharField(constraints=[SQL("DEFAULT ''")])
product = CharField(constraints=[SQL("DEFAULT ''")]) product = CharField(constraints=[SQL("DEFAULT ''")])
@ -542,14 +388,12 @@ class CsSettings(BaseModel):
(('product', 'lang', 'prop_key'), True), (('product', 'lang', 'prop_key'), True),
) )
class EserviceAlembicVersion(BaseModel): class EserviceAlembicVersion(BaseModel):
version_num = CharField(primary_key=True) version_num = CharField(primary_key=True)
class Meta: class Meta:
table_name = 'eservice_alembic_version' table_name = 'eservice_alembic_version'
class EserviceCustomEquipment(BaseModel): class EserviceCustomEquipment(BaseModel):
data = TextField(null=True) data = TextField(null=True)
device_type = CharField() device_type = CharField()
@ -564,7 +408,6 @@ class EserviceCustomEquipment(BaseModel):
class Meta: class Meta:
table_name = 'eservice_custom_equipment' table_name = 'eservice_custom_equipment'
class EserviceIpmiFru(BaseModel): class EserviceIpmiFru(BaseModel):
fru_info = UnknownField(null=True) # json fru_info = UnknownField(null=True) # json
ipmi_id = AutoField() ipmi_id = AutoField()
@ -573,7 +416,6 @@ class EserviceIpmiFru(BaseModel):
class Meta: class Meta:
table_name = 'eservice_ipmi_fru' table_name = 'eservice_ipmi_fru'
class EserviceIpmiInfo(BaseModel): class EserviceIpmiInfo(BaseModel):
ipmi_id = AutoField() ipmi_id = AutoField()
model = CharField() model = CharField()
@ -581,7 +423,6 @@ class EserviceIpmiInfo(BaseModel):
class Meta: class Meta:
table_name = 'eservice_ipmi_info' table_name = 'eservice_ipmi_info'
class EserviceIpmiSensors(BaseModel): class EserviceIpmiSensors(BaseModel):
ipmi_id = AutoField() ipmi_id = AutoField()
sensors_info = UnknownField(null=True) # json sensors_info = UnknownField(null=True) # json
@ -590,7 +431,6 @@ class EserviceIpmiSensors(BaseModel):
class Meta: class Meta:
table_name = 'eservice_ipmi_sensors' table_name = 'eservice_ipmi_sensors'
class IpmiProxyLocation(BaseModel): class IpmiProxyLocation(BaseModel):
docker_compose = TextField(null=True) docker_compose = TextField(null=True)
instance = IntegerField(null=True) instance = IntegerField(null=True)
@ -605,7 +445,6 @@ class IpmiProxyLocation(BaseModel):
(('instance', 'location'), True), (('instance', 'location'), True),
) )
class IpmiProxyConnection(BaseModel): class IpmiProxyConnection(BaseModel):
close_time = DateTimeField(null=True) close_time = DateTimeField(null=True)
connection_data = UnknownField(null=True) # json connection_data = UnknownField(null=True) # json
@ -613,11 +452,7 @@ class IpmiProxyConnection(BaseModel):
intel_amt = IntegerField(null=True) intel_amt = IntegerField(null=True)
ipmi = IntegerField(null=True) ipmi = IntegerField(null=True)
listen_web_port = IntegerField(null=True, unique=True) listen_web_port = IntegerField(null=True, unique=True)
location = ForeignKeyField( location = ForeignKeyField(column_name='location_id', field='id', model=IpmiProxyLocation)
column_name='location_id',
field='id',
model=IpmiProxyLocation
)
type = CharField(constraints=[SQL("DEFAULT 'web'")]) type = CharField(constraints=[SQL("DEFAULT 'web'")])
user = IntegerField(null=True) user = IntegerField(null=True)
vnc_port = IntegerField(null=True) vnc_port = IntegerField(null=True)
@ -625,7 +460,6 @@ class IpmiProxyConnection(BaseModel):
class Meta: class Meta:
table_name = 'ipmi_proxy_connection' table_name = 'ipmi_proxy_connection'
class IpmiProxyJavaAgreement(BaseModel): class IpmiProxyJavaAgreement(BaseModel):
instance = IntegerField(null=True, unique=True) instance = IntegerField(null=True, unique=True)
java_agree = IntegerField(constraints=[SQL("DEFAULT 1")]) java_agree = IntegerField(constraints=[SQL("DEFAULT 1")])
@ -633,14 +467,12 @@ class IpmiProxyJavaAgreement(BaseModel):
class Meta: class Meta:
table_name = 'ipmi_proxy_java_agreement' table_name = 'ipmi_proxy_java_agreement'
class IpmiProxyPlugin(BaseModel): class IpmiProxyPlugin(BaseModel):
instance = IntegerField(null=True, unique=True) instance = IntegerField(null=True, unique=True)
class Meta: class Meta:
table_name = 'ipmi_proxy_plugin' table_name = 'ipmi_proxy_plugin'
class IspSettings(BaseModel): class IspSettings(BaseModel):
name = CharField(primary_key=True) name = CharField(primary_key=True)
value = TextField() value = TextField()
@ -648,19 +480,15 @@ class IspSettings(BaseModel):
class Meta: class Meta:
table_name = 'isp_settings' table_name = 'isp_settings'
class JournalAlembicVersion(BaseModel): class JournalAlembicVersion(BaseModel):
version_num = CharField(primary_key=True) version_num = CharField(primary_key=True)
class Meta: class Meta:
table_name = 'journal_alembic_version' table_name = 'journal_alembic_version'
class JournalEvents(BaseModel): class JournalEvents(BaseModel):
data = UnknownField(null=True) # json data = UnknownField(null=True) # json
date_time = DateTimeField( date_time = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP(3)")])
constraints=[SQL("DEFAULT CURRENT_TIMESTAMP(3)")]
)
entity_id = IntegerField() entity_id = IntegerField()
entity_name = CharField() entity_name = CharField()
entity_owner = IntegerField() entity_owner = IntegerField()
@ -676,7 +504,6 @@ class JournalEvents(BaseModel):
class Meta: class Meta:
table_name = 'journal_events' table_name = 'journal_events'
class MsgsChannel(BaseModel): class MsgsChannel(BaseModel):
comment = TextField(null=True) comment = TextField(null=True)
creation_date = DateTimeField(null=True) creation_date = DateTimeField(null=True)
@ -690,7 +517,6 @@ class MsgsChannel(BaseModel):
class Meta: class Meta:
table_name = 'msgs_channel' table_name = 'msgs_channel'
class MsgsDeliveryMethod(BaseModel): class MsgsDeliveryMethod(BaseModel):
delivery_method = CharField(primary_key=True) delivery_method = CharField(primary_key=True)
dm_params = UnknownField(null=True) # json dm_params = UnknownField(null=True) # json
@ -698,14 +524,12 @@ class MsgsDeliveryMethod(BaseModel):
class Meta: class Meta:
table_name = 'msgs_delivery_method' table_name = 'msgs_delivery_method'
class MsgsMessageDesign(BaseModel): class MsgsMessageDesign(BaseModel):
design = CharField(primary_key=True) design = CharField(primary_key=True)
class Meta: class Meta:
table_name = 'msgs_message_design' table_name = 'msgs_message_design'
class MsgsMessageDesignVariant(BaseModel): class MsgsMessageDesignVariant(BaseModel):
delivery_method = CharField() delivery_method = CharField()
design = CharField() design = CharField()
@ -720,7 +544,6 @@ class MsgsMessageDesignVariant(BaseModel):
) )
primary_key = CompositeKey('delivery_method', 'design', 'language') primary_key = CompositeKey('delivery_method', 'design', 'language')
class MsgsNoticeReceiver(BaseModel): class MsgsNoticeReceiver(BaseModel):
delivery_method = CharField() delivery_method = CharField()
receivers = UnknownField(null=True) # json receivers = UnknownField(null=True) # json
@ -732,7 +555,6 @@ class MsgsNoticeReceiver(BaseModel):
(('user', 'delivery_method'), True), (('user', 'delivery_method'), True),
) )
class MsgsTemplate(BaseModel): class MsgsTemplate(BaseModel):
priority = CharField() priority = CharField()
template = CharField(primary_key=True) template = CharField(primary_key=True)
@ -740,7 +562,6 @@ class MsgsTemplate(BaseModel):
class Meta: class Meta:
table_name = 'msgs_template' table_name = 'msgs_template'
class MsgsTemplate2Category(BaseModel): class MsgsTemplate2Category(BaseModel):
category = CharField() category = CharField()
template = CharField() template = CharField()
@ -753,7 +574,6 @@ class MsgsTemplate2Category(BaseModel):
) )
primary_key = CompositeKey('category', 'template') primary_key = CompositeKey('category', 'template')
class MsgsTemplateVariant(BaseModel): class MsgsTemplateVariant(BaseModel):
delivery_method = CharField() delivery_method = CharField()
language = CharField() language = CharField()
@ -768,7 +588,6 @@ class MsgsTemplateVariant(BaseModel):
) )
primary_key = CompositeKey('delivery_method', 'language', 'template') primary_key = CompositeKey('delivery_method', 'language', 'template')
class MsgsUser(BaseModel): class MsgsUser(BaseModel):
language = CharField() language = CharField()
user = AutoField() user = AutoField()
@ -776,7 +595,6 @@ class MsgsUser(BaseModel):
class Meta: class Meta:
table_name = 'msgs_user' table_name = 'msgs_user'
class MsgsUser2DeliveryMethod(BaseModel): class MsgsUser2DeliveryMethod(BaseModel):
delivery_method = CharField() delivery_method = CharField()
u2dm_params = UnknownField(null=True) # json u2dm_params = UnknownField(null=True) # json
@ -790,7 +608,6 @@ class MsgsUser2DeliveryMethod(BaseModel):
) )
primary_key = CompositeKey('delivery_method', 'user') primary_key = CompositeKey('delivery_method', 'user')
class MsgsUserSubscription(BaseModel): class MsgsUserSubscription(BaseModel):
category = CharField() category = CharField()
delivery_method = CharField() delivery_method = CharField()
@ -803,7 +620,6 @@ class MsgsUserSubscription(BaseModel):
) )
primary_key = CompositeKey('category', 'delivery_method', 'user') primary_key = CompositeKey('category', 'delivery_method', 'user')
class NcNotice(BaseModel): class NcNotice(BaseModel):
create_timestamp = IntegerField(null=True) create_timestamp = IntegerField(null=True)
entity = UnknownField(null=True) # json entity = UnknownField(null=True) # json
@ -815,7 +631,6 @@ class NcNotice(BaseModel):
class Meta: class Meta:
table_name = 'nc_notice' table_name = 'nc_notice'
class NcUser(BaseModel): class NcUser(BaseModel):
last_notice_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")]) last_notice_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")])
read_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")]) read_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")])
@ -823,21 +638,10 @@ class NcUser(BaseModel):
class Meta: class Meta:
table_name = 'nc_user' table_name = 'nc_user'
class NcNotice2User(BaseModel): class NcNotice2User(BaseModel):
notice = ForeignKeyField( notice = ForeignKeyField(column_name='notice', field='id', model=NcNotice, null=True)
column_name='notice',
field='id',
model=NcNotice,
null=True
)
read_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")]) read_timestamp = IntegerField(constraints=[SQL("DEFAULT 0")])
user = ForeignKeyField( user = ForeignKeyField(column_name='user', field='id', model=NcUser, null=True)
column_name='user',
field='id',
model=NcUser,
null=True
)
class Meta: class Meta:
table_name = 'nc_notice2user' table_name = 'nc_notice2user'
@ -845,7 +649,6 @@ class NcNotice2User(BaseModel):
(('user', 'notice'), True), (('user', 'notice'), True),
) )
class NotifierNotify(BaseModel): class NotifierNotify(BaseModel):
additional_info = UnknownField() # json additional_info = UnknownField() # json
description = UnknownField() # json description = UnknownField() # json
@ -856,16 +659,12 @@ class NotifierNotify(BaseModel):
owner = IntegerField(null=True) owner = IntegerField(null=True)
request_id = CharField(null=True) request_id = CharField(null=True)
request_ip = CharField(null=True) request_ip = CharField(null=True)
time = DateTimeField( time = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")], index=True)
constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")],
index=True
)
trustee = IntegerField(null=True) trustee = IntegerField(null=True)
class Meta: class Meta:
table_name = 'notifier_notify' table_name = 'notifier_notify'
class PsPlugin(BaseModel): class PsPlugin(BaseModel):
content = TextField() content = TextField()
current_version = CharField(null=True) current_version = CharField(null=True)
@ -884,7 +683,6 @@ class PsPlugin(BaseModel):
class Meta: class Meta:
table_name = 'ps_plugin' table_name = 'ps_plugin'
class PsPluginLicense(BaseModel): class PsPluginLicense(BaseModel):
instance = IntegerField(null=True) instance = IntegerField(null=True)
license = UnknownField(null=True) # json license = UnknownField(null=True) # json
@ -896,14 +694,12 @@ class PsPluginLicense(BaseModel):
(('instance', 'plugin'), True), (('instance', 'plugin'), True),
) )
class ReportAlembicVersion(BaseModel): class ReportAlembicVersion(BaseModel):
version_num = CharField(primary_key=True) version_num = CharField(primary_key=True)
class Meta: class Meta:
table_name = 'report_alembic_version' table_name = 'report_alembic_version'
class ReportFile(BaseModel): class ReportFile(BaseModel):
additional_info = UnknownField(null=True) # json additional_info = UnknownField(null=True) # json
content = TextField(null=True) content = TextField(null=True)
@ -919,7 +715,6 @@ class ReportFile(BaseModel):
class Meta: class Meta:
table_name = 'report_file' table_name = 'report_file'
class TaskmgrTask(BaseModel): class TaskmgrTask(BaseModel):
before_execute = UnknownField(null=True) # json before_execute = UnknownField(null=True) # json
bin_args = UnknownField(null=True) # json bin_args = UnknownField(null=True) # json
@ -936,9 +731,7 @@ class TaskmgrTask(BaseModel):
on_start = UnknownField(null=True) # json on_start = UnknownField(null=True) # json
output = TextField() output = TextField()
queue = UnknownField(null=True) # json queue = UnknownField(null=True) # json
registration_time = DateTimeField( registration_time = DateTimeField(constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")])
constraints=[SQL("DEFAULT CURRENT_TIMESTAMP")]
)
request_info = UnknownField(null=True) # json request_info = UnknownField(null=True) # json
return_code = IntegerField() return_code = IntegerField()
service = CharField(constraints=[SQL("DEFAULT ''")]) service = CharField(constraints=[SQL("DEFAULT ''")])
@ -951,7 +744,6 @@ class TaskmgrTask(BaseModel):
class Meta: class Meta:
table_name = 'taskmgr_task' table_name = 'taskmgr_task'
class Vault(BaseModel): class Vault(BaseModel):
key = CharField(unique=True) key = CharField(unique=True)
value = TextField() value = TextField()
@ -959,14 +751,12 @@ class Vault(BaseModel):
class Meta: class Meta:
table_name = 'vault' table_name = 'vault'
class VaultAlembicVersion(BaseModel): class VaultAlembicVersion(BaseModel):
version_num = CharField(primary_key=True) version_num = CharField(primary_key=True)
class Meta: class Meta:
table_name = 'vault_alembic_version' table_name = 'vault_alembic_version'
class VaultQueryLog(BaseModel): class VaultQueryLog(BaseModel):
date = DateTimeField() date = DateTimeField()
owner_email = CharField() owner_email = CharField()
@ -978,3 +768,5 @@ class VaultQueryLog(BaseModel):
class Meta: class Meta:
table_name = 'vault_query_log' table_name = 'vault_query_log'

View File

File diff suppressed because it is too large Load Diff

21
isp_maintenance/ispmgr.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import click
from core.cli.lazy_group import LazyGroup
@click.group(
cls=LazyGroup,
lazy_subcommands={
'vm6': 'apps.vm6.commands.cli',
'dci6': 'apps.dci6.commands.cli',
},
help='main CLI command for lazy example',
)
def cli():
pass
if __name__ == '__main__':
cli()

View File

@ -1,12 +1,12 @@
from mgrctl.settings.general import BASE_DIR from settings.general import BASE_DIR
from mgrctl.settings.platform import ( from settings.platform import (
PLATFORM_TYPE, PLATFORM_TYPE,
PLATFORM_URL, PLATFORM_URL,
PLATFORM_CONFIG PLATFORM_CONFIG
) )
from mgrctl.settings.db import( from settings.db import(
DB_ENGINE, DB_ENGINE,
DB_HOST, DB_HOST,
DB_PORT, DB_PORT,

View File

@ -1,5 +1,5 @@
from mgrctl.settings.environment import env from settings.environment import env
from mgrctl.settings.platform import PLATFORM_CONFIG from settings.platform import PLATFORM_CONFIG
# ! Required because some instance use psql db: # ! Required because some instance use psql db:

View File

@ -6,9 +6,10 @@ BASE_DIR = pathlib.Path(__file__).resolve().parent.parent
INSTALLED_APPS = { INSTALLED_APPS = {
'vm6': { 'vm6': {
'auth': 'mgrctl.apps.vm6.auth.commands.cli', 'access': 'apps.vm6.access.commands.cli',
'nodes': 'apps.vm6.nodes.commands.cli',
}, },
'dci6': { 'dci6': {
'auth': 'mgrctl.apps.dci6.auth.commands.cli', 'access': 'apps.dci6.access.commands.cli',
}, },
} }

View File

@ -0,0 +1,13 @@
from settings.environment import env
from settings.general import BASE_DIR
from utils.helpers import parse_json_file
PLATFORM_TYPE = env.str('PLATFORM_TYPE', 'vm')
PLATFORM_CONFIG = parse_json_file(f'{BASE_DIR}/config.json')
PLATFORM_URL = env.url(
'PLATFORM_URL',
f"https://{PLATFORM_CONFIG.get('DomainName' ,'replace.me')}"
)

View File

View File

@ -1,9 +1,8 @@
import json import json
import sys import sys
import click
def parse_json_file(file_path: str) -> dict: def parse_json_file(file_path):
""" """
Function read json file as usual config.json then parse it to python dict Function read json file as usual config.json then parse it to python dict
@ -17,7 +16,5 @@ def parse_json_file(file_path: str) -> dict:
with open(file_path, 'r') as f: with open(file_path, 'r') as f:
return json.load(f) return json.load(f)
except Exception as error: except Exception as error:
click.echo(error) print(error)
click.echo("Required: /opt/ispsystem/PLATFORM_TYPE/config.json")
click.echo("Note: don't forget to mount this file into the container")
sys.exit(1) sys.exit(1)

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,153 +0,0 @@
import sys
import json
import click
import urllib
import requests
from time import sleep
from mgrctl.settings.api import (
API_INPUT_PORT,
API_URL,
API_HEADERS,
API_EMAIL,
API_PASSWORD,
API_VERIFY_SSL,
API_COUNT_TRY_CONNECTIONS
)
from mgrctl.settings.platform import PLATFORM_TYPE
class BaseAPI(object):
def __init__(self):
"""Announces required parameters"""
self.API_URL = API_URL
self.API_HEADERS = API_HEADERS
self.API_EMAIL = API_EMAIL
self.API_PASSWORD = API_PASSWORD
self.API_VERIFY_SSL = API_VERIFY_SSL
self.API_VERSION = 'v3'
self.API_DEFINITION = 'api'
def _gen_request_url(self, url):
return f'{self.API_URL}/{self.API_DEFINITION}/{self.API_VERSION}{url}'
def call_api(self, url, method='GET', headers={}, data={}):
attempt = API_COUNT_TRY_CONNECTIONS
while attempt:
attempt -= 1
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':
api_request = requests.post(
url=uri,
json=data,
headers=headers,
verify=self.API_VERIFY_SSL
)
if method == 'GET':
uri = f'{uri}?{params_str}' if params_str else uri
api_request = requests.get(
url=uri,
headers=headers,
verify=self.API_VERIFY_SSL
)
except Exception as error:
ConnectionError = requests.exceptions.ConnectionError
if type(error) is ConnectionError and PLATFORM_TYPE == 'dci':
# ? workaround if new docker version use dashes
# TODO: ISPsystem developers must set container_name !!!
self.API_URL = f'http://dci-input-1:{API_INPUT_PORT}'
if attempt == 0:
click.echo(f'Error: {type(error).__name__}')
sys.exit()
else:
continue
else:
click.echo(f'Error: {type(error).__name__}')
sys.exit()
# Get response:
response = self._parse_response(api_request)
# Validate response:
if self._error_handler(response):
continue # new attempt connection
return response
def _parse_response(self, api_request):
try:
response = json.loads(api_request.text)
return response
except json.decoder.JSONDecodeError:
click.echo('Error: Invalid API response')
raise sys.exit()
def _is_error(self, response):
if response.get('error'):
return True
def _is_error_3004(self, error):
if error.get('code') == 3004:
sleep(2) # wait 2 second timeout
return True
def _error_handler(self, response):
if self._is_error(response):
error = response.get('error')
if self._is_error_3004(error):
return True
else:
click.echo(f'Error: API return {response}')
raise sys.exit()
class BaseAuthAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_VERSION = 'v4'
self.API_DEFINITION = 'auth'
def get_auth_token(self, email=None, password=None) -> dict:
email = self.API_EMAIL if not email else email
password = self.API_PASSWORD if not password else password
return self.call_api(
url='/public/token',
method='POST',
data={'email': email, 'password': password}
)
def get_auth_key(self, token=None, user=None) -> dict:
headers = {}
user = self.API_EMAIL if not user else user
if token:
headers = self.make_auth_header(token)
return self.call_api(
url=f'/user/{user}/key',
method='POST',
headers=headers
)
def make_auth_header(self, token: str) -> dict:
return {'x-xsrf-token': token}
def whoami(self) -> dict:
return self.call_api(
url='/whoami',
method='GET'
)
class BaseIpAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_DEFINITION = 'ip'
class BaseDnsProxyAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_DEFINITION = 'dnsproxy'

View File

@ -1,51 +0,0 @@
from mgrctl.api.base import BaseAPI, BaseAuthAPI, BaseDnsProxyAPI, BaseIpAPI
class AuthAPI(BaseAuthAPI):
pass
class BackupAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_VERSION = 'v4'
self.API_DEFINITION = 'backup'
class DnsProxyAPI(BaseDnsProxyAPI):
pass
class EserviceAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_DEFINITION = 'eservice'
class IsoAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_DEFINITION = 'iso'
class IpmiAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_DEFINITION = 'ipmiproxy'
class IpAPI(BaseIpAPI):
pass
class ReportAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_VERSION = 'v4'
self.API_DEFINITION = 'report'
class UpdaterAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_DEFINITION = 'updater'

View File

@ -1,19 +0,0 @@
from mgrctl.api.base import BaseAPI, BaseAuthAPI, BaseDnsProxyAPI, BaseIpAPI
class AuthAPI(BaseAuthAPI):
pass
class DnsProxyAPI(BaseDnsProxyAPI):
pass
class IpAPI(BaseIpAPI):
pass
class VmAPI(BaseAPI):
def __init__(self):
super().__init__()
self.API_DEFINITION = 'vm'

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,99 +0,0 @@
import click
from mgrctl.apps.dci6.auth import __version__
from mgrctl.api.dci6 import AuthAPI
from mgrctl.utils.api_users import UserAPI
user_cursor = UserAPI(callback_class=AuthAPI)
@click.group(help='auth cmd for auth in DCImanager 6')
@click.version_option(
version=__version__,
package_name='mgrctl.apps.dci6.auth',
message=__version__
)
def cli():
pass
@cli.group(help='Manage users')
def user():
pass
@user.command(help='List users')
@click.option(
'--all',
is_flag=True,
required=False,
help='Show all users'
)
@click.option(
'--admins',
is_flag=True,
required=False,
help='Show all active admins',
)
def ls(all, admins):
if all:
users = user_cursor.get_users(role='all')
elif admins:
users = user_cursor.get_users(role='admin')
else:
users = user_cursor.get_users(role='all')
# print users:
user_cursor.echo_users(users)
@user.command(
help='Generate an access key and return auth link(s)',
no_args_is_help=True
)
@click.option(
'--id',
'_id',
required=False,
type=int,
help='User id'
)
@click.option(
'--count',
required=False,
type=int,
help='Number of access keys generated',
)
@click.option(
'--random',
is_flag=True,
required=False,
help='Generate access key for the first available admin'
)
@click.option(
'--interactive',
is_flag=True,
required=False,
help='Interactive mode, ignores other keys'
)
def access(_id, count, interactive, random):
if _id and not count:
keys = user_cursor.get_access_keys(user=_id, count=1)
elif _id and count:
keys = user_cursor.get_access_keys(user=_id, count=count)
elif random:
admin = user_cursor.get_first_random_admin()
keys = user_cursor.get_access_keys(user=admin.get('id', 3))
elif interactive:
user_cursor.gen_access_links_interactive()
return # exit from func
else:
pass
links = user_cursor.gen_access_links(keys)
user_cursor.echo_access_links(links)
@user.command(help='Generate API token for mgrctl user')
def token():
token = user_cursor.gen_api_token()
user_cursor.echo_api_token(token)

View File

@ -1,13 +0,0 @@
import click
from mgrctl.cli.lazy_group import LazyGroup
from mgrctl.settings.general import INSTALLED_APPS
@click.group(
cls=LazyGroup,
lazy_subcommands=INSTALLED_APPS['dci6'],
help='dci6 command for DCI6manager management',
)
def cli():
pass

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,99 +0,0 @@
import click
from mgrctl.apps.vm6.auth import __version__
from mgrctl.api.vm6 import AuthAPI
from mgrctl.utils.api_users import UserAPI
user_cursor = UserAPI(callback_class=AuthAPI)
@click.group(help='auth cmd for auth in VMmanager 6')
@click.version_option(
version=__version__,
package_name='mgrctl.apps.vm6.auth',
message=__version__
)
def cli():
pass
@cli.group(help='Manage users')
def user():
pass
@user.command(help='List users')
@click.option(
'--all',
is_flag=True,
required=False,
help='Show all users'
)
@click.option(
'--admins',
is_flag=True,
required=False,
help='Show all active admins',
)
def ls(all, admins):
if all:
users = user_cursor.get_users(role='all')
elif admins:
users = user_cursor.get_users(role='admin')
else:
users = user_cursor.get_users(role='all')
# print users:
user_cursor.echo_users(users)
@user.command(
help='Generate an access key and return auth link(s)',
no_args_is_help=True
)
@click.option(
'--id',
'_id',
required=False,
type=int,
help='User id'
)
@click.option(
'--count',
required=False,
type=int,
help='Number of access keys generated',
)
@click.option(
'--random',
is_flag=True,
required=False,
help='Generate access key for the first available admin'
)
@click.option(
'--interactive',
is_flag=True,
required=False,
help='Interactive mode, ignores other keys'
)
def access(_id, count, interactive, random):
if _id and not count:
keys = user_cursor.get_access_keys(user=_id, count=1)
elif _id and count:
keys = user_cursor.get_access_keys(user=_id, count=count)
elif random:
admin = user_cursor.get_first_random_admin()
keys = user_cursor.get_access_keys(user=admin.get('id', 3))
elif interactive:
user_cursor.gen_access_links_interactive()
return # exit from func
else:
pass
links = user_cursor.gen_access_links(keys)
user_cursor.echo_access_links(links)
@user.command(help='Generate API token for mgrctl user')
def token():
token = user_cursor.gen_api_token()
user_cursor.echo_api_token(token)

View File

@ -1,19 +0,0 @@
import click
from mgrctl.cli.lazy_group import LazyGroup
from mgrctl.settings.general import INSTALLED_APPS
from mgrctl.apps.vm6 import __version__
@click.group(
cls=LazyGroup,
lazy_subcommands=INSTALLED_APPS['vm6'],
help='vm6 command for VM6manager management',
)
@click.version_option(
version=__version__,
package_name='mgrctl',
message=__version__
)
def cli():
pass

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,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')

View File

@ -1,32 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# █▀▄▀█ █▀▀ █▀█ █▀▀ ▀█▀ █░░ ▀
# █░▀░█ █▄█ █▀▄ █▄▄ ░█░ █▄▄ ▄
# -- -- -- -- -- -- -- -- --
import click
from mgrctl import __version__
from mgrctl.cli.lazy_group import LazyGroup
@click.group(
cls=LazyGroup,
lazy_subcommands={
'vm6': 'mgrctl.apps.vm6.commands.cli',
'dci6': 'mgrctl.apps.dci6.commands.cli',
},
help='main CLI command for mgrctl app',
)
@click.version_option(
version=__version__,
package_name='mgrctl',
message=__version__
)
def cli():
pass
if __name__ == '__main__':
cli()

View File

@ -1,47 +0,0 @@
from requests.packages import urllib3
from mgrctl.settings.environment import env
from mgrctl.settings.platform import (
PLATFORM_TYPE,
PLATFORM_VERIFY_SSL,
PLATFORM_VERIFY_SSL_WARNING,
PLATFORM_DUMMY,
PLATFORM_DUMMY_API_URL,
PLATFORM_DUMMY_EMAIL,
PLATFORM_DUMMY_PASSWORD,
PLATFORM_DUMMY_TOKEN,
)
# Name of nginx container:
API_INPUT_HOSTNAME = 'input' if PLATFORM_TYPE == 'vm' else 'dci_input_1'
# Port that nginx container is listening:
API_INPUT_PORT = '1500'
# Internal API url:
API_URL = f'http://{API_INPUT_HOSTNAME}:{API_INPUT_PORT}'
# Headers for internal auth:
API_HEADERS = {"Internal-Auth": "on", "Accept": "application/json"}
# Alias for import:
API_VERIFY_SSL = PLATFORM_VERIFY_SSL
# API 3004 Unavailable error handler:
API_COUNT_TRY_CONNECTIONS = env.int('API_COUNT_TRY_CONNECTIONS', 3)
# Suppress warning from urllib3:
if not PLATFORM_VERIFY_SSL_WARNING:
# ! This is not recommended,
# ! the user will not see a message about an untrusted SSL connection
urllib3.disable_warnings(
category=urllib3.exceptions.InsecureRequestWarning
)
# Development mode:
if PLATFORM_DUMMY:
API_URL = PLATFORM_DUMMY_API_URL
API_HEADERS = {'x-xsrf-token': PLATFORM_DUMMY_TOKEN}
API_EMAIL = PLATFORM_DUMMY_EMAIL
API_PASSWORD = PLATFORM_DUMMY_PASSWORD

View File

@ -1,41 +0,0 @@
from mgrctl.settings.environment import env
from mgrctl.utils.helpers import parse_json_file
PLATFORM_TYPE = env.str('PLATFORM_TYPE', 'vm')
PLATFORM_VERIFY_SSL = env.bool('PLATFORM_VERIFY_SSL', True)
PLATFORM_VERIFY_SSL_WARNING = env.bool('PLATFORM_VERIFY_SSL_WARNING', True)
PLATFORM_CONFIG = env.str(
'PLATFORM_CONFIG',
f'/opt/ispsystem/{PLATFORM_TYPE}/config.json'
)
PLATFORM_CONFIG = parse_json_file(PLATFORM_CONFIG)
PLATFORM_URL = env.str(
'PLATFORM_URL',
f"https://{PLATFORM_CONFIG.get('DomainName' ,'replace.me')}"
)
# Development mode:
PLATFORM_DUMMY = env.bool('PLATFORM_DUMMY', False)
if PLATFORM_TYPE == 'vm':
PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_VM6_API_URL', '')
PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_VM6_EMAIL', '')
PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_VM6_PASSWORD', '')
PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_VM6_TOKEN', '')
elif PLATFORM_TYPE == 'dci':
PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_DCI6_API_URL', '')
PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_DCI6_EMAIL', '')
PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_DCI6_PASSWORD', '')
PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_DCI6_TOKEN', '')
else:
# ? guarantees that constants exist for import
# ? if the user has set the wrong PLATFORM_TYPE:
PLATFORM_DUMMY_API_URL = env.str('PLATFORM_DUMMY_API_URL', '')
PLATFORM_DUMMY_EMAIL = env.str('PLATFORM_DUMMY_EMAIL', '')
PLATFORM_DUMMY_PASSWORD = env.str('PLATFORM_DUMMY_PASSWORD', '')
PLATFORM_DUMMY_TOKEN = env.str('PLATFORM_DUMMY_TOKEN', '')

View File

@ -1,92 +0,0 @@
import click
from tabulate import tabulate
from mgrctl.settings.platform import PLATFORM_URL
class UserAPI(object):
def __init__(self, callback_class):
"""Announces required parameters"""
self.callback_class = callback_class
self.callback = callback_class()
def get_users(self, role: str) -> list:
data = {}
if role == 'admin':
data = {"where": "((roles+CP+'%@admin%')+AND+(state+EQ+'active'))"}
response = self.callback.call_api(
url='/user',
method='GET',
data=data
)
users = self._extract_users(users=response)
return users
def _extract_users(self, users: dict) -> list:
return users.get('list', [])
def _format_users(self, users: list) -> list:
output = []
for user in users:
output.append({
'id': user.get('id', ''),
'email': user.get('email', ''),
'roles': user.get('roles', []),
'state': user.get('state', ''),
# add more fields here...
})
return output
def get_first_random_admin(self):
users = self.get_users(role='admin')
admin = {}
for user in users:
if '@admin' in user.get('roles', []):
admin = user
break
return admin
def echo_users(self, users: list) -> None:
output = self._format_users(users)
click.echo(tabulate(output, headers='keys'))
def get_access_keys(self, user, count=1):
keys = []
while count >= 1:
count -= 1
key = self.callback.get_auth_key(user=user)
check = key.get('key', '')
if check:
keys.append(key)
return keys
def gen_access_links(self, keys: list) -> list:
links = []
for key in keys:
_id = key.get('id', '')
link = f"{PLATFORM_URL}/auth/key/{key.get('key', '')}"
links.append({'id': _id, 'link': link})
return links
def echo_access_links(self, links: list) -> None:
click.echo(tabulate(links, headers='keys'))
def gen_access_links_interactive(self) -> None:
users = self.get_users(role='admin')
self.echo_users(users)
try:
click.echo('Choose user id and count of keys')
_id = int(input('User ID: '))
count = int(input('Count of keys: '))
keys = self.get_access_keys(user=_id, count=count)
links = self.gen_access_links(keys)
self.echo_access_links(links)
except ValueError:
click.echo('Error: Invalid, value is not a valid integer')
def gen_api_token(self, email=None, password=None):
token = self.callback.get_auth_token(email, password)
return token
def echo_api_token(self, token: dict) -> None:
click.echo(tabulate([token], headers='keys'))

27
poetry.lock generated
View File

@ -1066,17 +1066,6 @@ files = [
cryptography = ">=2.0" cryptography = ">=2.0"
jeepney = ">=0.6" jeepney = ">=0.6"
[[package]]
name = "sh"
version = "2.0.7"
description = "Python subprocess replacement"
optional = false
python-versions = "<4.0,>=3.8.1"
files = [
{file = "sh-2.0.7-py3-none-any.whl", hash = "sha256:2f2f79a65abd00696cf2e9ad26508cf8abb6dba5745f40255f1c0ded2876926d"},
{file = "sh-2.0.7.tar.gz", hash = "sha256:029d45198902bfb967391eccfd13a88d92f7cebd200411e93f99ebacc6afbb35"},
]
[[package]] [[package]]
name = "shellingham" name = "shellingham"
version = "1.5.4" version = "1.5.4"
@ -1088,20 +1077,6 @@ files = [
{file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
] ]
[[package]]
name = "tabulate"
version = "0.9.0"
description = "Pretty-print tabular data"
optional = false
python-versions = ">=3.7"
files = [
{file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
{file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
]
[package.extras]
widechars = ["wcwidth"]
[[package]] [[package]]
name = "tomlkit" name = "tomlkit"
version = "0.12.3" version = "0.12.3"
@ -1263,4 +1238,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.11" python-versions = "^3.11"
content-hash = "ae5af366753982ef73f90fc9f4d59b03db4fb597e31bd88f445423837288f3e1" content-hash = "8c1b8d4cae2524776d0d04253f6067ca4a2282d0681677df78afbc5437b0dea5"

View File

@ -1,13 +1,8 @@
[tool.poetry] [tool.poetry]
name = "mgrctl" name = "isp-maintenance"
version = "0.1.0" version = "0.1.0"
description = "Maintenance service for ISPsystem platforms" description = "Maintenance service for ISPsystem platforms"
authors = [ authors = ["MOIS3Y <s.zhukovskii@ispsystem.com>", "Failak3 <v.shmidt@ispsystem.com>", "a.garaev <a.garaev@ispsystem.com>", "Ann_M <a.moskovkina@ispsystem.com>"]
"MOIS3Y <s.zhukovskii@ispsystem.com>",
"Failak3 <v.shmidt@ispsystem.com>",
"a.garaev <a.garaev@ispsystem.com>",
"Ann_M <a.moskovkina@ispsystem.com>"
]
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
@ -19,15 +14,11 @@ requests = "^2.31.0"
environs = "^10.3.0" environs = "^10.3.0"
pymysql = {extras = ["rsa"], version = "^1.1.0"} pymysql = {extras = ["rsa"], version = "^1.1.0"}
poetry-plugin-export = "^1.6.0" poetry-plugin-export = "^1.6.0"
sh = "^2.0.7"
tabulate = "^0.9.0"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
flake8 = "^7.0.0" flake8 = "^7.0.0"
[tool.poetry.scripts]
mgrctl = 'mgrctl.mgrctl:cli'
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"

View File

@ -500,15 +500,9 @@ requests==2.31.0 ; python_version >= "3.11" and python_version < "4.0" \
secretstorage==3.3.3 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "linux" \ secretstorage==3.3.3 ; python_version >= "3.11" and python_version < "4.0" and sys_platform == "linux" \
--hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \
--hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 --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" \ shellingham==1.5.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \
--hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de --hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de
tabulate==0.9.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
--hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
tomlkit==0.12.3 ; python_version >= "3.11" and python_version < "4.0" \ tomlkit==0.12.3 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4 \ --hash=sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4 \
--hash=sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba --hash=sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba

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,50 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import click
import sh
from .lazy_group import LazyGroup
from .utils import abort_if_false
from . import settings
@click.group()
def cli1():
pass
@click.group(
cls=LazyGroup,
lazy_subcommands={'docker-compose': 'cli.builder.docker_compose'},
)
def cli2():
pass
@click.group(help='cmd for build/destroy project in docker containers')
def docker_compose():
pass
@docker_compose.command(help='cmd for build project in docker containers')
def build():
with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True):
sh.docker_compose('-f', settings.COMPOSE_FILE, 'build', _fg=True)
@docker_compose.command(help='cmd for destroy project in docker containers')
@click.option(
'--yes',
is_flag=True,
callback=abort_if_false,
expose_value=False,
prompt='Are you sure you want to destroy docker containers')
def destroy():
with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True):
sh.docker_compose('-f', settings.COMPOSE_FILE, 'down', _fg=True)
cli = click.CommandCollection(
sources=[cli1, cli2],
help='cmd for building the project'
)

View File

@ -1,39 +0,0 @@
import importlib
import click
class LazyGroup(click.Group):
def __init__(self, *args, lazy_subcommands=None, **kwargs):
super().__init__(*args, **kwargs)
# lazy_subcommands is a map of the form:
#
# {command-name} -> {module-name}.{command-object-name}
#
self.lazy_subcommands = lazy_subcommands or {}
def list_commands(self, ctx):
base = super().list_commands(ctx)
lazy = sorted(self.lazy_subcommands.keys())
return base + lazy
def get_command(self, ctx, cmd_name):
if cmd_name in self.lazy_subcommands:
return self._lazy_load(cmd_name)
return super().get_command(ctx, cmd_name)
def _lazy_load(self, cmd_name):
# lazily loading a command,
# first get the module name and attribute name
import_path = self.lazy_subcommands[cmd_name]
modname, cmd_object_name = import_path.rsplit(".", 1)
# do the import
mod = importlib.import_module(modname)
# get the Command object from that module
cmd_object = getattr(mod, cmd_object_name)
# check the result to make debugging easier
if not isinstance(cmd_object, click.BaseCommand):
raise ValueError(
f"Lazy loading of {import_path} failed by returning "
"a non-command object"
)
return cmd_object

View File

@ -1,57 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import click
import sh
from .lazy_group import LazyGroup
from . import settings
@click.group()
def cli1():
pass
@click.group(
cls=LazyGroup,
lazy_subcommands={'docker-compose': 'cli.runner.docker_compose'},
)
def cli2():
pass
@click.group(help='cmd for run/stop/restart project in docker containers')
def docker_compose():
pass
@docker_compose.command(help='cmd for run project docker containers')
def up():
with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True):
sh.docker_compose('-f', settings.COMPOSE_FILE, 'up', '-d', _fg=True)
@docker_compose.command(help='cmd for down project docker containers')
def down():
with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True):
sh.docker_compose('-f', settings.COMPOSE_FILE, 'down', _fg=True)
@docker_compose.command(help='cmd for restart project docker containers')
def restart():
with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True):
sh.docker_compose(
'-f',
settings.COMPOSE_FILE,
'up',
'-d',
'--build',
'--force-recreate',
_fg=True
)
cli = click.CommandCollection(
sources=[cli1, cli2],
help='cmd for running the project standalone or docker-compose'
)

View File

@ -1,18 +0,0 @@
import pathlib
from environs import Env
# Path:
ROOT_DIR = pathlib.Path(__file__).resolve().parent.parent.parent.parent
PROJECT_DIR = ROOT_DIR / 'mgrctl'
COMPOSE_FILE = ROOT_DIR / 'docker-compose.yml'
# Init environment:
env = Env()
# read .env file, if it exists
# reed more about .env file here: https://github.com/sloria/environs
env.read_env(path=ROOT_DIR / '.env')
# ! insecure save sudo password wherever
SUDO_PASSWORD = env.str('SUDO_PASSWORD', None)

View File

@ -1,15 +0,0 @@
import click
from . import __version__
def print_version(ctx, param, value):
if not value or ctx.resilient_parsing:
return
click.echo(__version__)
ctx.exit()
def abort_if_false(ctx, param, value):
if not value:
ctx.abort()

View File

@ -1,30 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import click
from cli.lazy_group import LazyGroup
from cli.utils import print_version
@click.group(
cls=LazyGroup,
lazy_subcommands={
'builder': 'cli.builder.cli',
'runner': 'cli.runner.cli',
},
help='dev.py CLI tool for dev actions',
)
@click.option(
'--version',
is_flag=True,
callback=print_version,
expose_value=False,
is_eager=True,
help='Print version and exit'
)
def cli():
pass
if __name__ == '__main__':
cli()

View File

@ -1,512 +0,0 @@
#!/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 $@