def _start(env): click.echo('Starting services...') run('mkdir -p %s' % env['DB_BACKUP_MOUNT']) with cd(BASE_DIR): run( 'docker-compose up -d --remove-orphans', capture_output=False, env=env, ) root_url = _root_url(env) click.echo( '\nDone. It may take a few moments for the app to come online at:\n' ' -> %s\n\n' 'If it isn\'t available immediately, please check again after ' 'a minute or two. If you experience any problems with the ' 'installation, please check the Troubleshooting guide:\n' ' -> https://github.com/teamplify/teamplify-runner/#troubleshooting' '' % root_url, ) if env['WEB_HOST'].lower() == 'localhost': click.echo( '\nWARNING: you\'re running Teamplify on localhost. This is ' 'probably OK if you only need to run a demo on your local machine. ' 'However, in this mode it will not be available to anyone from the ' 'network. If you\'d like to make it available on the network, you ' 'need to provide a publicly visible domain name that points to ' 'this server.', )
def _restore(env, filename): click.echo('Copying the backup...') restore_filename = 'restore.sql.gz' restore_mount = os.path.join(env['DB_BACKUP_MOUNT'], restore_filename) run('cp %s %s' % (filename, restore_mount)) try: sql = ( 'docker exec -e MYSQL_PWD="{password}" teamplify_db mysql -u{user} ' '-e "%s"'.format( user=env['DB_USER'], password=env['DB_PASSWORD'], )) click.echo('Dropping and re-creating the DB...') run(sql % ('drop database %s' % env['DB_NAME'])) run(sql % ('create database %s' % env['DB_NAME'])) click.echo('Restoring DB backup...') run( 'docker exec -e MYSQL_PWD="{password}" teamplify_db bash -c "' 'gunzip < {filename} | mysql -u{user} {db}"'.format( filename='/'.join(('/backup', restore_filename)), user=env['DB_USER'], password=env['DB_PASSWORD'], db=env['DB_NAME'], ), ) finally: run('rm %s' % restore_mount) click.echo('Done.')
def _create_admin(env, email, full_name): click.echo('Creating admin...') cmd = 'docker exec -it teamplify_app ' \ '/code/manage.py createadmin --email %s' % email if full_name: cmd += ' --full-name "%s"' % full_name run(cmd, capture_output=False, env=env)
def _stop(env): click.echo('Stopping services...') with cd(BASE_DIR): run( 'docker-compose rm -v --stop --force', capture_output=False, env=env, )
def _remove_unused_images(): unused_images = run( 'docker images -f reference=teamplify/server -f dangling=true -q', suppress_output=True, ).stdout_lines click.echo('Cleanup: %s stale image(s) found' % len(unused_images)) if unused_images: # Suppress errors because it might be possible # that some images are still used run( 'docker rmi %s' % ' '.join(unused_images), suppress_output=True, raise_on_error=False, )
def _running(env): with cd(BASE_DIR): output = run( 'docker-compose ps -q app', suppress_output=True, env=env, ).stdout_lines return bool(output)
def _image_id(name): try: return run( 'docker image ls -q --no-trunc %s' % name, suppress_output=True, ).stdout_lines[0] except IndexError: return None
def update(ctx): """ Update to the latest version """ env = ctx.obj['env'] if _running(env): current_image = _image_id(env['IMAGE_APP']) run('docker pull %s' % env['IMAGE_APP'], capture_output=False) new_image = _image_id(env['IMAGE_APP']) if current_image != new_image: _stop(env) _start(env) click.echo('') else: run('docker pull %s' % env['IMAGE_APP']) _remove_unused_images() click.echo('Done.')
def update(ctx): """ Update to the latest version """ env = ctx.obj['env'] image_name = 'teamplify/server:%s' % env['MAIN_UPDATE_CHANNEL'] if _running(env): current_image = _image_id(image_name) run('docker pull %s' % image_name, capture_output=False) new_image = _image_id(image_name) if current_image != new_image: _stop(env) _start(env) click.echo('') else: run('docker pull %s' % image_name) _remove_unused_images() click.echo('Done.')
def _backup(env, filename=None): now = datetime.utcnow().replace(microsecond=0) default_filename = '%s_%s.sql.gz' % ( env['DB_NAME'], now.isoformat('_').replace(':', '-'), ) if not filename: target_file = default_filename elif os.path.isdir(filename): target_file = os.path.join(filename, default_filename) else: target_file = filename temp_filename = os.path.join('/backup', default_filename) cleanup_on_error = not os.path.exists(target_file) # check for write access on the host run('touch %s' % target_file) # check for write access inside docker run('docker exec teamplify_db bash -c "touch %s"' % temp_filename) command = ('MYSQL_PWD={password} mysqldump --single-transaction -u{user} ' '-h {host} {db} | gzip > {filename}'.format( user=env['DB_USER'], password=env['DB_PASSWORD'], host='localhost', db=env['DB_NAME'], filename=os.path.join('/backup', default_filename), )) click.echo('Making backup of Teamplify DB to:\n -> %s' % target_file) click.echo('Please wait...') try: run( 'docker exec teamplify_db bash -c "{command}"'.format( command=command, ), exit_on_error=False, ) except RuntimeError: if cleanup_on_error: run('rm %s' % target_file) exit(1) run('mv {source} {target}'.format( source=os.path.join(env['DB_BACKUP_MOUNT'], default_filename), target=target_file, )) click.echo('Done.')
def erase(ctx, quiet): """ Erase all of Teamplify data and Docker images """ if not quiet: confirm = input( '\nIMPORTANT: This command will erase all of the data stored in ' 'the built-in Teamplify DB, and also remove all Docker images, ' 'volumes, and networks used by Teamplify.\n\n' 'Do you want to confirm the deletion of all Teamplify data (y/N)? ', ) if confirm.lower() != 'y': click.echo('Erase command cancelled, exiting') return env = ctx.obj['env'] _stop(env) click.echo('') networks = run( 'docker network ls -f name=teamplify_runner* -q', suppress_output=True, ).stdout_lines if networks: click.echo('Removing %s Docker network(s):' % len(networks)) run('docker network rm %s' % ' '.join(networks), raise_on_error=False) volumes = run( 'docker volume ls -f name=teamplify_runner* -q', suppress_output=True, ).stdout_lines if volumes: click.echo('Removing %s Docker volume(s):' % len(volumes)) run('docker volume rm %s' % ' '.join(volumes), raise_on_error=False) click.echo('Removing Docker images:') images = [] for image_id, reference in IMAGES.items(): if image_id == 'app': for channel in ('stable', 'latest'): images.append('%s:%s' % (reference, channel)) else: images.append(reference) run('docker rmi %s' % ' '.join(images), raise_on_error=False) click.echo('Done.')