forked from ISPsystem/isp-maintenance
		
	Add: devtools, Makefile
This commit is contained in:
		
							parent
							
								
									0f96d0f956
								
							
						
					
					
						commit
						287216d975
					
				
							
								
								
									
										13
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| build: | ||||
| 	python3 ./scripts/devtools/dev.py builder docker-compose build | ||||
| destroy: | ||||
| 	python3 ./scripts/devtools/dev.py builder docker-compose destroy | ||||
| up: | ||||
| 	python3 ./scripts/devtools/dev.py runner docker-compose up | ||||
| down: | ||||
| 	python3 ./scripts/devtools/dev.py runner docker-compose down | ||||
| restart: | ||||
| 	python3 ./scripts/devtools/dev.py runner docker-compose restart | ||||
| setup: build up | ||||
| 
 | ||||
| .PHONY: exec setup build | ||||
							
								
								
									
										59
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| # ? 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: | ||||
| # ?     /opt/ispsystem/vm/config.json - configuration file | ||||
| # ?     /opt/ispsystem/vm/mysql - database directory | ||||
| # ? DCI6: | ||||
| # ?     /opt/ispsystem/dci/config.json - configuration file | ||||
| # ?     /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: | ||||
|     driver: bridge | ||||
							
								
								
									
										10
									
								
								scripts/devtools/cli/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								scripts/devtools/cli/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| # █▀▄▀█ █▀▀ ▀█▀ ▄▀█ ▀ | ||||
| # █░▀░█ ██▄ ░█░ █▀█ ▄ | ||||
| # -- -- -- -- -- -- - | ||||
| __author__ = "MOIS3Y" | ||||
| __credits__ = ["Stepan Zhukovsky"] | ||||
| __license__ = "MIT" | ||||
| __version__ = "0.1.0" | ||||
| __maintainer__ = "Stepan Zhukovsky" | ||||
| __email__ = "stepan@zhukovsky.me" | ||||
| __status__ = "Development" | ||||
							
								
								
									
										50
									
								
								scripts/devtools/cli/builder.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								scripts/devtools/cli/builder.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| import click | ||||
| import sh | ||||
| 
 | ||||
| from .lazy_group import LazyGroup | ||||
| from .utils import abort_if_false | ||||
| from . import settings | ||||
| 
 | ||||
| 
 | ||||
| @click.group() | ||||
| def cli1(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={'docker-compose': 'cli.builder.docker_compose'}, | ||||
| ) | ||||
| def cli2(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='cmd for build/destroy project in docker containers') | ||||
| def docker_compose(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for build project in docker containers') | ||||
| def build(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'build', _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for destroy project in docker containers') | ||||
| @click.option( | ||||
|     '--yes', | ||||
|     is_flag=True, | ||||
|     callback=abort_if_false, | ||||
|     expose_value=False, | ||||
|     prompt='Are you sure you want to destroy docker containers') | ||||
| def destroy(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'down',  _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| cli = click.CommandCollection( | ||||
|     sources=[cli1, cli2], | ||||
|     help='cmd for building the project' | ||||
| ) | ||||
							
								
								
									
										39
									
								
								scripts/devtools/cli/lazy_group.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								scripts/devtools/cli/lazy_group.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| import importlib | ||||
| import click | ||||
| 
 | ||||
| 
 | ||||
| class LazyGroup(click.Group): | ||||
|     def __init__(self, *args, lazy_subcommands=None, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         # lazy_subcommands is a map of the form: | ||||
|         # | ||||
|         #   {command-name} -> {module-name}.{command-object-name} | ||||
|         # | ||||
|         self.lazy_subcommands = lazy_subcommands or {} | ||||
| 
 | ||||
|     def list_commands(self, ctx): | ||||
|         base = super().list_commands(ctx) | ||||
|         lazy = sorted(self.lazy_subcommands.keys()) | ||||
|         return base + lazy | ||||
| 
 | ||||
|     def get_command(self, ctx, cmd_name): | ||||
|         if cmd_name in self.lazy_subcommands: | ||||
|             return self._lazy_load(cmd_name) | ||||
|         return super().get_command(ctx, cmd_name) | ||||
| 
 | ||||
|     def _lazy_load(self, cmd_name): | ||||
|         # lazily loading a command, | ||||
|         # first get the module name and attribute name | ||||
|         import_path = self.lazy_subcommands[cmd_name] | ||||
|         modname, cmd_object_name = import_path.rsplit(".", 1) | ||||
|         # do the import | ||||
|         mod = importlib.import_module(modname) | ||||
|         # get the Command object from that module | ||||
|         cmd_object = getattr(mod, cmd_object_name) | ||||
|         # check the result to make debugging easier | ||||
|         if not isinstance(cmd_object, click.BaseCommand): | ||||
|             raise ValueError( | ||||
|                 f"Lazy loading of {import_path} failed by returning " | ||||
|                 "a non-command object" | ||||
|             ) | ||||
|         return cmd_object | ||||
							
								
								
									
										57
									
								
								scripts/devtools/cli/runner.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								scripts/devtools/cli/runner.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| import click | ||||
| import sh | ||||
| 
 | ||||
| from .lazy_group import LazyGroup | ||||
| from . import settings | ||||
| 
 | ||||
| 
 | ||||
| @click.group() | ||||
| def cli1(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={'docker-compose': 'cli.runner.docker_compose'}, | ||||
| ) | ||||
| def cli2(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @click.group(help='cmd for run/stop/restart project in docker containers') | ||||
| def docker_compose(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for run project docker containers') | ||||
| def up(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'up', '-d', _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for down project docker containers') | ||||
| def down(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose('-f', settings.COMPOSE_FILE, 'down', _fg=True) | ||||
| 
 | ||||
| 
 | ||||
| @docker_compose.command(help='cmd for restart project docker containers') | ||||
| def restart(): | ||||
|     with sh.contrib.sudo(password=settings.SUDO_PASSWORD, _with=True): | ||||
|         sh.docker_compose( | ||||
|             '-f', | ||||
|             settings.COMPOSE_FILE, | ||||
|             'up', | ||||
|             '-d', | ||||
|             '--build', | ||||
|             '--force-recreate', | ||||
|             _fg=True | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| cli = click.CommandCollection( | ||||
|     sources=[cli1, cli2], | ||||
|     help='cmd for running the project standalone or docker-compose' | ||||
| ) | ||||
							
								
								
									
										18
									
								
								scripts/devtools/cli/settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								scripts/devtools/cli/settings.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| import pathlib | ||||
| from environs import Env | ||||
| 
 | ||||
| 
 | ||||
| # Path: | ||||
| ROOT_DIR = pathlib.Path(__file__).resolve().parent.parent.parent.parent | ||||
| PROJECT_DIR = ROOT_DIR / 'mgrctl' | ||||
| COMPOSE_FILE = ROOT_DIR / 'docker-compose.yml' | ||||
| 
 | ||||
| # Init environment: | ||||
| env = Env() | ||||
| 
 | ||||
| # read .env file, if it exists | ||||
| # reed more about .env file here: https://github.com/sloria/environs | ||||
| env.read_env(path=ROOT_DIR / '.env') | ||||
| 
 | ||||
| # ! insecure save sudo password wherever | ||||
| SUDO_PASSWORD = env.str('SUDO_PASSWORD', None) | ||||
							
								
								
									
										15
									
								
								scripts/devtools/cli/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								scripts/devtools/cli/utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import click | ||||
| 
 | ||||
| from . import __version__ | ||||
| 
 | ||||
| 
 | ||||
| def print_version(ctx, param, value): | ||||
|     if not value or ctx.resilient_parsing: | ||||
|         return | ||||
|     click.echo(__version__) | ||||
|     ctx.exit() | ||||
| 
 | ||||
| 
 | ||||
| def abort_if_false(ctx, param, value): | ||||
|     if not value: | ||||
|         ctx.abort() | ||||
							
								
								
									
										30
									
								
								scripts/devtools/dev.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										30
									
								
								scripts/devtools/dev.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,30 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- coding: utf-8 -*- | ||||
| import click | ||||
| 
 | ||||
| from cli.lazy_group import LazyGroup | ||||
| from cli.utils import print_version | ||||
| 
 | ||||
| 
 | ||||
| @click.group( | ||||
|     cls=LazyGroup, | ||||
|     lazy_subcommands={ | ||||
|         'builder': 'cli.builder.cli', | ||||
|         'runner': 'cli.runner.cli', | ||||
|     }, | ||||
|     help='dev.py CLI tool for dev actions', | ||||
| ) | ||||
| @click.option( | ||||
|     '--version', | ||||
|     is_flag=True, | ||||
|     callback=print_version, | ||||
|     expose_value=False, | ||||
|     is_eager=True, | ||||
|     help='Print version and exit' | ||||
| ) | ||||
| def cli(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     cli() | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user