def prompt_select_instance(instances): print("There are multiple matching instances!") template = "\t{i}) {name} {address}:{port} {id} {local}" for i, instance in enumerate(instances): local = "(local)" if armada_utils.is_local_container(instance['ServiceID']) else "" print(template.format(i=i + 1, name=instance['ServiceName'], address=instance['Address'], port=instance['ServicePort'], id=instance['ServiceID'], local=local)) try: selection = int(input("Please select one: ")) if 0 >= selection > len(instances): raise ValueError except ValueError: raise armada_utils.ArmadaCommandException("Invalid choice!") except KeyboardInterrupt: raise armada_utils.ArmadaCommandException("Aborted.") selection -= 1 return instances[selection]
def command_stop(args): microservice_handles = args.microservice_handle or [os.environ['MICROSERVICE_NAME']] if not microservice_handles: raise ValueError('No microservice name or container id supplied.') armada_utils.notify_about_detected_dev_environment(microservice_handles[0]) services = {microservice_handle: armada_utils.get_matched_containers(microservice_handle) for microservice_handle in microservice_handles} for microservice_handle, instances in services.items(): instances_count = len(instances) if instances_count > 1 and not args.all: raise armada_utils.ArmadaCommandException( 'There are too many ({instances_count}) matching containers for service: {microservice_handle}. ' 'Provide more specific container_id or microservice name or use -a/--all flag.'.format(**locals())) were_errors = False for microservice_handle, instances in services.items(): instances_count = len(instances) if instances_count > 1: print('Stopping {instances_count} services {microservice_handle}...'.format(**locals())) else: microservice_name = instances[0]['ServiceName'] container_id = instances[0]["ServiceID"].split(':')[0] print('Stopping service {microservice_name} ({container_id})...'.format(**locals())) for i, instance in enumerate(instances): try: if instances_count > 1: print('[{0}/{1}]'.format(i + 1, instances_count)) container_id = instance['ServiceID'].split(':')[0] payload = {'container_id': container_id} ship_name = instance['Address'] result = armada_api.post('stop', payload, ship_name=ship_name) if result['status'] == 'error' and result['error'].startswith( 'armada API exception: ValueError - Cannot find ship:'): payload['force'] = True result = armada_api.post('stop', payload) if result['status'] == 'ok': print('Service {container_id} has been stopped.'.format(**locals())) print() else: raise ArmadaCommandException('Stopping error: {0}'.format(result['error'])) except: traceback.print_exc() were_errors = True if were_errors: sys.exit(1)
def command_restart(args): microservice_handle = args.microservice_handle or os.environ[ 'MICROSERVICE_NAME'] if not microservice_handle: raise ValueError('No microservice name or container id supplied.') armada_utils.notify_about_detected_dev_environment(microservice_handle) instances = armada_utils.get_matched_containers(microservice_handle) instances_count = len(instances) if instances_count > 1: if not args.all: raise armada_utils.ArmadaCommandException( 'There are too many ({instances_count}) matching containers. ' 'Provide more specific container_id or microservice name or use -a/--all flag.' .format(**locals())) print('Restarting {instances_count} services {microservice_handle}...'. format(**locals())) else: microservice_name = instances[0]['ServiceName'] container_id = instances[0]["ServiceID"].split(':')[0] print('Restarting service {microservice_name} ({container_id})...'. format(**locals())) were_errors = False for i, instance in enumerate(instances): try: if instances_count > 1: print('[{0}/{1}]'.format(i + 1, instances_count)) container_id = instance['ServiceID'].split(':')[0] payload = {'container_id': container_id} if args.ship: payload['target_ship'] = args.ship payload['force'] = args.force print( 'Checking if there is new image version. May take few minutes if download is needed...' ) ship_name = instance['Address'] result = armada_api.post('restart', payload, ship_name=ship_name) if result['status'] == 'ok': new_container_id = result['container_id'] print( 'Service has been restarted and is running in container {new_container_id} ' 'available at addresses:'.format(**locals())) for service_address, docker_port in six.iteritems( result['endpoints']): print(' {0} ({1})'.format(service_address, docker_port)) if instances_count > 1: print() else: raise armada_utils.ArmadaCommandException(result['error']) except armada_utils.ArmadaCommandException as e: print("ArmadaCommandException: {0}".format(str(e))) were_errors = True except: traceback.print_exc() were_errors = True if were_errors: sys.exit(1)
def command_ssh(args): microservice_name = args.microservice_name or os.environ[ 'MICROSERVICE_NAME'] if not microservice_name: raise ValueError('No microservice name supplied.') armada_utils.notify_about_detected_dev_environment(microservice_name) instances = [ i for i in armada_utils.get_matched_containers(microservice_name) if 'Status' not in i ] if args.local: instances = [ i for i in instances if armada_utils.is_local_container(i['ServiceID']) ] instances_count = len(instances) if instances_count < 1: raise armada_utils.ArmadaCommandException( 'There are no running containers with microservice: ' '{microservice_name}'.format(**locals())) if instances_count > 1: if args.no_prompt: raise armada_utils.ArmadaCommandException( 'There are too many ({instances_count}) matching containers. ' 'Provide more specific container_id or microservice name.'. format(**locals())) instance = prompt_select_instance(instances) else: instance = instances[0] if 'Status' in instance: raise armada_utils.ArmadaCommandException( 'Cannot connect to not running service.') service_id = instance['ServiceID'] container_id = service_id.split(':')[0] payload = {'container_id': container_id} is_local = armada_utils.is_local_container(container_id) if args.command: command = ' '.join(args.command) else: command = 'bash' args.tty = True args.interactive = True tty = '-t' if args.tty else '' interactive = '-i' if args.interactive else '' term = os.environ.get('TERM') or 'dummy' command = pipes.quote(command) docker_command = 'docker exec {interactive} {tty} {container_id} env TERM={term} ' \ 'sh -c {command}'.format(**locals()) if is_local: print("Connecting to {0}...".format(instance['ServiceName'])) ssh_args = shlex.split(docker_command) else: ssh_host = instance['Address'] docker_key_file = os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', 'keys/docker.key') remote_ssh_chunk = ( 'ssh -t {tty} -p 2201 -i {docker_key_file} ' '-o StrictHostKeyChecking=no -o LogLevel=ERROR -o UserKnownHostsFile=/dev/null ' 'docker@{ssh_host}').format(**locals()) ssh_args = shlex.split(remote_ssh_chunk) ssh_args.extend(('sudo', docker_command)) print("Connecting to {0} on host {1}...".format( instance['ServiceName'], ssh_host)) os.execvpe(ssh_args[0], ssh_args, { 'LANG': 'C.UTF-8', 'LC_ALL': 'C.UTF-8', })