Example #1
0
def get_ansible_inventory():
    log = logger.getlogger()
    inventory_choice = None
    dynamic_inventory_path = get_dynamic_inventory_path()
    software_hosts_file_path = (
        os.path.join(get_playbooks_path(), 'software_hosts'))

    heading1("Software hosts inventory setup\n")

    dynamic_inventory = None

    # If dynamic inventory contains clients prompt user to use it
    if (dynamic_inventory is not None and
            len(set(_get_hosts_list(dynamic_inventory)) -
                set(['deployer', 'localhost'])) > 0):
        print("Ansible Dynamic Inventory found:")
        print("--------------------------------")
        print(_get_groups_hosts_string(dynamic_inventory))
        print("--------------------------------")
        validate_software_inventory(dynamic_inventory)
        if click.confirm('Do you want to use this inventory?'):
            print("Using Ansible Dynamic Inventory")
            inventory_choice = dynamic_inventory_path
        else:
            print("NOT using Ansible Dynamic Inventory")

    # If dynamic inventory has no hosts or user declines to use it
    if inventory_choice is None:
        while True:
            # Check if software inventory file exists
            if os.path.isfile(software_hosts_file_path):
                print("Software inventory file found at '{}':"
                      .format(software_hosts_file_path))
            # If no software inventory file exists create one using template
            else:
                rlinput("Press enter to create client node inventory")
                _create_new_software_inventory(software_hosts_file_path)

            # If still no software inventory file exists prompt user to
            # exit (else start over to create one).
            if not os.path.isfile(software_hosts_file_path):
                print("No inventory file found at '{}'"
                      .format(software_hosts_file_path))
                if click.confirm('Do you want to exit the program?'):
                    sys.exit(1)
                else:
                    continue

            # Menu items can modified to show validation results
            continue_msg = 'Continue with current inventory'
            edit_msg = 'Edit inventory file'
            exit_msg = 'Exit program'
            ssh_config_msg = 'Configure Client Nodes for SSH Key Access'
            menu_items = []

            # Validate software inventory
            inv_count = len(_validate_inventory_count(software_hosts_file_path,
                                                      0))
            print(f'Validating software inventory ({inv_count} nodes)...')
            if validate_software_inventory(software_hosts_file_path):
                print(bold("Validation passed!"))
            else:
                print(bold("Unable to complete validation"))
                continue_msg = ("Continue with inventory as-is - "
                                "WARNING: Validation incomplete")
                menu_items.append(ssh_config_msg)

            # Prompt user
            menu_items += [continue_msg, edit_msg, exit_msg]
            choice, item = get_selection(menu_items)
            print(f'Choice: {choice} Item: {item}')
            if item == ssh_config_msg:
                configure_ssh_keys(software_hosts_file_path)
            elif item == continue_msg:
                print("Using '{}' as inventory"
                      .format(software_hosts_file_path))
                inventory_choice = software_hosts_file_path
                break
            elif item == edit_msg:
                click.edit(filename=software_hosts_file_path)
            elif item == exit_msg:
                sys.exit(1)

    if inventory_choice is None:
        log.error("Software inventory file is required to continue!")
        sys.exit(1)
    log.debug("User software inventory choice: {}".format(inventory_choice))

    return inventory_choice
Example #2
0
def configure_ssh_keys(software_hosts_file_path):
    """Configure SSH keys for Ansible software hosts

    Scan for SSH key pairs in home directory, and if called using
    'sudo' also in "login" user's home directory. Allow user to create
    a new SSH key pair if 'default_ssh_key_name' doesn't already exist.
    If multiple choices are available user will be prompted to choose.
    Selected key pair is copied into "login" user's home '.ssh'
    directory if necessary. Selected key pair is then copied to all
    hosts listed in 'software_hosts' file via 'ssh-copy-id', and
    finally assigned to the 'ansible_ssh_private_key_file' var in
    the 'software_hosts' '[all:vars]' section.

    Args:
        software_hosts_file_path (str): Path to software inventory file
    """
    log = logger.getlogger()
    default_ssh_key_name = "powerup"

    ssh_key_options = get_existing_ssh_key_pairs(no_root_keys=True)

    user_name, user_home_dir = get_user_and_home()
    if os.path.join(user_home_dir, ".ssh",
                    default_ssh_key_name) not in ssh_key_options:
        ssh_key_options.insert(0, 'Create New "powerup" Key Pair')

    if len(ssh_key_options) == 1:
        item = ssh_key_options[0]
    elif len(ssh_key_options) > 1:
        print(bold("\nSelect an SSH key to use:"))
        choice, item = get_selection(ssh_key_options)

    if item == 'Create New "powerup" Key Pair':
        ssh_key = create_ssh_key_pair(default_ssh_key_name)
    else:
        ssh_key = item

    ssh_key = copy_ssh_key_pair_to_user_dir(ssh_key)

    add_software_hosts_global_var(
        software_hosts_file_path,
        "ansible_ssh_common_args='-o StrictHostKeyChecking=no'")

    hostvars = get_ansible_hostvars(software_hosts_file_path)

    run = True
    while run:
        global_user = None
        global_pass = None
        header_printed = False
        header_msg = bold('\nGlobal client SSH login credentials required')
        for host in _validate_inventory_count(software_hosts_file_path, 0):
            if global_user is None and 'ansible_user' not in hostvars[host]:
                print(header_msg)
                header_printed = True
                global_user = rlinput('username: '******'ansible_user={global_user}')
            if (global_pass is None and
                    'ansible_ssh_pass' not in hostvars[host]):
                if not header_printed:
                    print(header_msg)
                global_pass = getpass('password: '******'Retry', 'Continue', 'Exit'])
            if choice == "1":
                pass
            elif choice == "2":
                run = False
            elif choice == "3":
                log.debug('User chooses to exit.')
                sys.exit('Exiting')
        else:
            print()
            log.info("SSH key successfully copied to all hosts\n")
            run = False

    add_software_hosts_global_var(software_hosts_file_path,
                                  f'ansible_ssh_private_key_file={ssh_key}')