def run_action_with_check_mode(run_check, run_apply, skip_check, quiet=False, always_skip_check=False): if always_skip_check: user_wants_to_apply = ask( 'This command will apply without running the check first. Continue?', quiet=quiet) elif skip_check: user_wants_to_apply = ask('Do you want to apply without running the check first?', quiet=quiet) else: exit_code = run_check() if exit_code == 1: # this means there was an error before ansible was able to start running return exit_code elif exit_code == 0: puts(color_success(u"✓ Check completed with status code {}".format(exit_code))) user_wants_to_apply = ask('Do you want to apply these changes?', quiet=quiet) else: puts(color_error(u"✗ Check failed with status code {}".format(exit_code))) user_wants_to_apply = ask('Do you want to try to apply these changes anyway?', quiet=quiet) exit_code = 0 if user_wants_to_apply: exit_code = run_apply() if exit_code == 0: puts(color_success(u"✓ Apply completed with status code {}".format(exit_code))) else: puts(color_error(u"✗ Apply failed with status code {}".format(exit_code))) return exit_code
def describe(migration): puts('\nMembership') with indent(): puts(get_membership(migration.target_couch_config).get_printable()) puts('\nDB Info') print_db_info(migration.target_couch_config) puts('\nShard allocation') diff_with_db = None if os.path.exists(migration.shard_plan_path): diff_with_db = diff_plan(migration) if diff_with_db: puts(color_highlight('DB allocation differs from plan:\n')) puts("{}\n\n".format(diff_with_db)) else: puts(color_success('DB allocation matches plan.')) if not diff_with_db: print_shard_table([ get_shard_allocation(migration.target_couch_config, db_name) for db_name in sorted( get_db_list(migration.target_couch_config.get_control_node())) ]) puts('\nShard count by node') print_shard_allocation_by_node([ get_shard_allocation(migration.target_couch_config, db_name) for db_name in sorted( get_db_list(migration.target_couch_config.get_control_node())) ]) return 0
def commit(migration, ansible_context): print_allocation(migration) alloc_docs_by_db = {plan.db_name: plan for plan in migration.shard_plan} puts(color_summary("Checking shards on disk vs plan. Please wait.")) if not assert_files(migration, alloc_docs_by_db, ansible_context): puts(color_error("Some shard files are not where we expect. Have you run 'migrate'?")) puts(color_error("Aborting")) return 1 else: puts(color_success("All shards appear to be where we expect according to the plan.")) if ask("Are you sure you want to update the Couch Database config?"): commit_migration(migration) diff_with_db = diff_plan(migration) if diff_with_db: puts(color_error('DB allocation differs from expected:\n')) puts("{}\n\n".format(diff_with_db)) puts("Check the DB state and logs and maybe try running 'commit' again?") return 1 puts(color_highlight("New shard allocation:\n")) print_shard_table([ get_shard_allocation(migration.target_couch_config, db_name) for db_name in sorted(get_db_list(migration.target_couch_config.get_control_node())) ]) return 0
def aws_sign_in(aws_profile, duration_minutes=DEFAULT_SIGN_IN_DURATION_MINUTES, force_new=False): """ Create a temp session through MFA for a given aws profile :param aws_profile: The name of an existing aws profile to create a temp session for :param duration_minutes: How long to set the session expiration if a new one is created :param force_new: If set to True, creates new credentials even if valid ones are found :return: The name of temp session profile. (Always the passed in profile followed by ':session') """ aws_session_profile = '{}:session'.format(aws_profile) if not force_new \ and _has_valid_session_credentials(aws_session_profile): return aws_session_profile default_username = get_default_username() if default_username.is_guess: username = input("Enter username associated with credentials [{}]: ".format( default_username)) or default_username print_help_message_about_the_commcare_cloud_default_username_env_var(username) else: username = default_username mfa_token = input("Enter your MFA token: ") generate_session_profile(aws_profile, username, mfa_token, duration_minutes) puts(color_success(u"✓ Sign in accepted")) puts("You will be able to use AWS from the command line for the next {} minutes." .format(duration_minutes)) puts(color_notice( "To use this session outside of commcare-cloud, " "prefix your command with AWS_PROFILE={}:session".format(aws_profile))) return aws_session_profile
def run(self, args, unknown_args): environment = get_environment(args.env_name) try: environment.check() except Exception: puts(color_error(u"✗ The environment has the following error:")) raise else: puts(color_success(u"✓ The environment configuration is valid."))
def run(self, args, unknown_args): limit = args.limit environment = get_environment(args.env_name) if limit: environment.inventory_manager.subset(limit) with open(environment.paths.known_hosts, 'r', encoding='utf-8') as known_hosts: original_keys_by_host = _get_host_key_map( [line.strip() for line in known_hosts.readlines()] ) procs = {} for hostname in environment.inventory_hostname_map: port = '22' if ':' in hostname: hostname, port = hostname.split(':') cmd = 'ssh-keyscan -T 10 -p {port} {hostname},$(dig +short {hostname})'.format( hostname=hostname, port=port ) procs[hostname] = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) lines = [] error_hosts = set() for hostname, proc in procs.items(): sys.stdout.write('[{}]: '.format(hostname)) proc.wait() error, host_lines = _get_lines(proc) if error: sys.stdout.write(error) else: sys.stdout.write(str(color_success('fetched key\n'))) lines.extend(host_lines) updated_keys_by_host = _get_host_key_map(lines) all_keys = set(original_keys_by_host) | set(updated_keys_by_host) lines = [] for host_key_type in sorted(all_keys): host, key_type = host_key_type original = original_keys_by_host.pop(host_key_type, None) updated = updated_keys_by_host.get(host_key_type, None) if updated and original: if updated != original: print(color_changed('Updating key: {} {}'.format(*host_key_type))) elif updated: print(color_added('Adding key: {} {}'.format(*host_key_type))) elif original: if limit or host in error_hosts: # if we're limiting or there was an error keep original key updated = original else: print(color_removed('Removing key: {} {}'.format(*host_key_type))) if updated: lines.append('{} {} {}'.format(host, key_type, updated)) with open(environment.paths.known_hosts, 'w', encoding='utf-8') as known_hosts: known_hosts.write('\n'.join(sorted(lines))) try: environment.check_known_hosts() except EnvironmentException as e: print(color_error(str(e))) return 1 return 0