示例#1
0
 def deploy(self):
     CLI.info('Deploying...')
     self.clean()
     self.upload()
     self.pull()
     self.reload()
     self.logs()
     self.status()
示例#2
0
    def restart_proxy(self):
        CLI.info('Restarting proxy...')
        steps = 1

        CLI.step(1, steps, 'Reloading proxy container...')
        os.system(
            f'docker-compose {self.docker_ssh} -f configs/docker/docker-compose.{self.environment_id}.proxy.yml --project-name=reverse up -d'
        )
示例#3
0
 def pg_dump(self):
     now = datetime.datetime.now()
     # filename = now.strftime("%Y%m%d%H%M%S")
     filename = now.strftime(f"{self.PROJECT_NAME}_%Y%m%d_%H%M.pg")
     CLI.info(f'Backuping database into file {filename}')
     env = self.load_environment()
     os.system(
         f'docker {self.docker_ssh} exec -it {self.CONTAINER_DB} bash -c \'pg_dump -Fc -h {env["POSTGRES_HOST"]} -U {env["POSTGRES_USER"]} {env["POSTGRES_DBNAME"]} -W > /backups/{filename}\''
     )
示例#4
0
 def pg_restore(self, params):
     CLI.info(f'Restoring database from file {params}')
     CLI.underline(
         "Don't forget to drop database at first to prevent constraints collisions!"
     )
     env = self.load_environment()
     os.system(
         f'docker {self.docker_ssh} exec -it {self.CONTAINER_DB} bash -c \'pg_restore -h {env["POSTGRES_HOST"]} -U {env["POSTGRES_USER"]} -d {env["POSTGRES_DBNAME"]} -W < /backups/{params}\''
     )
示例#5
0
    def status(self):
        if self.SWARM:  # todo remove containers as well ?
            CLI.info('Getting status...')
            os.system(f'docker stack services {self.PROJECT_NAME}')

        else:
            CLI.info('Getting status...')
            steps = 2

            CLI.step(1, steps, 'List of Docker images')
            os.system(f'docker {self.docker_ssh} image ls')

            CLI.step(2, steps, 'Docker containers')
            os.system(f'docker {self.docker_ssh} container ls -a --size')
示例#6
0
def main():
    # check params
    params = parse_args()

    # print(params)
    if len(params['commands']) == 0:
        CLI.error('Missing commands')

    environment_id = params['environment_id']
    commands = params['commands']
    mode = params['settings'].get('mode', 'docker-host')
    hostname = os.popen('hostname').read().rstrip("\n")

    # setup manager
    manager = Mantis(environment_id=environment_id, mode=mode)

    print(f'Mantis (v{VERSION}) attached to '
          f'{Colors.BOLD}{manager.environment_id}{Colors.ENDC}: '
          f'{Colors.RED}{manager.host}{Colors.ENDC}, '
          f'mode: {Colors.GREEN}{manager.mode}{Colors.ENDC}, '
          f'hostname: {Colors.BLUE}{hostname}{Colors.ENDC}')

    if mode == 'ssh':
        cmds = [
            f'cd {manager.project_path}',
            f'time mantis {environment_id} --mode=host {" ".join(commands)}'
        ]
        cmd = ';'.join(cmds)
        exec = f"ssh -t {manager.user}@{manager.host} -p {manager.port} '{cmd}'"
        os.system(exec)
    else:
        # execute all commands
        for command in commands:
            if ':' in command:
                command, params = command.split(':')
            else:
                params = None

            execute(manager, command, params)
示例#7
0
    def networks(self):
        # todo for swarm
        CLI.info('Getting networks...')
        steps = 1

        CLI.step(1, steps, 'List of Docker networks')

        networks = os.popen(f'docker {self.docker_ssh} network ls').read()
        networks = networks.strip().split('\n')

        for index, network in enumerate(networks):
            network_data = list(filter(lambda x: x != '', network.split(' ')))
            network_name = network_data[1]

            if index == 0:
                print(f'{network}\tCONTAINERS')
            else:
                containers = os.popen(
                    f'docker {self.docker_ssh} network inspect -f \'{{{{ range $key, $value := .Containers }}}}{{{{ .Name }}}} {{{{ end }}}}\' {network_name}'
                ).read()
                containers = ', '.join(containers.split())
                print(f'{network}\t{containers}'.strip())
示例#8
0
    def push(self):
        CLI.info(f'Pushing...')

        steps = 2
        CLI.step(1, steps, 'Tagging Docker image...')
        os.system(
            f'docker tag {self.IMAGE_NAME} {self.DOCKER_REPOSITORY}:{self.DOCKER_TAG}'
        )
        print(
            f'Successfully tagged {self.DOCKER_REPOSITORY}:{self.DOCKER_TAG}')

        CLI.step(2, steps, 'Pushing Docker image...')
        os.system(f'docker push {self.DOCKER_REPOSITORY}:{self.DOCKER_TAG}')
示例#9
0
    def logs(self, params=None):
        if self.SWARM:
            CLI.info('Reading logs...')

            services = params.split(' ') if params else self.get_services()
            lines = '-f' if params else '--tail 10'
            steps = len(services)

            for index, service in enumerate(services):
                CLI.step(index + 1, steps, f'{service} logs')
                os.system(f'docker service logs {service} {lines}')

        else:
            CLI.info('Reading logs...')

            containers = params.split(' ') if params else self.get_containers()
            lines = '-f' if params else '--tail 10'
            steps = len(containers)

            for index, container in enumerate(containers):
                CLI.step(index + 1, steps, f'{container} logs')
                os.system(f'docker {self.docker_ssh} logs {container} {lines}')
示例#10
0
    def remove(self, params=''):
        if self.SWARM:  # todo remove containers as well ?
            CLI.info('Removing services...')
            os.system(f'docker stack rm {self.PROJECT_NAME}')

        else:
            CLI.info('Removing containers...')

            containers = self.get_containers(
            ) if params == '' else params.split(' ')

            steps = len(containers)

            for index, container in enumerate(containers):
                CLI.step(index + 1, steps, f'Removing {container}')
                os.system(f'docker {self.docker_ssh} container rm {container}')
示例#11
0
    def stop(self, params=None):
        if self.SWARM:  # todo can stop service ?
            CLI.info('Removing services...')
            os.system(f'docker stack rm {self.PROJECT_NAME}')

        else:
            CLI.info('Stopping containers...')

            containers = self.get_containers() if not params else params.split(
                ' ')

            steps = len(containers)

            for index, container in enumerate(containers):
                CLI.step(index + 1, steps, f'Stopping {container}')
                os.system(
                    f'docker {self.docker_ssh} container stop {container}')
示例#12
0
    def start(self, params):
        if self.SWARM:
            CLI.info('Starting services...')
            os.system(
                f'docker stack deploy -c configs/docker/{self.COMPOSE_PREFIX}.yml -c configs/docker/{self.COMPOSE_PREFIX}.{self.environment_id}.yml {self.PROJECT_NAME}'
            )

        else:
            CLI.info('Starting containers...')

            containers = self.get_containers() if not params else params.split(
                ' ')

            steps = len(containers)

            for index, container in enumerate(containers):
                CLI.step(index + 1, steps, f'Starting {container}')
                os.system(
                    f'docker {self.docker_ssh} container start {container}')
示例#13
0
    def build(self, params=''):
        CLI.info(f'Building...')
        CLI.info(f'Params = {params}')
        CLI.info(f'Dockerfile = {self.configs_path}/docker/{self.DOCKER_FILE}')
        steps = 1

        CLI.step(1, steps, 'Building Docker image...')

        build_args = self.config['build']['args']
        build_args = ','.join(map('='.join, build_args.items()))
        build_kit = self.config['build']['kit']
        build_kit = 'DOCKER_BUILDKIT=1' if build_kit else ''

        if build_args != '':
            build_args = build_args.split(',')
            build_args = [f'--build-arg {arg}' for arg in build_args]
            build_args = ' '.join(build_args)

        CLI.info(f'Kit = {build_kit}')
        CLI.info(f'Args = {build_args}')

        os.system(
            f'time {build_kit} docker build . {build_args} -t {self.IMAGE_NAME} -f {self.configs_path}/docker/{self.DOCKER_FILE} {params}'
        )
示例#14
0
 def send_test_email(self):
     CLI.info('Sending test email...')
     os.system(
         f'docker {self.docker_ssh} exec -i {self.CONTAINER_APP} python manage.py sendtestemail --admins'
     )
示例#15
0
    def restart(self):
        CLI.info('Restarting...')
        steps = 4

        if self.SWARM:
            CLI.step(1, steps, 'Stopping and removing Docker app service...')

            for service in self.get_services():
                if service == self.CONTAINER_APP:
                    os.system(f'docker service rm {service}')

            CLI.step(2, steps, 'Recreating Docker swarm stack...')
            os.system(
                f'docker stack deploy -c configs/docker/{self.COMPOSE_PREFIX}.yml -c configs/docker/{self.COMPOSE_PREFIX}.{self.environment_id}.yml {self.PROJECT_NAME}'
            )

            CLI.step(
                3, steps,
                'Prune Docker images and volumes')  # todo prune on every node
            os.system(
                f'docker {self.docker_ssh} system prune --volumes --force')

            CLI.step(4, steps,
                     'Collecting static files')  # todo collect static
            app_container = self.get_containers_starts_with(self.CONTAINER_APP)

            if app_container:
                os.system(
                    f'docker {self.docker_ssh} exec -i {app_container[0]} python manage.py collectstatic --noinput --verbosity 0'
                )

        else:
            CLI.step(1, steps, 'Stopping and removing Docker containers...')

            for service in self.config['containers']['deploy'][
                    'zero_downtime'] + self.config['containers']['deploy'][
                        'restart']:
                container = self.get_container_name(service)
                os.popen(f'docker {self.docker_ssh} container stop {container}'
                         ).read()
                os.system(f'docker {self.docker_ssh} container rm {container}')

            CLI.step(2, steps, 'Recreating Docker containers...')
            os.system(
                f'docker-compose {self.docker_ssh} -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.yml -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.{self.environment_id}.yml --project-name={self.PROJECT_NAME} up -d'
            )
            # os.system(f'docker-compose {self.docker_ssh} -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.yml -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.{self.environment_id}.yml --project-name={self.PROJECT_NAME} up --remove-orphans -d')

            CLI.step(3, steps, 'Prune Docker images and volumes')
            os.system(
                f'docker {self.docker_ssh} system prune --volumes --force')

            CLI.step(4, steps, 'Collecting static files')
            os.system(
                f'docker {self.docker_ssh} exec -i {self.CONTAINER_APP} python manage.py collectstatic --noinput --verbosity 0'
            )
示例#16
0
    def reload(self):  # todo deploy swarm
        CLI.info('Reloading containers...')
        zero_downtime_services = self.config['containers']['deploy'][
            'zero_downtime']
        restart_services = self.config['containers']['deploy']['restart']

        steps = 5

        step = 1
        CLI.step(step, steps,
                 f'Zero downtime services: {zero_downtime_services}')

        for service in zero_downtime_services:
            container = self.get_container_name(service)
            os.system(
                f'docker-compose {self.docker_ssh} -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.yml -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.{self.environment_id}.yml --project-name={self.PROJECT_NAME} run -d --service-ports --name={container}_new {service}'
            )
            CLI.info(f'Renaming old container [{container}_old]...')

            if container in self.get_containers():
                os.system(
                    f'docker {self.docker_ssh} container rename {container} {container}_old'
                )
            else:
                CLI.info(f'{container}_old was not running')

            CLI.info(f'Renaming new container [{container}]...')
            os.system(
                f'docker {self.docker_ssh} container rename {container}_new {container}'
            )

        step += 1
        CLI.step(step, steps, 'Collecting static files')
        os.system(
            f'docker {self.docker_ssh} exec -i {self.CONTAINER_APP} python manage.py collectstatic --noinput --verbosity 0'
        )

        step += 1
        CLI.step(step, steps, 'Reloading webserver...')
        os.system(
            f'docker {self.docker_ssh} exec -it {self.CONTAINER_WEBSERVER} {self.WEBSERVER} -s reload'
        )

        step += 1
        CLI.step(
            step, steps,
            f'Stopping old zero downtime services: {zero_downtime_services}')

        for service in zero_downtime_services:
            container = self.get_container_name(service)

            if container in self.get_containers():
                CLI.info(f'Stopping old container [{container}_old]...')
                os.system(
                    f'docker {self.docker_ssh} container stop {container}_old')

                CLI.info(f'Removing old container [{container}_old]...')
                os.system(
                    f'docker {self.docker_ssh} container rm {container}_old')
            else:
                CLI.info(f'{container}_old was not running')

        step += 1
        CLI.step(step, steps, f'Restart services: {restart_services}')

        for service in restart_services:
            container = self.get_container_name(service)

            CLI.underline(f'Recreating {service} container ({container})...')

            if container in self.get_containers():
                CLI.info(f'Stopping container [{container}]...')
                os.system(
                    f'docker {self.docker_ssh} container stop {container}')

                CLI.info(f'Removing container [{container}]...')
                os.system(f'docker {self.docker_ssh} container rm {container}')

                CLI.info(f'Creating new container [{container}]...')
                os.system(
                    f'docker-compose {self.docker_ssh} -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.yml -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.{self.environment_id}.yml --project-name={self.PROJECT_NAME} run -d --service-ports --name={container} {service}'
                )
            else:
                CLI.info(f'{container} was not running')
示例#17
0
 def exec(self, params):
     container, command = params.split(' ', maxsplit=1)
     CLI.info(f'Executing command "{command}" in container {container}...')
     os.system(f'docker {self.docker_ssh} exec -it {container} {command}')
示例#18
0
 def psql(self):
     CLI.info('Starting psql...')
     env = self.load_environment()
     os.system(
         f'docker {self.docker_ssh} exec -it {self.CONTAINER_DB} psql -h {env["POSTGRES_HOST"]} -U {env["POSTGRES_USER"]} -d {env["POSTGRES_DBNAME"]} -W'
     )
示例#19
0
    def clean(self):  # todo clean on all nodes
        CLI.info('Cleaning...')
        steps = 1

        CLI.step(1, steps, 'Prune Docker images and volumes')
        os.system(f'docker {self.docker_ssh} system prune --volumes --force')
示例#20
0
 def ssh(self, params):
     CLI.info('Logging to container...')
     os.system(f'docker {self.docker_ssh} exec -it {params} /bin/sh')
示例#21
0
 def shell(self):
     CLI.info('Connecting to Django shell...')
     os.system(
         f'docker {self.docker_ssh} exec -i {self.CONTAINER_APP} python manage.py shell'
     )
示例#22
0
 def pull(self):
     CLI.info('Pulling docker image...')
     os.system(
         f'docker-compose {self.docker_ssh} -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.yml -f {self.configs_path}/docker/{self.COMPOSE_PREFIX}.{self.environment_id}.yml pull'
     )
示例#23
0
 def reload_webserver(self):
     CLI.info('Reloading webserver...')
     os.system(
         f'docker {self.docker_ssh} exec -it {self.CONTAINER_WEBSERVER} {self.WEBSERVER} -s reload'
     )
示例#24
0
    def upload(self, context='services'):
        CLI.info('Uploading...')
        steps = 1

        if context == 'services':
            CLI.step(
                1, steps,
                'Uploading configs for context "services" [webserver, cache, htpasswd]'
            )
        elif context == 'compose':
            CLI.step(
                1, steps,
                'Uploading configs for context "compose" [docker compose configs and environment]'
            )
        elif context == 'mantis':
            CLI.step(1, steps, 'Uploading configs for mantis [mantis.json]')
        else:
            CLI.error(f'Unknown context "{context}"')

        if self.environment_id == 'dev':
            print('Skipping for dev...')
        elif self.mode == 'host':
            CLI.warning(
                'Not uploading due to host mode! Be sure your configs on host are up to date!'
            )
        else:
            if context == 'services':
                os.system(
                    f'rsync -arvz -e \'ssh -p {self.port}\' -rvzh --progress {self.cache_config} {self.user}@{self.host}:/home/{self.user}/public_html/web/configs/{self.CACHE}/'
                )
                os.system(
                    f'rsync -arvz -e \'ssh -p {self.port}\' -rvzh --progress {self.webserver_config} {self.user}@{self.host}:/home/{self.user}/public_html/web/configs/{self.WEBSERVER}/'
                )
                os.system(
                    f'rsync -arvz -e \'ssh -p {self.port}\' -rvzh --progress {self.webserver_config_proxy} {self.user}@{self.host}:/etc/nginx/conf.d/proxy/'
                )
                os.system(
                    f'rsync -arvz -e \'ssh -p {self.port}\' -rvzh --progress {self.htpasswd} {self.user}@{self.host}:/etc/nginx/conf.d/'
                )

            elif context == 'mantis':
                os.system(
                    f'rsync -arvz -e \'ssh -p {self.port}\' -rvzh --progress {self.config_file} {self.user}@{self.host}:/home/{self.user}/public_html/web/configs/'
                )

            elif context == 'compose':
                os.system(
                    f'rsync -arvz -e \'ssh -p {self.port}\' -rvzh --progress {self.environment_file} {self.user}@{self.host}:/home/{self.user}/public_html/web/configs/environments/'
                )

                for config in self.compose_configs:
                    os.system(
                        f'rsync -arvz -e \'ssh -p {self.port}\' -rvzh --progress {config} {self.user}@{self.host}:/home/{self.user}/public_html/web/configs/docker/'
                    )
示例#25
0
def execute(manager, command, params=None):
    if manager.environment_id is None:
        CLI.error('Missing environment')

    else:
        manager_method = {
            '--build': 'build',
            '-b': 'build',
            '--push': 'push',
            '--pull': 'pull',
            '-p': 'pull',
            '--upload': 'upload',
            '--upload-docker-configs': 'upload_docker_configs',
            '-u': 'upload',
            '--reload': 'reload',
            '--restart': 'restart',
            '--deploy': 'deploy',
            '-d': 'deploy',
            '--stop': 'stop',
            '--start': 'start',
            '--clean': 'clean',
            '-c': 'clean',
            '--remove': 'remove',
            '--reload-webserver': 'reload_webserver',
            '--restart-proxy': 'restart_proxy',
            '--status': 'status',
            '-s': 'status',
            '--networks': 'networks',
            '-n': 'networks',
            '--logs': 'logs',
            '-l': 'logs',
            '--shell': 'shell',
            '--ssh': 'ssh',
            '--manage': 'manage',
            '--exec': 'exec',
            '--psql': 'psql',
            '--pg-dump': 'pg_dump',
            '--pg-restore': 'pg_restore',
            '--send-test-email': 'send_test_email',
        }.get(command)

        methods_with_params = [
            'build', 'ssh', 'exec', 'manage', 'pg_restore', 'start', 'stop',
            'logs', 'remove', 'upload'
        ]

        if manager_method is None or not hasattr(manager, manager_method):
            CLI.error(
                f'Invalid command "{command}" \n\nUsage: mantis <ENVIRONMENT> '
                '\n--no-ssh |'
                '\n--build/-b |'
                '\n--push |'
                '\n--pull/-p |'
                '\n--upload/-u | '
                '\n--deploy/-d | '
                '\n--stop | '
                '\n--start | '
                '\n--reload | '
                '\n--restart | '
                '\n--remove | '
                '\n--clean/-c | '
                '\n--status/-s | '
                '\n--networks/-n | '
                '\n--logs/-l | '
                '\n--reload-webserver | '
                '\n--restart-proxy | '
                '\n--manage | '
                '\n--shell | '
                '\n--ssh | '
                '\n--exec | '
                '\n--psql | '
                '\n--pg-dump | '
                '\n--pg-restore | '
                '\n--send-test-email')
        else:
            if manager_method in methods_with_params and params:
                getattr(manager, manager_method)(params)
            else:
                getattr(manager, manager_method)()
示例#26
0
 def manage(self, params):
     CLI.info('Django manage...')
     os.system(
         f'docker {self.docker_ssh} exec -ti {self.CONTAINER_APP} python manage.py {params}'
     )