Example #1
0
    def get_ansible_tasks(self):
        # Load playbooks
        loader = DataLoader()
        inventory = InventoryManager(loader=loader, sources=[self.args.host])
        variable_manager = VariableManager(loader=loader, inventory=inventory)

        pb = Playbook.load(self.args.playbook,
                           variable_manager=variable_manager,
                           loader=loader)

        plays = pb.get_plays()

        all_vars = {}
        all_vars.update(variable_manager.get_vars(host=Host(self.args.host)))
        # enumarate all available plays
        tasks = set()
        for play in plays:
            all_vars.update(variable_manager.get_vars(play=play))

        templar = Templar(loader=loader, variables=all_vars)
        for play in plays:
            new_play = play.copy()
            new_play.post_validate(templar)
            for role in new_play.get_roles():
                u = Unwrap()
                block_container = role.compile(new_play)
                u.unwrap_blocks(block_container)
                tasks.update(u.tasks)

        return templar, tasks
Example #2
0
    def inventory_hosts_by_group(self):
        """
        filename is a path to an ansible inventory file

        returns a mapping of group names ("webworker", "proxy", etc.)
        to lists of hostnames as listed in the inventory file.
        ("Hostnames" can also be IP addresses.)
        If the hostname in the file includes :<port>, that will be included here as well.

        """
        inventory = self.inventory_manager
        var_manager = VariableManager(self._ansible_inventory_data_loader,
                                      inventory)
        # use the ip address specified by ansible_host to ssh in if it's given
        ssh_addr_map = {
            host.name:
            var_manager.get_vars(host=host).get('ansible_host', host.name)
            for host in inventory.get_hosts()
        }
        # use the port specified by ansible_port to ssh in if it's given
        port_map = {
            host.name: var_manager.get_vars(host=host).get('ansible_port')
            for host in inventory.get_hosts()
        }
        return {
            group: [
                '{}:{}'.format(ssh_addr_map[host], port_map[host])
                if port_map[host] is not None else ssh_addr_map[host]
                for host in hosts
            ]
            for group, hosts in
            self.inventory_manager.get_groups_dict().items()
        }
Example #3
0
    def test_variable_manager_role_vars_dependencies(self):
        '''
        Tests vars from role dependencies with duplicate dependencies.
        '''
        mock_inventory = MagicMock()

        fake_loader = DictDataLoader({
            # role common-role
            '/etc/ansible/roles/common-role/tasks/main.yml':
            """
            - debug: msg="{{role_var}}"
            """,
            # We do not need allow_duplicates: yes for this role
            # because eliminating duplicates is done by the execution
            # strategy, which we do not test here.

            # role role1
            '/etc/ansible/roles/role1/vars/main.yml':
            """
            role_var: "role_var_from_role1"
            """,
            '/etc/ansible/roles/role1/meta/main.yml':
            """
            dependencies:
              - { role: common-role }
            """,

            # role role2
            '/etc/ansible/roles/role2/vars/main.yml':
            """
            role_var: "role_var_from_role2"
            """,
            '/etc/ansible/roles/role2/meta/main.yml':
            """
            dependencies:
              - { role: common-role }
            """,
        })

        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        v._fact_cache = defaultdict(dict)

        play1 = Play.load(dict(
            hosts=['all'],
            roles=['role1', 'role2'],
        ),
                          loader=fake_loader,
                          variable_manager=v)

        # The task defined by common-role exists twice because role1
        # and role2 depend on common-role.  Check that the tasks see
        # different values of role_var.
        blocks = play1.compile()
        task = blocks[1].block[0]
        res = v.get_vars(play=play1, task=task)
        self.assertEqual(res['role_var'], 'role_var_from_role1')

        task = blocks[2].block[0]
        res = v.get_vars(play=play1, task=task)
        self.assertEqual(res['role_var'], 'role_var_from_role2')
Example #4
0
class AnsibleInventory(object):
    virt_component = 'virtual_component'

    def __init__(self, inventory: str = None, extra_vars: dict = None):
        self._logger = logging.getLogger(self.__class__.__module__)
        self.inventory = inventory
        self.loader = DataLoader()
        self._logger.info('Loading inventory: %s' % inventory)
        self._logger.debug('Extra variables: %s' % extra_vars)
        self.inv_mgr = InventoryManager(loader=self.loader,
                                        sources=self.inventory)
        self.var_mgr = VariableManager(loader=self.loader,
                                       inventory=self.inv_mgr)
        self.var_mgr._extra_vars = extra_vars or dict()

    def get_hosts_containing(self, var: str = None) -> list:
        hosts = []

        for host in self.inv_mgr.get_hosts():
            # If no specific var provided, then add it to the list
            if not var:
                hosts.append(host)
                continue

            # If var is provided and not part of host vars, ignore it
            host_vars = self.var_mgr.get_vars(host=host)
            if var not in host_vars:
                continue

            # Var has been found so adding it
            hosts.append(host)

        return hosts

    def get_host_vars(self, host: Host):
        data = self.var_mgr.get_vars(host=host)
        templar = Templar(variables=data, loader=self.loader)
        return templar.template(data, fail_on_undefined=False)

    def get_virtual_components(self) -> list:
        virtual_components = []
        for group in self.inv_mgr.get_groups_dict():
            group_vars = self.inv_mgr.groups[group].get_vars()

            if self.virt_component in group_vars:
                vcmp_type = group_vars.get(self.virt_component)
                group_vars.pop('virtual_component')
                vcmp_impl = group_vars.get('implementation')
                group_vars.pop('implementation')
                hosts = self.inv_mgr.groups[group].get_hosts()
                vcmp = AnsibleVirtualComponent(name=group,
                                               type=vcmp_type,
                                               implementation=vcmp_impl,
                                               members=hosts,
                                               **group_vars)

                virtual_components.append(vcmp)
        return virtual_components
    def test_variable_manager_role_vars_dependencies(self):
        '''
        Tests vars from role dependencies with duplicate dependencies.
        '''
        mock_inventory = MagicMock()

        fake_loader = DictDataLoader({
            # role common-role
            '/etc/ansible/roles/common-role/tasks/main.yml': """
            - debug: msg="{{role_var}}"
            """,
            # We do not need allow_duplicates: yes for this role
            # because eliminating duplicates is done by the execution
            # strategy, which we do not test here.

            # role role1
            '/etc/ansible/roles/role1/vars/main.yml': """
            role_var: "role_var_from_role1"
            """,
            '/etc/ansible/roles/role1/meta/main.yml': """
            dependencies:
              - { role: common-role }
            """,

            # role role2
            '/etc/ansible/roles/role2/vars/main.yml': """
            role_var: "role_var_from_role2"
            """,
            '/etc/ansible/roles/role2/meta/main.yml': """
            dependencies:
              - { role: common-role }
            """,
        })

        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        v._fact_cache = defaultdict(dict)

        play1 = Play.load(dict(
            hosts=['all'],
            roles=['role1', 'role2'],
        ), loader=fake_loader, variable_manager=v)

        # The task defined by common-role exists twice because role1
        # and role2 depend on common-role.  Check that the tasks see
        # different values of role_var.
        blocks = play1.compile()
        task = blocks[1].block[0]
        res = v.get_vars(play=play1, task=task)
        self.assertEqual(res['role_var'], 'role_var_from_role1')

        task = blocks[2].block[0]
        res = v.get_vars(play=play1, task=task)
        self.assertEqual(res['role_var'], 'role_var_from_role2')
    def playbookrun(self, playbook_path):

        playbook_inventory = InventoryManager(loader=self.loader,
                                              sources=['playbook_hosts'])
        playbook_variable = VariableManager(loader=self.loader,
                                            inventory=playbook_inventory)
        playbook_inventory.add_host(host="192.168.122.102",
                                    port=22,
                                    group='all')
        playbook_inventory.add_group('test_group')
        playbook_inventory.add_host(host="192.168.122.103",
                                    port=22,
                                    group="test_group")
        print(playbook_inventory.get_groups_dict())
        host = playbook_inventory.get_host(hostname="192.168.122.102")
        host.set_variable("ansible_ssh_pass", "/*bankentan123")
        host.set_variable("ansible_ssh_user", "root")
        host.set_variable("ansible_ssh_port", "22")
        host.set_variable("ansible_ssh_host", "192.168.122.102")
        host.set_variable("myname", "bankentan")
        vars = playbook_variable.get_vars(host=host)
        print(vars)
        context._init_global_context(self.ops)
        playbook = PlaybookExecutor(playbooks=playbook_path,
                                    inventory=playbook_inventory,
                                    variable_manager=self.variable_manager,
                                    loader=self.loader,
                                    passwords=self.passwords)
        result = playbook.run()
        return result
Example #7
0
def get_configured_replicasets():
    inventory = InventoryManager(loader=DataLoader(), sources='hosts.yml')
    variable_manager = VariableManager(loader=DataLoader(),
                                       inventory=inventory)

    replicasets = {}

    for instance in inventory.hosts:
        host_vars = variable_manager.get_vars(host=inventory.hosts[instance])
        if 'replicaset_alias' not in host_vars:
            continue

        if instance_is_expelled(host_vars):
            continue

        replicaset_alias = host_vars['replicaset_alias']
        if replicaset_alias not in replicasets:
            replicasets[replicaset_alias] = {
                'instances': [],
                'failover_priority': host_vars.get('failover_priority'),
                'roles': host_vars['roles'],
                'all_rw': host_vars.get('all_rw'),
                'weight': host_vars.get('weight'),
                'vshard_group': host_vars.get('vshard_group')
            }

        replicasets[replicaset_alias]['instances'].append(instance)

    return replicasets
Example #8
0
    def test_variable_manager_task_vars(self):
        # FIXME: BCS make this work
        return

        # pylint: disable=unreachable
        fake_loader = DictDataLoader({})

        mock_task = MagicMock()
        mock_task._role = None
        mock_task.loop = None
        mock_task.get_vars.return_value = dict(foo="bar")
        mock_task.get_include_params.return_value = dict()

        mock_all = MagicMock()
        mock_all.get_vars.return_value = {}
        mock_all.get_file_vars.return_value = {}

        mock_host = MagicMock()
        mock_host.get.name.return_value = 'test01'
        mock_host.get_vars.return_value = {}
        mock_host.get_host_vars.return_value = {}

        mock_inventory = MagicMock()
        mock_inventory.hosts.get.return_value = mock_host
        mock_inventory.hosts.get.name.return_value = 'test01'
        mock_inventory.get_host.return_value = mock_host
        mock_inventory.groups.__getitem__.return_value = mock_all

        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        self.assertEqual(
            v.get_vars(task=mock_task, use_cache=False).get("foo"), "bar")
    def test_variable_manager_task_vars(self):
        # FIXME: BCS make this work
        return

        # pylint: disable=unreachable
        fake_loader = DictDataLoader({})

        mock_task = MagicMock()
        mock_task._role = None
        mock_task.loop = None
        mock_task.get_vars.return_value = dict(foo="bar")
        mock_task.get_include_params.return_value = dict()

        mock_all = MagicMock()
        mock_all.get_vars.return_value = {}
        mock_all.get_file_vars.return_value = {}

        mock_host = MagicMock()
        mock_host.get.name.return_value = 'test01'
        mock_host.get_vars.return_value = {}
        mock_host.get_host_vars.return_value = {}

        mock_inventory = MagicMock()
        mock_inventory.hosts.get.return_value = mock_host
        mock_inventory.hosts.get.name.return_value = 'test01'
        mock_inventory.get_host.return_value = mock_host
        mock_inventory.groups.__getitem__.return_value = mock_all

        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        self.assertEqual(v.get_vars(task=mock_task, use_cache=False).get("foo"), "bar")
Example #10
0
def test():
    try:
        loader = DataLoader()
        ds = loader.load(get_values())

        inventory = InventoryManager(loader=loader)
        if ds is not None:
            for key, value in ds.items():
                inventory.groups['all'].set_variable(key, value)

        variable_manager = VariableManager(
            loader=loader,
            inventory=inventory,
            version_info=CLI.version_info(gitinfo=False))
        templar = Templar(loader=loader)
        templar.available_variables = variable_manager.get_vars(host=Host(
            name='all'))
        try:
            rendered = templar.template(get_template(),
                                        convert_data=False,
                                        cache=False)
        except Exception as e:
            rendered = "Template rendering failed: {0}".format(e)
    except Exception as e:
        rendered = "Template syntax error: {0}".format(e)

    result = {"result": str(rendered)}

    return json.dumps(result)
def ansible_syntax_check():
    # templ = """{{ lookup(
    #           'template', '%s/ansible/roles/sigia/templates/ansible_extra_vars.j2')
    #            }}""" % ( config.rootdir )
    loader = DataLoader()
    inventory = InventoryManager(loader=loader, sources='local,')
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    pb = Playbook.load(config.rootdir +
                       "/infrastructure/ansible/aws-security.yml",
                       variable_manager=variable_manager,
                       loader=loader)
    plays = pb.get_plays()
    localhost = inventory.get_host("local")
    for play in plays:
        variable_manager.set_host_facts(localhost,
                                        variable_manager.get_vars(play))
    # local_vars = variable_manager.get_vars(host=localhost)
    # templar = Templar(loader=loader, variables=local_vars)
    # extra_vars = templar.template(templ)
    # if extra_vars:
    #     variable_manager.extra_vars = extra_vars
    r = ansible_runner.run(
        private_data_dir=TEST_DIR,
        inventory='local,',
        playbook=str(config.rootdir) +
        '/infrastructure/ansible/aws-security.yml',
        # extravars=extra_vars,
        artifact_dir="/tmp/ansible",
        rotate_artifacts=5)
    return r
Example #12
0
    def get(self):
        if os.path.isdir(self.cluster_config_path):
            return {"cluster": None, "inventory": None}

        data_loader = DataLoader()
        # data_loader.set_vault_password('627VR8*;YU99B')
        variable_manager = VariableManager(loader=data_loader)

        extra_vars = self.console_args.extra_vars[:]

        configurations = [
            '@' + config for config in self.cluster_config_path.split(',')
        ]

        extra_vars.append('cluster=' +
                          get_cluster_name(self.cluster_config_path))
        extra_vars.extend(configurations)

        options = collections.namedtuple('options', 'extra_vars')
        variable_manager.extra_vars = load_extra_vars(
            loader=data_loader, options=options(extra_vars=extra_vars))

        read_variables = variable_manager.get_vars()

        templar = Templar(data_loader, variables=read_variables)
        templar._filter_loader = self.template.filter_plugin_loader

        return templar.template(read_variables, fail_on_undefined=True)
 def _convert_to_dynamic_inventory(aelf, ansible_static_inventory):
     variable_manager = VariableManager(loader=DataLoader(),
                                        inventory=ansible_static_inventory)
     ansible_dynamic_inventory = dict()
     for group in ansible_static_inventory.groups.values():
         ansible_dynamic_inventory[group.name] = dict()
         group_hosts = group.get_hosts()
         if len(group_hosts):
             ansible_dynamic_inventory[group.name]["hosts"] = map(
                 str, group_hosts)
         group_vars = group.get_vars()
         if len(group_vars):
             ansible_dynamic_inventory[group.name]["vars"] = group_vars
         group_children = group.child_groups
         if len(group_children):
             ansible_dynamic_inventory[group.name]["children"] = map(
                 str, group_children)
     ansible_dynamic_inventory["_meta"] = dict()
     ansible_dynamic_inventory["_meta"]["hostvars"] = dict()
     for host in ansible_static_inventory.get_hosts():
         ansible_dynamic_inventory["_meta"]["hostvars"][
             host.name] = variable_manager.get_vars(host=host)
         del (ansible_dynamic_inventory['_meta']['hostvars'][host.name]
              ['groups'])
         del (ansible_dynamic_inventory['_meta']['hostvars'][host.name]
              ['inventory_dir'])
         del (ansible_dynamic_inventory['_meta']['hostvars'][host.name]
              ['inventory_file'])
         del (ansible_dynamic_inventory['_meta']['hostvars'][host.name]
              ['omit'])
     return ansible_dynamic_inventory
class Inventory24(Inventory):

    def __init__(self, inventory, ask_vault_pass, vault_password_files, vault_ids):
        from ansible.cli import CLI
        super(Inventory24, self).__init__()
        loader = DataLoader()
        if vault_ids or vault_password_files or ask_vault_pass:
            CLI.setup_vault_secrets(loader, vault_ids, vault_password_files, ask_vault_pass)
        self.inventory = ansible.inventory.manager.InventoryManager(loader=loader, sources=inventory)
        self.variable_manager = VariableManager(loader=loader)
        self.variable_manager.set_inventory(self.inventory)

    # internal fuctions that actually do the work
    # adapted almost entirely from lib/ansible/vars/manager.py
    def _plugins_inventory(self, entities):
        import os
        from ansible.plugins.loader import vars_loader
        from ansible.utils.vars import combine_vars
        ''' merges all entities by inventory source '''
        data = {}
        for inventory_dir in self.variable_manager._inventory._sources:
            if ',' in inventory_dir:  # skip host lists
                continue
            elif not os.path.isdir(inventory_dir):  # always pass 'inventory directory'
                inventory_dir = os.path.dirname(inventory_dir)

            for plugin in vars_loader.all():
                data = combine_vars(data, self._get_plugin_vars(plugin, inventory_dir, entities))
        return data

    def _get_plugin_vars(self, plugin, path, entities):
        from ansible.inventory.host import Host
        data = {}
        try:
            data = plugin.get_vars(self.variable_manager._loader, path, entities)
        except AttributeError:
            for entity in entities:
                if isinstance(entity, Host):
                    data.update(plugin.get_host_vars(entity.name))
                else:
                    data.update(plugin.get_group_vars(entity.name))
        return data

    def get_group_vars(self, group):
        return self._plugins_inventory([group])

    def get_host_vars(self, host):
        try:
            all_vars = self.variable_manager.get_vars(host=host, include_hostvars=True)
        except ansible.errors.AnsibleParserError:
            raise NoVaultSecretFound
        # play, host, task, include_hostvars, include_delegate_to
        magic_vars = ['ansible_playbook_python', 'groups', 'group_names', 'inventory_dir',
                      'inventory_file', 'inventory_hostname', 'inventory_hostname_short',
                      'omit', 'playbook_dir']
        return {k: v for (k, v) in all_vars.items() if k not in magic_vars}

    def get_group(self, group_name):
        return self.inventory.groups[group_name]
def get_ansible_host_ip():
    loader = DataLoader()
    inventory = InventoryManager(loader=loader, sources='hosts')
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    hostnames = []
    for host in inventory.get_hosts():
        hostnames.append(variable_manager.get_vars(host=host))
    ip = ' '.join([str(i['ansible_host']) for i in hostnames])
    return str(ip)
def get_ansible_host_ip():
    loader = DataLoader()
    inventory = InventoryManager(loader=loader, sources='hosts')
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    hostnames = []
    for host in inventory.get_hosts():
        hostnames.append(variable_manager.get_vars(host=host))
    ip = ' '.join([str(i['ansible_host']) for i in hostnames])
    return str(ip)
Example #17
0
    def __init__(self):
        initial_dir = os.getcwd()
        ansible_basedir = os.path.join(
            os.environ.get("PROJECT_ENVIRONMENT_FILES_PATH"), "ansible")

        # Move to project directory
        os.chdir(os.environ.get("PROJECT_ENVIRONMENT_FILES_PATH"))

        # Load list of inventories from config:w
        config = ConfigManager('/etc/ansible/ansible.cfg')
        sources = config.data.get_setting('DEFAULT_HOST_LIST').value

        loader = CustomLoader()
        loader.set_basedir(ansible_basedir)

        # load the inventory, set the basic playbook directory
        self._inventory = CustomInventoryManager(loader=loader,
                                                 sources=sources)
        var_manager = VariableManager(loader=loader, inventory=self._inventory)
        play = Play.load(dict(hosts=['all']),
                         loader=loader,
                         variable_manager=var_manager)

        # Move back to directory of origin
        os.chdir(initial_dir)

        control_host = None
        if 'control' in self._inventory.groups:
            control_group = self._inventory.groups['control']

            if len(control_group.get_hosts()) > 0:
                control_host = control_group.get_hosts()[0]

        # Hostvars
        hostvars = {}
        for host in self._inventory.get_hosts():
            hostvars[host.name] = host.vars

        # make sure we load all magic variables on top of the global variables
        self._vars = combine_vars(
            var_manager.get_vars(play=play, task=Task(), host=control_host), {
                'hostvars': hostvars,
                'env': os.environ
            })

        # create the template renderer
        self._templar = Templar(loader=loader, variables=self._vars)

        # setup some easy variables that we use a lot
        self._vars['control_ip'] = self.get_var(
            "hostvars[groups['control'][0]]['ansible_host']")
        self._vars['edge_ip'] = self.get_var(
            "hostvars[groups['edge'][0]]['ansible_host']")
        self._vars['monitor_ip'] = self.get_var(
            "hostvars[groups['monitor'][0]]['ansible_host']")
    def test_variable_manager_play_vars(self):
        fake_loader = DictDataLoader({})

        mock_play = MagicMock()
        mock_play.get_vars.return_value = dict(foo="bar")
        mock_play.get_roles.return_value = []
        mock_play.get_vars_files.return_value = []

        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        self.assertEqual(v.get_vars(play=mock_play, use_cache=False).get("foo"), "bar")
    def test_basic_manager(self):
        fake_loader = DictDataLoader({})

        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        variables = v.get_vars(use_cache=False)

        # Check var manager expected values,  never check: ['omit', 'vars']
        # FIXME:  add the following ['ansible_version', 'ansible_playbook_python', 'groups']
        for varname, value in (('playbook_dir', os.path.abspath('.')), ):
            self.assertEqual(variables[varname], value)
    def test_variable_manager_play_vars(self):
        fake_loader = DictDataLoader({})

        mock_play = MagicMock()
        mock_play.get_vars.return_value = dict(foo="bar")
        mock_play.get_roles.return_value = []
        mock_play.get_vars_files.return_value = []

        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        self.assertEqual(v.get_vars(play=mock_play, use_cache=False).get("foo"), "bar")
Example #21
0
    def test_basic_manager(self):
        fake_loader = DictDataLoader({})

        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        variables = v.get_vars(use_cache=False)

        # Check var manager expected values,  never check: ['omit', 'vars']
        # FIXME:  add the following ['ansible_version', 'ansible_playbook_python', 'groups']
        for varname, value in (('playbook_dir', os.path.abspath('.')), ):
            self.assertEqual(variables[varname], value)
Example #22
0
    def test_basic_manager(self):
        fake_loader = DictDataLoader({})

        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        vars = v.get_vars(use_cache=False)

        # FIXME: not sure why we remove all and only test playbook_dir
        for remove in ['omit', 'vars', 'ansible_version', 'ansible_check_mode', 'ansible_playbook_python']:
            if remove in vars:
                del vars[remove]

        self.assertEqual(vars, dict(playbook_dir=os.path.abspath('.')))
Example #23
0
    def test_variable_manager_options_vars(self):
        fake_loader = DictDataLoader({})

        options_vars = dict(a=1, b=2, c=3)
        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)

        # override internal options_vars loading
        v._extra_vars = options_vars

        myvars = v.get_vars(use_cache=False)
        for (key, val) in iteritems(options_vars):
            self.assertEqual(myvars.get(key), val)
Example #24
0
def list_inventory(ansible_inventory='/etc/ansible/hosts', ansible_groups=None):
    from ansible.parsing.dataloader import DataLoader
    from ansible.inventory.manager import InventoryManager
    from ansible.vars.manager import VariableManager

    data_loader = DataLoader()
    inventory = InventoryManager(loader=data_loader, sources=ansible_inventory)
    variable_manager = VariableManager(loader=data_loader, inventory=inventory)

    for ag in ansible_groups:
        for h in inventory.groups[ag].get_hosts():
            rhost = (h.get_vars()['ansible_host'] if 'ansible_host' in h.get_vars() else h.get_vars()['inventory_hostname'])
            ruser = (variable_manager.get_vars(host=h)['ansible_user'] if 'ansible_user' in variable_manager.get_vars(host=h) else 'root')
            yield (rhost, ruser)
    def test_variable_manager_extra_vars(self):
        fake_loader = DictDataLoader({})

        extra_vars = dict(a=1, b=2, c=3)
        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        v.extra_vars = extra_vars

        vars = v.get_vars(use_cache=False)

        for (key, val) in iteritems(extra_vars):
            self.assertEqual(vars.get(key), val)

        self.assertIsNot(v.extra_vars, extra_vars)
Example #26
0
    def test_variable_manager_extra_vars(self):
        fake_loader = DictDataLoader({})

        extra_vars = dict(a=1, b=2, c=3)
        mock_inventory = MagicMock()
        v = VariableManager(loader=fake_loader, inventory=mock_inventory)
        v.extra_vars = extra_vars

        vars = v.get_vars(use_cache=False)

        for (key, val) in iteritems(extra_vars):
            self.assertEqual(vars.get(key), val)

        self.assertIsNot(v.extra_vars, extra_vars)
Example #27
0
def parse_inventory(inventory):
    loader = DataLoader()
    inv = InventoryManager(loader=loader, sources=[inventory])
    vars = VariableManager(loader=loader, inventory=inv)
    all_groups = inv.get_groups_dict()
    tidb_nodes = all_groups['tidb_servers']
    tikv_nodes = all_groups['tikv_servers']
    tidb_servers = {}
    tikv_servers = {}
    for tidb in tidb_nodes:
        var = vars.get_vars(host=inv.get_host(hostname=str(tidb)))
        ip = var['ansible_host'] if 'ansible_host' in var else var[
            'inventory_hostname']
        tidb_port = var.get('tidb_port', 4000)
        tidb_status_port = var.get('tidb_status_port', 10080)
        deploy_dir = var['deploy_dir']

        if ip in tidb_servers:
            tidb_servers[ip].append([tidb_port, tidb_status_port, deploy_dir])
        else:
            tidb_servers[ip] = [[tidb_port, tidb_status_port, deploy_dir]]

    for tikv in tikv_nodes:
        var = vars.get_vars(host=inv.get_host(hostname=str(tikv)))
        ip = var['ansible_host'] if 'ansible_host' in var else var[
            'inventory_hostname']
        tikv_port = var.get('tikv_port', 20160)
        tikv_status_port = var.get('tikv_status_port', 20180)
        deploy_dir = var['deploy_dir']

        if ip in tikv_servers:
            tikv_servers[ip].append([tikv_port, tikv_status_port, deploy_dir])
        else:
            tikv_servers[ip] = [[tikv_port, tikv_status_port, deploy_dir]]

    return [tidb_servers, tikv_servers]
Example #28
0
def execute(playbooks: list, context: dict):
    '''
    '''
    assert playbooks

    os.environ["ANSIBLE_CONDITIONAL_BARE_VARS"] = "False"

    # ctx._init_global_context({})
    # since the API is constructed for CLI it expects certain options to always be set in the context object
    ctx.CLIARGS = ImmutableDict(connection='local',
                                module_path=['./playbooks/roles'],
                                forks=1,
                                become=False,
                                become_method="sudo",
                                syntax=False,
                                start_at_task=None,
                                diff=False,
                                verbosity=0)

    # initialize needed objects
    loader = DataLoader(
    )  # Takes care of finding and reading yaml, json and ini files
    # passwords = dict(become_pass="******")
    passwords = dict()

    # Instantiate our ResultCallback for handling results as they come in. Ansible expects this to be one of its main display outlets
    results_callback = ResultCallback()

    # create inventory, use path to host config file as source or hosts in a comma separated string
    inventory = InventoryManager(loader=loader, sources='localhost,')

    host = Host(name="localhost")
    # variable manager takes care of merging all the different sources to give you a unified view of variables available in each context
    variable_manager = VariableManager(loader=loader, inventory=inventory)

    variable_manager.set_host_variable(host, "current_directory",
                                       context.get("current_directory", ""))

    pbex = PlaybookExecutor(playbooks=playbooks,
                            inventory=inventory,
                            variable_manager=variable_manager,
                            loader=loader,
                            passwords=passwords)
    result = pbex.run()
    post_command = variable_manager.get_vars()["hostvars"]["localhost"].get(
        "mondrik_post_command")
    return result, post_command
Example #29
0
def inventory_load(inventory_sources, vault_secret):
    """ Load the inventory
    """
    loader = DataLoader()
    vault_secrets = [('default', TextVaultSecret(vault_secret))]
    loader.set_vault_secrets(vault_secrets)
    inventory = InventoryManager(loader=loader, sources=inventory_sources)
    result = {}
    for hostname in inventory.hosts:
        host = inventory.get_host(hostname)
        variable_manager = VariableManager(loader=loader, inventory=inventory)
        magic_vars = ['ansible_playbook_python', 'groups', 'group_names', 'inventory_dir',
                      'inventory_file', 'inventory_hostname', 'inventory_hostname_short',
                      'omit', 'playbook_dir']
        all_vars = variable_manager.get_vars(host=host, include_hostvars=True)
        cleaned = ({k: v for (k, v) in all_vars.items() if k not in magic_vars})
        result[hostname] = cleaned
    return result
Example #30
0
    def get(self):
        data_loader = DataLoader()
        # data_loader.set_vault_password()
        variable_manager = VariableManager(loader=data_loader)

        extra_vars = self.console_args.extra_vars[:]

        extra_vars.append('cluster=' +
                          get_cluster_name(self.cluster_config_path))

        options = collections.namedtuple('options', 'extra_vars')
        variable_manager.extra_vars = load_extra_vars(
            loader=data_loader, options=options(extra_vars=extra_vars))

        variables = variable_manager.get_vars()

        rendered = self.template.render(self.cluster_config_path, variables)

        return yaml.safe_load(rendered)
Example #31
0
def play_vars(ctx):
    # create inventory, use path to host config file as source or hosts in a comma
    # separated string
    inventory = InventoryManager(loader=loader, sources="inventory")
    # variable manager takes care of merging all the different sources to give you
    # a unified view of variables available in each context
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    # create data structure that represents our play, including tasks, this is basically
    # what our YAML loader does internally.
    play_source = dict(name="Ansible Play",
                       hosts="all",
                       gather_facts="no",
                       tasks=[])
    loader.set_vault_secrets([("default", VaultSecret(_bytes=to_bytes("TBD")))
                              ])
    # Create play object, playbook objects use .load instead of init or new methods,
    # this will also automatically create the task objects from the info provided
    # in play_source
    play = Play().load(play_source,
                       variable_manager=variable_manager,
                       loader=loader)
    tqm = None
    try:
        tqm = TaskQueueManager(
            inventory=inventory,
            variable_manager=variable_manager,
            loader=loader,
            passwords=dict(),
            # Use our custom callback instead of the ``default`` callback
            # plugin, which prints to stdout
            stdout_callback=results_callback,
        )
        # most interesting data for a play is actually
        # sent to the callback's methods
        tqm.run(play)
    finally:
        # we always need to cleanup child procs and the structures we use to
        # communicate with them
        if tqm is not None:
            tqm.cleanup()
        # Remove ansible tmpdir
        shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
    ctx.hostvars = variable_manager.get_vars()["hostvars"]
Example #32
0
def CallBackPlaybook(playbooks_path,extra_vars={},source=settings.ANSIBLE_SOURCE):
    """
    执行playbook
    :param playbooks_path: playbook的路径 list的类型
    :param source: ansible配置文件hosts
    :return:
    """
    dataloader = DataLoader()
    inventory = InventoryManager(loader=dataloader, sources=source)
    variableManager = VariableManager(loader=dataloader, inventory=inventory)
    variableManager.extra_vars=extra_vars #传入参数
    Options = namedtuple("Options", [
        "connection", "remote_user", "ask_sudo_pass", "verbosity", "ack_pass",
        "module_path", "forks", "become", "become_method", "become_user", "check",
        "listhosts", "listtasks", "listtags", "syntax", "sudo_user", "sudo", "diff"
    ])
    options = Options(connection='ssh', remote_user=None, ack_pass=None, sudo_user=None, forks=settings.ANSIBLE_FORKS, sudo=None,
                      ask_sudo_pass=False,
                      verbosity=5, module_path=None, become=None, become_method=None, become_user=None, check=False,
                      diff=False,
                      listhosts=None, listtasks=None, listtags=None, syntax=None)
    passwords = dict()
    try:
        logger = logging.getLogger("django")
        playbook = PlaybookExecutor(playbooks=playbooks_path, inventory=inventory, variable_manager=variableManager, loader=dataloader, options=options, passwords=passwords)
        callback = PlaybookCallbackBase()
        playbook._tqm._stdout_callback = callback  # 配置callback
        playbook.run()
        logger_info={"playbooks":playbooks_path,"variable_manager":variableManager.get_vars(),"passwords":passwords}
        logger.info(logger_info)
        status_list=['ok','failed','unreachable','skipped','stats']
        result_raw = {"ok": {}, "failed": {}, "unreachable": {}, "skipped": {}, "stats": {}}
        for status in status_list :
            for host,result in getattr(callback,'task_'+status).items() :
                result_raw[status][host] = result._result
                result_raw[status][host]["task"]=result._task.get_name()
        logger.info(str(result_raw))
        result_raw=get_result(result_raw)
        return result_raw
    except Exception as e:
        print(e)
        traceback.print_exc()
Example #33
0
def read_inventory_file(filename):
    """
    filename is a path to an ansible inventory file

    returns a mapping of group names ("webworker", "proxy", etc.)
    to lists of hostnames as listed in the inventory file.
    ("Hostnames" can also be IP addresses.)
    If the hostname in the file includes :<port>, that will be included here as well.

    """
    data_loader = DataLoader()
    inventory = get_inventory(filename, data_loader=data_loader)
    var_manager = VariableManager(data_loader, inventory)
    port_map = {host.name: var_manager.get_vars(host=host).get('ansible_port')
                for host in inventory.get_hosts()}
    return {group: [
        '{}:{}'.format(host, port_map[host])
        if port_map[host] is not None else host
        for host in hosts
    ] for group, hosts in get_inventory(filename).get_groups_dict().items()}
Example #34
0
def read_hosts(sources):
    hosts_list = []
    loader = DataLoader()
    inventory = InventoryManager(loader=loader, sources=sources)
    variable_manager = VariableManager(loader=loader, inventory=inventory)
    host_list = inventory.hosts
    for _host in host_list:
        host = inventory.get_host(hostname=_host)
        extra_vars = variable_manager.get_vars(host=host)
        ans_port = extra_vars.get("ansible_ssh_port") if extra_vars.get(
            "ansible_ssh_port") else extra_vars.get("ansible_port")
        ans_host = extra_vars.get("ansible_ssh_host") if extra_vars.get(
            "ansible_ssh_host") else extra_vars.get("ansible_host")
        hosts_list.append({
            "hostname": extra_vars.get("inventory_hostname"),
            "host": ans_host,
            "port": ans_port if ans_port else 22,
            "group_name": extra_vars.get("group_names")
        })

    return hosts_list
Example #35
0
def ansible_inventory(inventory_dir, host, ignore_ansible_stderr=True):
    from ansible.vars.manager import VariableManager
    from ansible.inventory.manager import InventoryManager
    from ansible.parsing.dataloader import DataLoader

    # bug solved in ansible 2.6+: printing an empty stderr!
    if ignore_ansible_stderr: sys.stderr = open(os.devnull, 'w')

    loader = DataLoader()
    inventory = InventoryManager(loader=loader, sources=unicode(inventory_dir))
    vm = VariableManager(loader=loader, inventory=inventory)

    hosts = inventory.get_hosts(unicode(host))

    if len(hosts) != 1:
        raise KeyError('Host %s does not match a (single) host in %s' % (host, inventory_dir))

    hostvars = vm.get_vars(host=hosts[0], include_hostvars=False)

    # restore default
    if ignore_ansible_stderr: sys.stderr = sys.__stderr__

    return hostvars
Example #36
0
def main():
    parser = argparse.ArgumentParser(
        description='Execute troubleshooting operation(s)')
    parser.add_argument('-u',
                        '--user',
                        dest='user',
                        metavar='<username>',
                        help='provide username for ssh login to devices')
    parser.add_argument('-p',
                        '--pass',
                        dest='passwd',
                        metavar='<password>',
                        help='provide ssh password or passphrase')
    parser.add_argument('-n',
                        '--nopass',
                        action='store_true',
                        help='disable password prompting')
    parser.add_argument('-c',
                        '--config',
                        dest='ssh_config',
                        metavar='<ssh_config>',
                        default='',
                        help='provide ssh config path')
    parser.add_argument('-i',
                        '--inventory',
                        dest='inventory_path',
                        metavar='<inventory_path>',
                        help='provide ansible inventory path')
    parser.add_argument('-l',
                        '--limit',
                        dest='limit',
                        metavar='<limit>',
                        help='specify host or group to run operations on')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='disable optional interactive prompts')

    args = parser.parse_args()

    print(
        f"{Fore.YELLOW}Welcome to the Python license management script for Junos boxes using PyEZ{Style.RESET_ALL}"
    )
    if (not args.user and not args.inventory_path and not args.quiet
            and validate_bool(
                "Would you like to print the command line help? (y/n) "
                "(type n to continue in interactive mode) ")):
        parser.print_help()
        sys.exit(0)

    user = validate_str("Enter your username: "******"Enter your password: "******"Enter path to ssh config: ",
                                  cli_input=args.ssh_config)
    else:
        ssh_config = None

    if not args.inventory_path:
        inventory_dir = Path("inventory")
        inventory_choices = [x for x in inventory_dir.iterdir() if x.is_dir()]
        inventory_choices.sort()
        print("\nAvailable Datacenters:")
        for idx, choice in enumerate(inventory_choices):
            print(f"{idx+1}: {choice.name}")
        user_choice = validate_int(
            "\nSelect Datacenter (Type Number only and press Enter):",
            input_min=1,
            input_max=inventory_choices.__len__())
        choice = inventory_choices[user_choice - 1]
        datacenter = choice.as_posix()
        print(f"Datacenter {choice.name} selected")
    else:
        datacenter = args.inventory_path
    # Ensure inventory path exists. Safeguard mainly when user provides path via cmd line

    # extract the datacenter name from the path
    dc_name = datacenter.rstrip('/').split('/')[-1]

    if not Path(datacenter).exists():
        print(f"Inventory Path '{datacenter}' does not exist. quitting...")
        sys.exit(1)

    if (not args.limit and not args.quiet and validate_bool(
            "Do you want to limit the execution to a specific set of hosts or groups? (y/n) "
    )):
        limit = validate_str(
            "Wildcard matching is supported like * and ? or [1-6] or [a:d] "
            "i.e. qfx5?00-[a:d] or qfx5100*\nEnter your limit: ")
    elif args.limit:
        limit = args.limit
    else:
        limit = None

    loader = DataLoader()
    inventory = InventoryManager(loader=loader, sources=datacenter)
    variables = VariableManager(loader=loader, inventory=inventory)

    if limit:
        if "*" in limit:
            limit = limit.replace("*", ".*")
        if "?" in limit:
            limit = limit.replace("?", ".")
        if ":" in limit:
            limit = limit.replace(":", "-")

    license_status_path = Path(f'{dc_name}-license_status.yml')
    if not license_status_path.exists():
        license_status_path.touch()
        license_status_path.chmod(0o660)
        license_status = {'licensed': {}, 'unlicensed': {}}
        yaml.dump(license_status, license_status_path)
    else:
        license_status = yaml.load(license_status_path)

    for host in inventory.get_hosts():
        hostname = host.get_name()
        match = False
        if limit:
            if re.match(limit, hostname):
                match = True
            else:
                for group in (str(g) for g in host.get_groups()):
                    if re.match(limit, group):
                        match = True
            if not match:
                continue
        netconf_port = variables.get_vars(host=host)['netconf_port']
        try:
            ansible_host = variables.get_vars(host=host)['ansible_host']
        except:
            ansible_host = hostname

        # Begin Device Output to User
        print(
            f"{Fore.BLUE}{Style.BRIGHT}Checking existing host_vars structure for device {hostname}{Style.RESET_ALL}"
        )
        try:
            host_path = Path(f'{datacenter}/host_vars/{hostname}')
            license_path = Path(
                f'{datacenter}/host_vars/{hostname}/licenses.yml')
            if not host_path.exists():
                print(f"Creating host_vars directory for host {hostname}")
                host_path.mkdir()
                host_path.chmod(0o770)
                old_yml_path = Path(f'{datacenter}/host_vars/{hostname}.yml')
                new_yml_path = Path(
                    f'{datacenter}/host_vars/{hostname}/system.yml')
                if old_yml_path.exists():
                    print(
                        f"Moving old host_vars file for {hostname} to {new_yml_path}"
                    )

                    old_yml_path.rename(new_yml_path)

            licenses = None
            if license_path.exists():
                print(f"loading license.yml for host {hostname}")
                licenses = yaml.load(license_path)
            else:
                print(f"initializing license.yml for host {hostname}")
                license_path.touch(
                )  # mode in touch does not set correctly. could be a umask issue
                license_path.chmod(0o660)  # mode works with chmod as expected.

            if licenses == None:
                licenses = {}

            if 'license_keys' not in licenses:
                licenses['license_keys'] = []
                yaml.dump(licenses, license_path)

            # Saving a copy for comparison later to see if we need to write updates to the yml
            original_licenses_in_yml = licenses['license_keys'].copy()

            print(
                f"{Fore.BLUE}{Style.BRIGHT}Retrieving existing licenses for device {hostname}{Style.RESET_ALL}"
            )
            with Device(host=ansible_host,
                        port=netconf_port,
                        user=user,
                        passwd=passwd,
                        ssh_config=ssh_config,
                        auto_probe=5) as dev:
                serial = dev.facts['serialnumber']
                model = dev.facts['model']
                hostname = dev.facts['hostname']
                print(f"device {hostname} has serialnumber {serial}")
                license_keys = dev.rpc.get_license_key_information()
                for key in license_keys:
                    key_data = key.xpath('key-data')
                    key_data = key_data[0].text.strip()
                    key_data = ' '.join(key_data.split('\n'))
                    key_data = ' '.join(key_data.split())
                    if key_data not in licenses['license_keys']:
                        key_name = key_data.split(' ')[0]
                        print(
                            f"{Fore.MAGENTA}Found unmanaged license key {key_name} on device {hostname}. "
                            f"Saving...{Style.RESET_ALL}")
                        licenses['license_keys'].append(key_data)

            new_license_paths = Path("licenses/").glob(f"{serial}*.txt")
            for new_license_path in new_license_paths:
                # These two lines processed license files in the old multiline format which had a header that we skipped
                # new_license = new_license_path.read_text().splitlines()[8:]
                # new_license = ' '.join([line.strip()
                # for line in new_license if line is not ''])
                # This is the new one line format where the files are generated by the
                # build_individual_licenses.py helper script
                new_license = new_license_path.read_text().strip()
                if new_license not in licenses['license_keys']:
                    key_name = new_license.split(' ')[0]
                    print(
                        f"{Fore.MAGENTA}Found new license key {key_name} in file '{new_license_path}' "
                        f"for device {hostname}. Converting...{Style.RESET_ALL}"
                    )
                    licenses['license_keys'].append(new_license)
            if licenses['license_keys'] != original_licenses_in_yml:
                print(f"Updating licenses.yml for host {hostname}...")
                yaml.dump(licenses, license_path)
            else:
                print(
                    f"{Fore.GREEN}Licenses already in sync for host {hostname}{Style.RESET_ALL}"
                )

            # Track what devices are licensed by datacenter
            if licenses['license_keys'] == []:
                try:
                    del license_status['licensed'][model][hostname]
                except KeyError:
                    pass
                if model not in license_status['unlicensed'].keys():
                    license_status['unlicensed'][model] = {}
                if hostname not in license_status['unlicensed'][model].keys():
                    license_status['unlicensed'][model][hostname] = serial
            else:
                try:
                    del license_status['unlicensed'][model][hostname]
                except KeyError:
                    pass
                if model not in license_status['licensed'].keys():
                    license_status['licensed'][model] = {}
                if hostname not in license_status['licensed'][model].keys():
                    license_status['licensed'][model][hostname] = serial

        except ConnectAuthError as err:
            print("Unable to login. Check username/password")
            print("Exiting so you don't lock yourself out :)")
            sys.exit(1)
        except (ProbeError, ConnectError) as err:
            print(
                "Cannot connect to device: \nMake sure device is reachable and "
                "'set system services netconf ssh' is set")
        except Exception as err:
            print(err.__class__.__name__ + ": " + err)
            sys.exit(1)

    # Remove empty subkeys (Model numbers with no entries)
    license_status_copy = copy.deepcopy(license_status)
    for k, v in license_status_copy['licensed'].items():
        if v == {}:
            del license_status['licensed'][k]
    for k, v in license_status_copy['unlicensed'].items():
        if v == {}:
            del license_status['unlicensed'][k]
    yaml.dump(license_status, license_status_path)
    print(f"{Fore.YELLOW}License Sync Complete!{Style.RESET_ALL}")
Example #37
0
class AnsibleRunner:

    def __init__(self,
                 inventory: List[str] = None):
        self.options = Options()
        self.data_loader = DataLoader()
        self.inventory_manager = InventoryManager(
            loader=self.data_loader,
            sources=inventory
        )
        self.variable_manager = VariableManager(
            loader=self.data_loader,
            inventory=self.inventory_manager
        )

    def add_host(self, host: Host) -> None:
        self.inventory_manager.add_host(
            host.address,
            group=host.group
        )
        h = self.inventory_manager.get_host(
            host.address
        )
        h.set_variable(
            'ansible_ssh_user',
            host.username
        )
        h.set_variable(
            'ansible_ssh_private_key_file',
            host.private_key_file
        )
        for (key, val) in host.variables.items():
            h.set_variable(key, val)

    def get_host_vars(self, host: Host) -> Optional[Dict[str, any]]:
        h = self.inventory_manager.get_host(
            host.address
        )
        return h.get_vars() if h is not None else None

    def get_local_facts(self, host: Host) -> Optional[Dict[str, any]]:
        h = self.inventory_manager.get_host(
            host.address
        )
        if h is None:
            return None
        v = self.variable_manager.get_vars(host=h)
        return v.get('ansible_facts', {}).get('ansible_local', {})

    def play(self,
             playbook: str,
             targets: List[str] = None,
             extra_vars: Dict[str, str] = None) -> bool:
        if extra_vars is None:
            extra_vars = {}

        if targets is not None:
            extra_vars['targets'] = ','.join(targets)

        self.variable_manager.extra_vars = extra_vars

        pbex = PlaybookExecutor(
            playbooks=[playbook],
            inventory=self.inventory_manager,
            variable_manager=self.variable_manager,
            loader=self.data_loader,
            options=self.options,
            passwords=None
        )

        return pbex.run() == 0
Example #38
0
class TestIncludeRole(unittest.TestCase):

    def setUp(self):

        self.loader = DictDataLoader({
            '/etc/ansible/roles/l1/tasks/main.yml': """
                - shell: echo 'hello world from l1'
                - include_role: name=l2
            """,
            '/etc/ansible/roles/l1/tasks/alt.yml': """
                - shell: echo 'hello world from l1 alt'
                - include_role: name=l2 tasks_from=alt defaults_from=alt
            """,
            '/etc/ansible/roles/l1/defaults/main.yml': """
                test_variable: l1-main
                l1_variable: l1-main
            """,
            '/etc/ansible/roles/l1/defaults/alt.yml': """
                test_variable: l1-alt
                l1_variable: l1-alt
            """,
            '/etc/ansible/roles/l2/tasks/main.yml': """
                - shell: echo 'hello world from l2'
                - include_role: name=l3
            """,
            '/etc/ansible/roles/l2/tasks/alt.yml': """
                - shell: echo 'hello world from l2 alt'
                - include_role: name=l3 tasks_from=alt defaults_from=alt
            """,
            '/etc/ansible/roles/l2/defaults/main.yml': """
                test_variable: l2-main
                l2_variable: l2-main
            """,
            '/etc/ansible/roles/l2/defaults/alt.yml': """
                test_variable: l2-alt
                l2_variable: l2-alt
            """,
            '/etc/ansible/roles/l3/tasks/main.yml': """
                - shell: echo 'hello world from l3'
            """,
            '/etc/ansible/roles/l3/tasks/alt.yml': """
                - shell: echo 'hello world from l3 alt'
            """,
            '/etc/ansible/roles/l3/defaults/main.yml': """
                test_variable: l3-main
                l3_variable: l3-main
            """,
            '/etc/ansible/roles/l3/defaults/alt.yml': """
                test_variable: l3-alt
                l3_variable: l3-alt
            """
        })

        self.var_manager = VariableManager(loader=self.loader)

    def tearDown(self):
        pass

    def get_tasks_vars(self, play, tasks):
        for task in flatten_tasks(tasks):
            role = task._role
            if not role:
                continue

            yield (role.get_name(),
                   self.var_manager.get_vars(play=play, task=task))

    @patch('ansible.playbook.role.definition.unfrackpath',
           mock_unfrackpath_noop)
    def test_simple(self):

        """Test one-level include with default tasks and variables"""

        play = Play.load(dict(
            name="test play",
            hosts=['foo'],
            gather_facts=False,
            tasks=[
                {'include_role': 'name=l3'}
            ]
        ), loader=self.loader, variable_manager=self.var_manager)

        tasks = play.compile()
        for role, task_vars in self.get_tasks_vars(play, tasks):
            self.assertEqual(task_vars.get('l3_variable'), 'l3-main')
            self.assertEqual(task_vars.get('test_variable'), 'l3-main')

    @patch('ansible.playbook.role.definition.unfrackpath',
           mock_unfrackpath_noop)
    def test_simple_alt_files(self):

        """Test one-level include with alternative tasks and variables"""

        play = Play.load(dict(
            name="test play",
            hosts=['foo'],
            gather_facts=False,
            tasks=[{'include_role': 'name=l3 tasks_from=alt defaults_from=alt'}]),
            loader=self.loader, variable_manager=self.var_manager)

        tasks = play.compile()
        for role, task_vars in self.get_tasks_vars(play, tasks):
            self.assertEqual(task_vars.get('l3_variable'), 'l3-alt')
            self.assertEqual(task_vars.get('test_variable'), 'l3-alt')

    @patch('ansible.playbook.role.definition.unfrackpath',
           mock_unfrackpath_noop)
    def test_nested(self):

        """
        Test nested includes with default tasks and variables.

        Variables from outer roles should be inherited, but overridden in inner
        roles.
        """

        play = Play.load(dict(
            name="test play",
            hosts=['foo'],
            gather_facts=False,
            tasks=[
                {'include_role': 'name=l1'}
            ]
        ), loader=self.loader, variable_manager=self.var_manager)

        tasks = play.compile()
        for role, task_vars in self.get_tasks_vars(play, tasks):
            # Outer-most role must not have variables from inner roles yet
            if role == 'l1':
                self.assertEqual(task_vars.get('l1_variable'), 'l1-main')
                self.assertEqual(task_vars.get('l2_variable'), None)
                self.assertEqual(task_vars.get('l3_variable'), None)
                self.assertEqual(task_vars.get('test_variable'), 'l1-main')
            # Middle role must have variables from outer role, but not inner
            elif role == 'l2':
                self.assertEqual(task_vars.get('l1_variable'), 'l1-main')
                self.assertEqual(task_vars.get('l2_variable'), 'l2-main')
                self.assertEqual(task_vars.get('l3_variable'), None)
                self.assertEqual(task_vars.get('test_variable'), 'l2-main')
            # Inner role must have variables from both outer roles
            elif role == 'l3':
                self.assertEqual(task_vars.get('l1_variable'), 'l1-main')
                self.assertEqual(task_vars.get('l2_variable'), 'l2-main')
                self.assertEqual(task_vars.get('l3_variable'), 'l3-main')
                self.assertEqual(task_vars.get('test_variable'), 'l3-main')

    @patch('ansible.playbook.role.definition.unfrackpath',
           mock_unfrackpath_noop)
    def test_nested_alt_files(self):

        """
        Test nested includes with alternative tasks and variables.

        Variables from outer roles should be inherited, but overridden in inner
        roles.
        """

        play = Play.load(dict(
            name="test play",
            hosts=['foo'],
            gather_facts=False,
            tasks=[
                {'include_role': 'name=l1 tasks_from=alt defaults_from=alt'}
            ]
        ), loader=self.loader, variable_manager=self.var_manager)

        tasks = play.compile()
        for role, task_vars in self.get_tasks_vars(play, tasks):
            # Outer-most role must not have variables from inner roles yet
            if role == 'l1':
                self.assertEqual(task_vars.get('l1_variable'), 'l1-alt')
                self.assertEqual(task_vars.get('l2_variable'), None)
                self.assertEqual(task_vars.get('l3_variable'), None)
                self.assertEqual(task_vars.get('test_variable'), 'l1-alt')
            # Middle role must have variables from outer role, but not inner
            elif role == 'l2':
                self.assertEqual(task_vars.get('l1_variable'), 'l1-alt')
                self.assertEqual(task_vars.get('l2_variable'), 'l2-alt')
                self.assertEqual(task_vars.get('l3_variable'), None)
                self.assertEqual(task_vars.get('test_variable'), 'l2-alt')
            # Inner role must have variables from both outer roles
            elif role == 'l3':
                self.assertEqual(task_vars.get('l1_variable'), 'l1-alt')
                self.assertEqual(task_vars.get('l2_variable'), 'l2-alt')
                self.assertEqual(task_vars.get('l3_variable'), 'l3-alt')
                self.assertEqual(task_vars.get('test_variable'), 'l3-alt')
Example #39
0
class MyInventory():
    '''
    resource = [{'hostid': '1231', 'hostname': 'h1', 'hostip': '1.1.1.1'},
                {'hostid': '2345', 'hostname': 'h2', 'hostip': '2.2.2.2'},
                ]
    resource = {'groupname1': {
        'hosts': [
            {'hostid': '1231', 'hostname': 'h1', 'hostip': '1.1.1.1'},
            {'hostid': '2231', 'hostname': 'h2', 'hostip': '1.1.1.2'},
                 ],
        'groupvars': {"k1":"v1"}
                              },
                'groupname2': {'hosts': [], 'groupvars': {}},
                              }
    '''

    # edit ori code  ansible/inventory/manage.pay line215  try if C.InventoryManager_PARSE_NOSOURCE:pass
    constants.InventoryManager_PARSE_NOSOURCE = True

    def __init__(self, resource):
        self.resource = resource
        self.loader = DataLoader()
        # self.inventory=InventoryManager(loader=self.loader,sources=['/etc/ansible/hosts'])
        self.inventory = InventoryManager(loader=self.loader)
        self.variable_manager = VariableManager(loader=self.loader,
                                                inventory=self.inventory)
        self._parse(self.resource)

    def _parse(self, resource):
        if isinstance(resource, list):
            self._addGroupHosts(self.resource)
        elif isinstance(resource, dict):
            # logging.info('parsing resuorce: %s'%(self.resource))
            for groupname, hosts_and_groupvars in self.resource.items():
                print("[1] groupname: %s |hostsandvars: %s" %
                      (groupname, hosts_and_groupvars))  # debug [1]
                self._addGroupHosts(hosts_and_groupvars.get('hosts'),
                                    groupname,
                                    hosts_and_groupvars.get('groupvars'))

        else:
            logging.error('resource error ,need dict or list')

    def _addGroupHosts(self, hosts, groupname='default', groupvars=None):
        self.inventory.add_group(group=groupname)
        group = Group(groupname)
        if groupvars:
            for k, v in groupvars.items():
                group.set_variable(k, v)

        # hosts=[{'hostid':'123','hostname':'h1','hostip':'192.168.188.20'}
        for host in hosts:
            hostid = host.get('hostid')
            hostname = host.get('hostname')
            hostip = host.get('hostip')
            username = host.get('username')
            password = host.get('password')
            port = host.get('port', 22)
            sshkey = host.get('sshkey')
            if hostname:
                self.inventory.add_host(
                    host=hostname, group=groupname
                )  # by default, indentify by hostname and need
                hostobj = self.inventory.get_host(
                    hostname=hostname)  # add host= , get hostname=

                self.variable_manager.set_host_variable(
                    host=hostobj, varname='ansible_ssh_host', value=hostip)
                self.variable_manager.set_host_variable(
                    host=hostobj, varname='ansible_ssh_port', value=port)
                self.variable_manager.set_host_variable(
                    host=hostobj, varname='ansible_ssh_user', value=username)
                self.variable_manager.set_host_variable(
                    host=hostobj, varname='ansible_ssh_pass', value=password)
                self.variable_manager.set_host_variable(
                    host=hostobj,
                    varname='ansible_ssh_private_key_file',
                    value=sshkey)

                # TODO: other vars such as become-method-user-pass
                #hostobj.set_variable('ansible_ssh_port',port)
                for k, v in host.items():
                    if k not in [
                            'hostip', 'port', 'username', 'password', 'sshkey'
                    ]:
                        hostobj.set_variable(k, v)
            else:
                logging.warning('resource error:cant get hostname from | %s' %
                                resource)

    def testcase(self):
        print(self.inventory.get_groups_dict())
        host = self.inventory.get_host(hostname='h1')
        print(self.variable_manager.get_vars(host=host))
    def test_variable_manager_precedence(self):
        # FIXME: this needs to be redone as dataloader is not the automatic source of data anymore
        return

        # pylint: disable=unreachable
        '''
        Tests complex variations and combinations of get_vars() with different
        objects to modify the context under which variables are merged.
        '''
        # FIXME: BCS makethiswork
        # return True

        mock_inventory = MagicMock()

        inventory1_filedata = """
            [group2:children]
            group1

            [group1]
            host1 host_var=host_var_from_inventory_host1

            [group1:vars]
            group_var = group_var_from_inventory_group1

            [group2:vars]
            group_var = group_var_from_inventory_group2
            """

        fake_loader = DictDataLoader({
            # inventory1
            '/etc/ansible/inventory1': inventory1_filedata,
            # role defaults_only1
            '/etc/ansible/roles/defaults_only1/defaults/main.yml': """
            default_var: "default_var_from_defaults_only1"
            host_var: "host_var_from_defaults_only1"
            group_var: "group_var_from_defaults_only1"
            group_var_all: "group_var_all_from_defaults_only1"
            extra_var: "extra_var_from_defaults_only1"
            """,
            '/etc/ansible/roles/defaults_only1/tasks/main.yml': """
            - debug: msg="here i am"
            """,

            # role defaults_only2
            '/etc/ansible/roles/defaults_only2/defaults/main.yml': """
            default_var: "default_var_from_defaults_only2"
            host_var: "host_var_from_defaults_only2"
            group_var: "group_var_from_defaults_only2"
            group_var_all: "group_var_all_from_defaults_only2"
            extra_var: "extra_var_from_defaults_only2"
            """,
        })

        inv1 = InventoryManager(loader=fake_loader, sources=['/etc/ansible/inventory1'])
        v = VariableManager(inventory=mock_inventory, loader=fake_loader)
        v._fact_cache = defaultdict(dict)

        play1 = Play.load(dict(
            hosts=['all'],
            roles=['defaults_only1', 'defaults_only2'],
        ), loader=fake_loader, variable_manager=v)

        # first we assert that the defaults as viewed as a whole are the merged results
        # of the defaults from each role, with the last role defined "winning" when
        # there is a variable naming conflict
        res = v.get_vars(play=play1)
        self.assertEqual(res['default_var'], 'default_var_from_defaults_only2')

        # next, we assert that when vars are viewed from the context of a task within a
        # role, that task will see its own role defaults before any other role's
        blocks = play1.compile()
        task = blocks[1].block[0]
        res = v.get_vars(play=play1, task=task)
        self.assertEqual(res['default_var'], 'default_var_from_defaults_only1')

        # next we assert the precedence of inventory variables
        v.set_inventory(inv1)
        h1 = inv1.get_host('host1')

        res = v.get_vars(play=play1, host=h1)
        self.assertEqual(res['group_var'], 'group_var_from_inventory_group1')
        self.assertEqual(res['host_var'], 'host_var_from_inventory_host1')

        # next we test with group_vars/ files loaded
        fake_loader.push("/etc/ansible/group_vars/all", """
        group_var_all: group_var_all_from_group_vars_all
        """)
        fake_loader.push("/etc/ansible/group_vars/group1", """
        group_var: group_var_from_group_vars_group1
        """)
        fake_loader.push("/etc/ansible/group_vars/group3", """
        # this is a dummy, which should not be used anywhere
        group_var: group_var_from_group_vars_group3
        """)
        fake_loader.push("/etc/ansible/host_vars/host1", """
        host_var: host_var_from_host_vars_host1
        """)
        fake_loader.push("group_vars/group1", """
        playbook_group_var: playbook_group_var
        """)
        fake_loader.push("host_vars/host1", """
        playbook_host_var: playbook_host_var
        """)

        res = v.get_vars(play=play1, host=h1)
        # self.assertEqual(res['group_var'], 'group_var_from_group_vars_group1')
        # self.assertEqual(res['group_var_all'], 'group_var_all_from_group_vars_all')
        # self.assertEqual(res['playbook_group_var'], 'playbook_group_var')
        # self.assertEqual(res['host_var'], 'host_var_from_host_vars_host1')
        # self.assertEqual(res['playbook_host_var'], 'playbook_host_var')

        # add in the fact cache
        v._fact_cache['host1'] = dict(fact_cache_var="fact_cache_var_from_fact_cache")

        res = v.get_vars(play=play1, host=h1)
        self.assertEqual(res['fact_cache_var'], 'fact_cache_var_from_fact_cache')