コード例 #1
0
    def _parse(self):
        all_hosts = {}

        self.raw = utils.parse_json(self.data)
        all=Group('all')
        groups = dict(all=all)
        group = None
        for (group_name, data) in self.raw.items():
            group = groups[group_name] = Group(group_name)
            host = None
            if not isinstance(data, dict):
                data = {'hosts': data}
            if 'hosts' in data:
                for hostname in data['hosts']:
                    if not hostname in all_hosts:
                        all_hosts[hostname] = Host(hostname)
                    host = all_hosts[hostname]
                    group.add_host(host)
            if 'vars' in data:
                for k, v in data['vars'].iteritems():
                    group.set_variable(k, v)
            all.add_child_group(group)
        # Separate loop to ensure all groups are defined
        for (group_name, data) in self.raw.items():
            if isinstance(data, dict) and 'children' in data:
                for child_name in data['children']:
                    if child_name in groups:
                        groups[group_name].add_child_group(groups[child_name])
        return groups
コード例 #2
0
ファイル: script.py プロジェクト: zoni/ansible
    def _parse(self, err):

        all_hosts = {}
        self.raw  = utils.parse_json(self.data)
        all       = Group('all')
        groups    = dict(all=all)
        group     = None


        if 'failed' in self.raw:
            sys.stderr.write(err + "\n")
            raise errors.AnsibleError("failed to parse executable inventory script results: %s" % self.raw)

        for (group_name, data) in self.raw.items():
 
            # in Ansible 1.3 and later, a "_meta" subelement may contain
            # a variable "hostvars" which contains a hash for each host
            # if this "hostvars" exists at all then do not call --host for each
            # host.  This is for efficiency and scripts should still return data
            # if called with --host for backwards compat with 1.2 and earlier.

            if group_name == '_meta':
                if 'hostvars' in data:
                    self.host_vars_from_top = data['hostvars']
                    continue

            group = groups[group_name] = Group(group_name)
            host = None

            if not isinstance(data, dict):
                data = {'hosts': data}
            elif not any(k in data for k in ('hosts','vars')):
                data = {'hosts': [group_name], 'vars': data}

            if 'hosts' in data:

                for hostname in data['hosts']:
                    if not hostname in all_hosts:
                        all_hosts[hostname] = Host(hostname)
                    host = all_hosts[hostname]
                    group.add_host(host)

            if 'vars' in data:
                for k, v in data['vars'].iteritems():
                    if group.name == all.name:
                        all.set_variable(k, v)
                    else:
                        group.set_variable(k, v)
            if group.name != all.name:
                all.add_child_group(group)

        # Separate loop to ensure all groups are defined
        for (group_name, data) in self.raw.items():
            if group_name == '_meta':
                continue
            if isinstance(data, dict) and 'children' in data:
                for child_name in data['children']:
                    if child_name in groups:
                        groups[group_name].add_child_group(groups[child_name])
        return groups
コード例 #3
0
ファイル: __init__.py プロジェクト: zhangll1990/ansible
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [h for h in host_list if h and h.strip()]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently an the implicit 'localhost' to it.

        ungrouped = Group(name='ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                try:
                    (host, port) = parse_address(h, allow_ranges=False)
                except AnsibleError as e:
                    display.vvv(
                        "Unable to parse address from hostname, leaving unchanged: %s"
                        % to_unicode(e))
                    host = h
                    port = None
                all.add_host(Host(host, port))
        elif self._loader.path_exists(host_list):
            #TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader,
                                                 groups=self.groups,
                                                 filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups,
                                              self._loader)
                vars_loader.add_directory(self.basedir(), with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError(
                    "Unable to parse %s as an inventory source" % host_list)

        self._vars_plugins = [x for x in vars_loader.all(self)]

        # get group vars from group_vars/ files and vars plugins
        for group in self.groups.values():
            group.vars = combine_vars(group.vars,
                                      self.get_group_variables(group.name))

        # get host vars from host_vars/ files and vars plugins
        for host in self.get_hosts():
            host.vars = combine_vars(host.vars,
                                     self.get_host_variables(host.name))
コード例 #4
0
ファイル: ini.py プロジェクト: svend/ansible
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            if line.startswith("["):
                active_group_name = line.replace("[","").replace("]","").strip()
                if line.find(":vars") != -1 or line.find(":children") != -1:
                    active_group_name = None
                else:
                    new_group = self.groups[active_group_name] = Group(name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith("#") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line)
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Two cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if (hostname.find("[") != -1 and
                    hostname.find("]") != -1 and
                    hostname.find(":") != -1 and
                    (hostname.rindex("]") < hostname.rindex(":")) or
                    (hostname.find("]") == -1 and hostname.find(":") != -1)):
                        tokens2  = hostname.rsplit(":", 1)
                        hostname = tokens2[0]
                        port     = tokens2[1]

                host = None
                _all_hosts = []
                if hostname in self.hosts:
                    host = self.hosts[hostname]
                    _all_hosts.append(host)
                else:
                    if detect_range(hostname):
                        _hosts = expand_hostname_range(hostname)
                        for _ in _hosts:
                            host = Host(name=_, port=port)
                            self.hosts[_] = host
                            _all_hosts.append(host)
                    else:
                        host = Host(name=hostname, port=port)
                        self.hosts[hostname] = host
                        _all_hosts.append(host)
                if len(tokens) > 1:
                    for t in tokens[1:]:
                        (k,v) = t.split("=")
                        host.set_variable(k,v)
                for _ in _all_hosts:
                    self.groups[active_group_name].add_host(_)
コード例 #5
0
 def test_depth_update(self):
     A = Group('A')
     B = Group('B')
     Z = Group('Z')
     A.add_child_group(B)
     A.add_child_group(Z)
     self.assertEqual(A.depth, 0)
     self.assertEqual(Z.depth, 1)
     self.assertEqual(B.depth, 1)
コード例 #6
0
ファイル: test_group.py プロジェクト: awiddersheim/ansible
 def test_depth_update(self):
     A = Group('A')
     B = Group('B')
     Z = Group('Z')
     A.add_child_group(B)
     A.add_child_group(Z)
     self.assertEqual(A.depth, 0)
     self.assertEqual(Z.depth, 1)
     self.assertEqual(B.depth, 1)
コード例 #7
0
 def test_depth_recursion(self):
     A = Group('A')
     B = Group('B')
     A.add_child_group(B)
     # hypothetical of adding B as child group to A
     A.parent_groups.append(B)
     B.child_groups.append(A)
     # can't update depths of groups, because of loop
     with self.assertRaises(AnsibleError):
         B._check_children_depth()
コード例 #8
0
ファイル: test_group.py プロジェクト: awiddersheim/ansible
 def test_depth_recursion(self):
     A = Group('A')
     B = Group('B')
     A.add_child_group(B)
     # hypothetical of adding B as child group to A
     A.parent_groups.append(B)
     B.child_groups.append(A)
     # can't update depths of groups, because of loop
     with self.assertRaises(AnsibleError):
         B._check_children_depth()
コード例 #9
0
ファイル: __init__.py プロジェクト: davismathew/stableansible
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [ h for h in host_list if h and h.strip() ]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently an the implicit 'localhost' to it.

        ungrouped = Group('ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                try:
                    (host, port) = parse_address(h, allow_ranges=False)
                except AnsibleError as e:
                    display.vvv("Unable to parse address from hostname, leaving unchanged: %s" % to_unicode(e))
                    host = h
                    port = None
                all.add_host(Host(host, port))
        elif self._loader.path_exists(host_list):
            #TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups, self._loader)
                vars_loader.add_directory(self.basedir(), with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError("Unable to parse %s as an inventory source" % host_list)
        else:
            display.warning("Host file not found: %s" % to_unicode(host_list))

        self._vars_plugins = [ x for x in vars_loader.all(self) ]

        # set group vars from group_vars/ files and vars plugins
        for g in self.groups:
            group = self.groups[g]
            group.vars = combine_vars(group.vars, self.get_group_variables(group.name))

        # set host vars from host_vars/ files and vars plugins
        for host in self.get_hosts():
            host.vars = combine_vars(host.vars, self.get_host_variables(host.name))
コード例 #10
0
ファイル: test_host.py プロジェクト: Rajeshkumar90/Ansible
 def test_get_group_vars_with_nested_groups(self):
     parent_group = Group('some_parent_group')
     parent_group.set_variable('parent_some_key', 'parent_some_value')
     child_group = Group('some_child_group')
     child_group.set_variable('child_some_key', 'child_some_value')
     parent_group.add_child_group(child_group)
     self.hostA.add_group(child_group)
     group_vars = self.hostA.get_group_vars()
     self.assertIsInstance(group_vars, dict)
     self.assertIn('parent_some_key', group_vars)
     self.assertIn('child_some_key', group_vars)
コード例 #11
0
 def test_sub_group_host_ordering(self):
     """With multiple nested groups, asserts that hosts are returned
     in deterministic order
     """
     top_group = Group('A')
     expected_hosts = []
     for name in ['z', 'b', 'c', 'a', 'p', 'q']:
         child = Group('group_{0}'.format(name))
         top_group.add_child_group(child)
         host = Host('host_{0}'.format(name))
         child.add_host(host)
         expected_hosts.append(host)
     assert top_group.get_hosts() == expected_hosts
コード例 #12
0
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [ h for h in host_list if h and h.strip() ]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently an the implicit 'localhost' to it.

        ungrouped = Group(name='ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                (host, port) = parse_address(h, allow_ranges=False)
                all.add_host(Host(host, port))
        elif self._loader.path_exists(host_list):
            #TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self._loader.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups, self._loader)
                vars_loader.add_directory(self.basedir(), with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError("Unable to parse %s as an inventory source" % host_list)

        self._vars_plugins = [ x for x in vars_loader.all(self) ]

        # FIXME: shouldn't be required, since the group/host vars file
        #        management will be done in VariableManager
        # get group vars from group_vars/ files and vars plugins
        for group in self.groups.values():
            group.vars = combine_vars(group.vars, self.get_group_variables(group.name))

        # get host vars from host_vars/ files and vars plugins
        for host in self.get_hosts():
            host.vars = combine_vars(host.vars, self.get_host_variables(host.name))
コード例 #13
0
    def _parse(self, err):

        all_hosts = {}
        self.raw = utils.parse_json(self.data)
        all = Group('all')
        groups = dict(all=all)
        group = None

        if 'failed' in self.raw:
            sys.stderr.write(err + "\n")
            raise errors.AnsibleError(
                "failed to parse executable inventory script results: %s" %
                self.raw)

        for (group_name, data) in self.raw.items():

            group = groups[group_name] = Group(group_name)
            host = None

            if not isinstance(data, dict):
                data = {'hosts': data}
            elif not any(k in data for k in ('hosts', 'vars')):
                data = {'hosts': [group_name], 'vars': data}

            if 'hosts' in data:

                for hostname in data['hosts']:
                    if not hostname in all_hosts:
                        all_hosts[hostname] = Host(hostname)
                    host = all_hosts[hostname]
                    group.add_host(host)

            if 'vars' in data:
                for k, v in data['vars'].iteritems():
                    if group.name == all.name:
                        all.set_variable(k, v)
                    else:
                        group.set_variable(k, v)
            if group.name != all.name:
                all.add_child_group(group)

        # Separate loop to ensure all groups are defined
        for (group_name, data) in self.raw.items():
            if isinstance(data, dict) and 'children' in data:
                for child_name in data['children']:
                    if child_name in groups:
                        groups[group_name].add_child_group(groups[child_name])
        return groups
コード例 #14
0
ファイル: script.py プロジェクト: ucxdvd/n-repo
 def _parse(self):
     groups = {}
     self.raw = utils.parse_json(self.data)
     all = Group('all')
     self.groups = dict(all=all)
     group = None
     for (group_name, hosts) in self.raw.items():
         group = groups[group_name] = Group(group_name)
         host = None
         for hostname in hosts:
             host = Host(hostname)
             group.add_host(host)
             # FIXME: hack shouldn't be needed
             all.add_host(host)
         all.add_child_group(group)
     return groups
コード例 #15
0
ファイル: script.py プロジェクト: Kafkamorph/n-repo
 def _parse(self):
     groups = {}
     self.raw = utils.parse_json(self.data)
     all=Group('all')
     self.groups = dict(all=all)
     group = None
     for (group_name, hosts) in self.raw.items():
         group = groups[group_name] = Group(group_name)
         host = None
         for hostname in hosts:
             host = Host(hostname)
             group.add_host(host)
             # FIXME: hack shouldn't be needed
             all.add_host(host)
         all.add_child_group(group)
     return groups  
コード例 #16
0
ファイル: ini.py プロジェクト: ucxdvd/n-repo
    def _parse_base_groups(self):

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            if line.startswith("["):
                active_group_name = line.replace("[", "").replace("]",
                                                                  "").strip()
                if line.find(":vars") != -1 or line.find(":children") != -1:
                    active_group_name = None
                else:
                    new_group = self.groups[active_group_name] = Group(
                        name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith("#") or line == '':
                pass
            elif active_group_name:
                tokens = line.split()
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                if hostname.find(":") != -1:
                    tokens2 = hostname.split(":")
                    hostname = tokens2[0]
                    port = tokens2[1]
                host = None
                if hostname in self.hosts:
                    host = self.hosts[hostname]
                else:
                    host = Host(name=hostname, port=port)
                    self.hosts[hostname] = host
                if len(tokens) > 1:
                    for t in tokens[1:]:
                        (k, v) = t.split("=")
                        host.set_variable(k, v)
                self.groups[active_group_name].add_host(host)
コード例 #17
0
ファイル: inventory.py プロジェクト: fr33jc/bang
def get_ansible_groups(group_map):
    """
    Constructs a list of :class:`ansible.inventory.group.Group` objects from a
    map of lists of host strings.

    """
    # Some of this logic is cribbed from
    # ansible.inventory.script.InventoryScript
    all_hosts = {}
    group_all = Group('all')
    groups = [group_all]
    for gname, hosts in group_map.iteritems():
        g = Group(gname)
        for host in hosts:
            h = all_hosts.get(host, Host(host))
            all_hosts[host] = h
            g.add_host(h)
            group_all.add_host(h)
        group_all.add_child_group(g)
        groups.append(g)
    return groups
コード例 #18
0
def get_ansible_groups(group_map):
    """
    Constructs a list of :class:`ansible.inventory.group.Group` objects from a
    map of lists of host strings.

    """
    # Some of this logic is cribbed from
    # ansible.inventory.script.InventoryScript
    all_hosts = {}
    group_all = Group('all')
    groups = [group_all]
    for gname, hosts in group_map.iteritems():
        g = Group(gname)
        for host in hosts:
            h = all_hosts.get(host, Host(host))
            all_hosts[host] = h
            g.add_host(h)
            group_all.add_host(h)
        group_all.add_child_group(g)
        groups.append(g)
    return groups
コード例 #19
0
ファイル: ini.py プロジェクト: Kafkamorph/n-repo
    def _parse_base_groups(self):

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            if line.startswith("["):
                active_group_name = line.replace("[","").replace("]","").strip()
                if line.find(":vars") != -1 or line.find(":children") != -1:
                    active_group_name = None
                else:
                    new_group = self.groups[active_group_name] = Group(name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith("#") or line == '':
                pass
            elif active_group_name:
                tokens = line.split()
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                if hostname.find(":") != -1:
                   tokens2  = hostname.split(":")
                   hostname = tokens2[0]
                   port     = tokens2[1]
                host = None
                if hostname in self.hosts:
                    host = self.hosts[hostname]
                else:
                    host = Host(name=hostname, port=port)
                    self.hosts[hostname] = host
                if len(tokens) > 1:
                   for t in tokens[1:]:
                      (k,v) = t.split("=")
                      host.set_variable(k,v)
                self.groups[active_group_name].add_host(host)
コード例 #20
0
ファイル: test_group.py プロジェクト: awiddersheim/ansible
 def test_loop_detection(self):
     A = Group('A')
     B = Group('B')
     C = Group('C')
     A.add_child_group(B)
     B.add_child_group(C)
     with self.assertRaises(AnsibleError):
         C.add_child_group(A)
コード例 #21
0
 def test_loop_detection(self):
     A = Group('A')
     B = Group('B')
     C = Group('C')
     A.add_child_group(B)
     B.add_child_group(C)
     with self.assertRaises(AnsibleError):
         C.add_child_group(A)
コード例 #22
0
 def test_populates_descendant_hosts(self):
     A = Group('A')
     B = Group('B')
     C = Group('C')
     h = Host('h')
     C.add_host(h)
     A.add_child_group(B)  # B is child of A
     B.add_child_group(C)  # C is descendant of A
     A.add_child_group(B)
     self.assertEqual(set(h.groups), set([C, B, A]))
     h2 = Host('h2')
     C.add_host(h2)
     self.assertEqual(set(h2.groups), set([C, B, A]))
コード例 #23
0
ファイル: test_group.py プロジェクト: awiddersheim/ansible
 def test_populates_descendant_hosts(self):
     A = Group('A')
     B = Group('B')
     C = Group('C')
     h = Host('h')
     C.add_host(h)
     A.add_child_group(B)  # B is child of A
     B.add_child_group(C)  # C is descendant of A
     A.add_child_group(B)
     self.assertEqual(set(h.groups), set([C, B, A]))
     h2 = Host('h2')
     C.add_host(h2)
     self.assertEqual(set(h2.groups), set([C, B, A]))
コード例 #24
0
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [ h for h in host_list if h and h.strip() ]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently an the implicit 'localhost' to it.

        ungrouped = Group('ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                try:
                    (host, port) = parse_address(h, allow_ranges=False)
                except AnsibleError as e:
                    display.vvv("Unable to parse address from hostname, leaving unchanged: %s" % to_text(e))
                    host = h
                    port = None

                new_host = Host(host, port)
                if h in C.LOCALHOST:
                    # set default localhost from inventory to avoid creating an implicit one. Last localhost defined 'wins'.
                    if self.localhost is not None:
                        display.warning("A duplicate localhost-like entry was found (%s). First found localhost was %s" % (h, self.localhost.name))
                    display.vvvv("Set default localhost to %s" % h)
                    self.localhost = new_host
                all.add_host(new_host)
        elif self._loader.path_exists(host_list):
            # TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups, self._loader)
                vars_loader.add_directory(self._basedir, with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError("Unable to parse %s as an inventory source" % host_list)
        else:
            display.warning("Host file not found: %s" % to_text(host_list))

        self._vars_plugins = [ x for x in vars_loader.all(self) ]

        # set group vars from group_vars/ files and vars plugins
        for g in self.groups:
            group = self.groups[g]
            group.vars = combine_vars(group.vars, self.get_group_variables(group.name))
            self.get_group_vars(group)

        # get host vars from host_vars/ files and vars plugins
        for host in self.get_hosts(ignore_limits=True, ignore_restrictions=True):
            host.vars = combine_vars(host.vars, self.get_host_variables(host.name))
            self.get_host_vars(host)
コード例 #25
0
ファイル: yaml.py プロジェクト: ucxdvd/n-repo
    def _parse(self, data):

        all = Group('all')
        ungrouped = Group('ungrouped')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        grouped_hosts = []

        yaml = utils.parse_yaml(data)

        # first add all groups
        for item in yaml:
            if type(item) == dict and 'group' in item:
                group = Group(item['group'])

                for subresult in item.get('hosts',[]):

                    if type(subresult) in [ str, unicode ]:
                        host = self._make_host(subresult)
                        group.add_host(host)
                        grouped_hosts.append(host)
                    elif type(subresult) == dict:
                        host = self._make_host(subresult['host'])
                        vars = subresult.get('vars',{})
                        if type(vars) == list:
                            for subitem in vars:
                               for (k,v) in subitem.items():
                                   host.set_variable(k,v) 
                        elif type(vars) == dict:
                            for (k,v) in subresult.get('vars',{}).items():
                                host.set_variable(k,v)
                        else:
                            raise errors.AnsibleError("unexpected type for variable")
                        group.add_host(host)
                        grouped_hosts.append(host)

                vars = item.get('vars',{})
                if type(vars) == dict:
                    for (k,v) in item.get('vars',{}).items():
                        group.set_variable(k,v) 
                elif type(vars) == list:
                    for subitem in vars:
                        if type(subitem) != dict:
                            raise errors.AnsibleError("expected a dictionary")
                        for (k,v) in subitem.items():
                            group.set_variable(k,v)

                self.groups[group.name] = group
                all.add_child_group(group)

        # add host definitions
        for item in yaml:
            if type(item) in [ str, unicode ]:
                host = self._make_host(item)
                if host not in grouped_hosts:
                    ungrouped.add_host(host)

            elif type(item) == dict and 'host' in item:
                host = self._make_host(item['host'])
                vars = item.get('vars', {})
                if type(vars)==list:
                    varlist, vars = vars, {}
                    for subitem in varlist:
                        vars.update(subitem)
                for (k,v) in vars.items():
                   host.set_variable(k,v)
                if host not in grouped_hosts:
                    ungrouped.add_host(host)
コード例 #26
0
ファイル: ini.py プロジェクト: dataxu/ansible
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            line = self._before_comment(line).strip()
            if line.startswith("[") and line.endswith("]"):
                active_group_name = line.replace("[","").replace("]","")
                if ":vars" in line or ":children" in line:
                    active_group_name = active_group_name.rsplit(":", 1)[0]
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(name=active_group_name)
                    active_group_name = None
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(name=active_group_name)
            elif line.startswith(";") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line)
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Three cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if hostname.count(":") > 1:
                    # Possible an IPv6 address, or maybe a host line with multiple ranges
                    # IPv6 with Port  XXX:XXX::XXX.port
                    # FQDN            foo.example.com
                    if hostname.count(".") == 1:
                        (hostname, port) = hostname.rsplit(".", 1)
                elif ("[" in hostname and
                    "]" in hostname and
                    ":" in hostname and
                    (hostname.rindex("]") < hostname.rindex(":")) or
                    ("]" not in hostname and ":" in hostname)):
                        (hostname, port) = hostname.rsplit(":", 1)

                hostnames = []
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'):
                                break
                            try:
                                (k,v) = t.split("=", 1)
                            except ValueError, e:
                                raise AnsibleError("Invalid ini entry in %s: %s - %s" % (self.filename, t, str(e)))
                            if k == 'ansible_ssh_host':
                                host.ipv4_address = self._parse_value(v)
                            else:
                                host.set_variable(k, self._parse_value(v))
                    self.groups[active_group_name].add_host(host)
コード例 #27
0
    def _parse(self, err):

        all_hosts = {}

        # not passing from_remote because data from CMDB is trusted
        self.raw  = utils.parse_json(self.data)
        self.raw  = json_dict_bytes_to_unicode(self.raw)

        all       = Group('all')
        groups    = dict(all=all)
        group     = None


        if 'failed' in self.raw:
            sys.stderr.write(err + "\n")
            raise errors.AnsibleError("failed to parse executable inventory script results: %s" % self.raw)

        for (group_name, data) in self.raw.items():

            # in Ansible 1.3 and later, a "_meta" subelement may contain
            # a variable "hostvars" which contains a hash for each host
            # if this "hostvars" exists at all then do not call --host for each
            # host.  This is for efficiency and scripts should still return data
            # if called with --host for backwards compat with 1.2 and earlier.

            if group_name == '_meta':
                if 'hostvars' in data:
                    self.host_vars_from_top = data['hostvars']
                    continue

            if group_name != all.name:
                group = groups[group_name] = Group(group_name)
            else:
                group = all
            host = None

            if not isinstance(data, dict):
                data = {'hosts': data}
            # is not those subkeys, then simplified syntax, host with vars
            elif not any(k in data for k in ('hosts','vars')):
                data = {'hosts': [group_name], 'vars': data}

            if 'hosts' in data:
                if not isinstance(data['hosts'], list):
                    raise errors.AnsibleError("You defined a group \"%s\" with bad "
                        "data for the host list:\n %s" % (group_name, data))

                for hostname in data['hosts']:
                    if not hostname in all_hosts:
                        all_hosts[hostname] = Host(hostname)
                    host = all_hosts[hostname]
                    group.add_host(host)

            if 'vars' in data:
                if not isinstance(data['vars'], dict):
                    raise errors.AnsibleError("You defined a group \"%s\" with bad "
                        "data for variables:\n %s" % (group_name, data))

                for k, v in data['vars'].iteritems():
                    if group.name == all.name:
                        all.set_variable(k, v)
                    else:
                        group.set_variable(k, v)

        # Separate loop to ensure all groups are defined
        for (group_name, data) in self.raw.items():
            if group_name == '_meta':
                continue
            if isinstance(data, dict) and 'children' in data:
                for child_name in data['children']:
                    if child_name in groups:
                        groups[group_name].add_child_group(groups[child_name])

        for group in groups.values():
            if group.depth == 0 and group.name != 'all':
                all.add_child_group(group)

        return groups
コード例 #28
0
ファイル: test_group.py プロジェクト: awiddersheim/ansible
    def test_depth_update_dual_branches(self):
        alpha = Group('alpha')
        A = Group('A')
        alpha.add_child_group(A)
        B = Group('B')
        A.add_child_group(B)
        Z = Group('Z')
        alpha.add_child_group(Z)
        beta = Group('beta')
        B.add_child_group(beta)
        Z.add_child_group(beta)

        self.assertEqual(alpha.depth, 0)  # apex
        self.assertEqual(beta.depth, 3)  # alpha -> A -> B -> beta

        omega = Group('omega')
        omega.add_child_group(alpha)

        # verify that both paths are traversed to get the max depth value
        self.assertEqual(B.depth, 3)  # omega -> alpha -> A -> B
        self.assertEqual(beta.depth, 4)  # B -> beta
コード例 #29
0
ファイル: ini.py プロジェクト: hostage-nl/ansible
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            if line.startswith("["):
                active_group_name = line.split(" #")[0].replace("[","").replace("]","").strip()
                if line.find(":vars") != -1 or line.find(":children") != -1:
                    active_group_name = active_group_name.rsplit(":", 1)[0]
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(name=active_group_name)
                        all.add_child_group(new_group)
                    active_group_name = None
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith("#") or line.startswith(";") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line.split(" #")[0])
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Two cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if (hostname.find("[") != -1 and
                    hostname.find("]") != -1 and
                    hostname.find(":") != -1 and
                    (hostname.rindex("]") < hostname.rindex(":")) or
                    (hostname.find("]") == -1 and hostname.find(":") != -1)):
                        tokens2  = hostname.rsplit(":", 1)
                        hostname = tokens2[0]
                        port     = tokens2[1]

                hostnames = []
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'):
                                break
                            try:
                                (k,v) = t.split("=")
                            except ValueError, e:
                                raise errors.AnsibleError("Invalid ini entry: %s - %s" % (t, str(e)))
                            try:
                                host.set_variable(k,ast.literal_eval(v))
                            except:
                                # most likely a string that literal_eval
                                # doesn't like, so just set it
                                host.set_variable(k,v)
                    self.groups[active_group_name].add_host(host)
コード例 #30
0
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            line = line.split("#")[0].strip()
            if line.startswith("[") and line.endswith("]"):
                active_group_name = line.replace("[", "").replace("]", "")
                if line.find(":vars") != -1 or line.find(":children") != -1:
                    active_group_name = active_group_name.rsplit(":", 1)[0]
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(
                            name=active_group_name)
                        all.add_child_group(new_group)
                    active_group_name = None
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(
                        name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith(";") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line)
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Three cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if hostname.count(":") > 1:
                    # probably an IPv6 addresss, so check for the format
                    # XXX:XXX::XXX.port, otherwise we'll just assume no
                    # port is set
                    if hostname.find(".") != -1:
                        (hostname, port) = hostname.rsplit(".", 1)
                elif (hostname.find("[") != -1 and hostname.find("]") != -1
                      and hostname.find(":") != -1 and
                      (hostname.rindex("]") < hostname.rindex(":")) or
                      (hostname.find("]") == -1 and hostname.find(":") != -1)):
                    (hostname, port) = hostname.rsplit(":", 1)

                hostnames = []
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'):
                                break
                            try:
                                (k, v) = t.split("=")
                            except ValueError, e:
                                raise errors.AnsibleError(
                                    "Invalid ini entry: %s - %s" % (t, str(e)))
                            try:
                                host.set_variable(k, ast.literal_eval(v))
                            except:
                                # most likely a string that literal_eval
                                # doesn't like, so just set it
                                host.set_variable(k, v)
                    self.groups[active_group_name].add_host(host)
コード例 #31
0
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            if line.startswith("["):
                active_group_name = line.split(" #")[0].replace(
                    "[", "").replace("]", "").strip()
                if line.find(":vars") != -1 or line.find(":children") != -1:
                    active_group_name = active_group_name.rsplit(":", 1)[0]
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(
                            name=active_group_name)
                        all.add_child_group(new_group)
                    active_group_name = None
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(
                        name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith("#") or line.startswith(";") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line.split(" #")[0])
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Two cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if (hostname.find("[") != -1 and hostname.find("]") != -1
                        and hostname.find(":") != -1 and
                    (hostname.rindex("]") < hostname.rindex(":")) or
                    (hostname.find("]") == -1 and hostname.find(":") != -1)):
                    tokens2 = hostname.rsplit(":", 1)
                    hostname = tokens2[0]
                    port = tokens2[1]

                hostnames = []
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'):
                                break
                            try:
                                (k, v) = t.split("=")
                            except ValueError, e:
                                raise errors.AnsibleError(
                                    "Invalid ini entry: %s - %s" % (t, str(e)))
                            host.set_variable(k, v)
                    self.groups[active_group_name].add_host(host)
コード例 #32
0
    def _parse_base_groups(self):
        # FIXME: refactor,貌似在后面的版本中该函数会被重构
        # 这部分解析ini配置文件的代码却是写的很臃肿,急需要重构
        # 基础group解析,除了已经定义组名的group以外,还有ungrouped表示未分组的组名,all表示所有组的总和

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        # 喜欢这种dict创建字典的方式,比用{}的方式好看多了
        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        # 遍历self.lines,self.lines是文件内容,
        # ini文件的解析大多可以用python内置的conparser类,不过ansible的inventory所支持的语法比较复杂,这里作者自己处理了
        for lineno in range(len(self.lines)):
            line = utils.before_comment(self.lines[lineno]).strip()
            # 如果某行以'['开头,以']'结尾则表名是一个section
            if line.startswith("[") and line.endswith("]"):
                # 将中括号replace掉获得组名
                active_group_name = line.replace("[","").replace("]","")
                # 如果组名中有:vars 或:children,则进行二次处理,比如[southeast:vars],在通过冒号分割得到southeast
                if ":vars" in line or ":children" in line:
                    active_group_name = active_group_name.rsplit(":", 1)[0] # rsplit(":", 1)表示右边开始以冒号为分隔符分割一次
                    # 如果组名未加到self.groups里面,则创建一个新的Group类,并添加到self.groups里面
                    # 如果组名已经存在与self.groups里面,跳过...
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(name=active_group_name)
                    # 在这种情况下将active_group_name设置为None,用来表示这不是一个包含真正host的group
                    active_group_name = None
                # 这部分是组名中没有冒号的处理方式,和上面一样。
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(name=active_group_name)
            elif line.startswith(";") or line == '':
                # 如果改行以分号开始或为空行则跳过。
                pass
            elif active_group_name:
                # 这种情况表示当前行为非中括号打头的行,既包含真实host主机数据的行
                # 在section中包含:vars/:children的段并不包含真实主机
                # shlex模块实现了一个类来解析简单的类shell语法,可以用来编写领域特定的语言,或者解析加引号的字符串。
                tokens = shlex.split(line)
                if len(tokens) == 0:
                    continue
                hostname = tokens[0] # 获取主机名
                port = C.DEFAULT_REMOTE_PORT # 使用默认的SSH端口号
                # Three cases to check:
                # 0. A hostname that contains a range pesudo-code and a port,like badwol[a:f].example.com:5309
                # 1. A hostname that contains just a port ,like badwolf.example.com:5309
                # 对hostname需要进行以下的检测
                if hostname.count(":") > 1:
                    # IPV6格式的地址,端口号和hostname之间用"."表示。
                    # Possible an IPv6 address, or maybe a host line with multiple ranges
                    # IPv6 with Port  XXX:XXX::XXX.port
                    # FQDN            foo.example.com
                    if hostname.count(".") == 1:
                        (hostname, port) = hostname.rsplit(".", 1)
                elif ("[" in hostname and
                    "]" in hostname and
                    ":" in hostname and
                    (hostname.rindex("]") < hostname.rindex(":")) or
                    ("]" not in hostname and ":" in hostname)):
                        # 如果冒号在中括号外面,表示这个冒号后面是端口号,因此通过通过rsplit按照冒号分割一次获取端口号和hostname
                        (hostname, port) = hostname.rsplit(":", 1)

                hostnames = []
                # 检测hostname是否是表示一个范围的hosts,如果是则将其扩展成一组host列表,否则加入空列表
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                # 遍历hostnames列表
                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        # 如果host不在self.hosts列表中,则创建一个Host基类
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    # len(tokens) > 1表示该行拥有变量,如:jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'): # 如果是注释则退出,在ini文件中仍然可以使用#作为注释标识。
                                break
                            try:
                                (k,v) = t.split("=", 1) # kv变量解析
                            except ValueError, e:
                                raise errors.AnsibleError("%s:%s: Invalid ini entry: %s - %s" % (self.filename, lineno + 1, t, str(e)))
                            host.set_variable(k, self._parse_value(v)) # 将该行解析的变量设置到该host下
                    self.groups[active_group_name].add_host(host) # 将该host加入到对应的group中。
コード例 #33
0
    def test_depth_update_dual_branches(self):
        alpha = Group('alpha')
        A = Group('A')
        alpha.add_child_group(A)
        B = Group('B')
        A.add_child_group(B)
        Z = Group('Z')
        alpha.add_child_group(Z)
        beta = Group('beta')
        B.add_child_group(beta)
        Z.add_child_group(beta)

        self.assertEqual(alpha.depth, 0)  # apex
        self.assertEqual(beta.depth, 3)  # alpha -> A -> B -> beta

        omega = Group('omega')
        omega.add_child_group(alpha)

        # verify that both paths are traversed to get the max depth value
        self.assertEqual(B.depth, 3)  # omega -> alpha -> A -> B
        self.assertEqual(beta.depth, 4)  # B -> beta
コード例 #34
0
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            line = utils.before_comment(line).strip()
            if line.startswith("[") and line.endswith("]"):
                active_group_name = line.replace("[","").replace("]","")
                if line.find(":vars") != -1 or line.find(":children") != -1:
                    active_group_name = active_group_name.rsplit(":", 1)[0]
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(name=active_group_name)
                        all.add_child_group(new_group)
                    active_group_name = None
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith(";") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line)
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Three cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if hostname.count(":") > 1:
                    # Possible an IPv6 address, or maybe a host line with multiple ranges
                    # IPv6 with Port  XXX:XXX::XXX.port
                    # FQDN            foo.example.com
                    if hostname.count(".") == 1:
                        (hostname, port) = hostname.rsplit(".", 1)
                elif (hostname.find("[") != -1 and
                    hostname.find("]") != -1 and
                    hostname.find(":") != -1 and
                    (hostname.rindex("]") < hostname.rindex(":")) or
                    (hostname.find("]") == -1 and hostname.find(":") != -1)):
                        (hostname, port) = hostname.rsplit(":", 1)

                hostnames = []
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'):
                                break
                            try:
                                (k,v) = t.split("=", 1)
                            except ValueError, e:
                                raise errors.AnsibleError("Invalid ini entry: %s - %s" % (t, str(e)))

                            # If there is a hash in the value don't pass it through to ast at ast will split at the hash.
                            if "#" in v:
                                host.set_variable(k, v)
                            else:
                                try:
                                    host.set_variable(k,ast.literal_eval(v))
                                # Using explicit exceptions.
                                # Likely a string that literal_eval does not like. We wil then just set it.
                                except ValueError:
                                    # For some reason this was thought to be malformed.
                                    host.set_variable(k, v)
                                except SyntaxError:
                                    # Is this a hash with an equals at the end?
                                    host.set_variable(k, v)

                    self.groups[active_group_name].add_host(host)
コード例 #35
0
ファイル: ini.py プロジェクト: grlee/ansible
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            line = utils.before_comment(line).strip()
            if line.startswith("[") and line.endswith("]"):
                active_group_name = line.replace("[","").replace("]","")
                if ":vars" in line or ":children" in line:
                    active_group_name = active_group_name.rsplit(":", 1)[0]
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(name=active_group_name)
                        all.add_child_group(new_group)
                    active_group_name = None
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(name=active_group_name)
                    all.add_child_group(new_group)
            elif line.startswith(";") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line)
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Three cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if hostname.count(":") > 1:
                    # Possible an IPv6 address, or maybe a host line with multiple ranges
                    # IPv6 with Port  XXX:XXX::XXX.port
                    # FQDN            foo.example.com
                    if hostname.count(".") == 1:
                        (hostname, port) = hostname.rsplit(".", 1)
                elif ("[" in hostname and
                    "]" in hostname and
                    ":" in hostname and
                    (hostname.rindex("]") < hostname.rindex(":")) or
                    ("]" not in hostname and ":" in hostname)):
                        (hostname, port) = hostname.rsplit(":", 1)

                hostnames = []
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'):
                                break
                            try:
                                (k,v) = t.split("=", 1)
                            except ValueError, e:
                                raise errors.AnsibleError("Invalid ini entry: %s - %s" % (t, str(e)))

                            # If there is a hash in the value don't pass it through to ast at ast will split at the hash.
                            if "#" in v:
                                host.set_variable(k, v)
                            else:
                                try:
                                    host.set_variable(k,ast.literal_eval(v))
                                # Using explicit exceptions.
                                # Likely a string that literal_eval does not like. We wil then just set it.
                                except ValueError:
                                    # For some reason this was thought to be malformed.
                                    host.set_variable(k, v)
                                except SyntaxError:
                                    # Is this a hash with an equals at the end?
                                    host.set_variable(k, v)

                    self.groups[active_group_name].add_host(host)
コード例 #36
0
ファイル: __init__.py プロジェクト: yuzhida/ansible
    def parse_inventory(self, host_list):

        if isinstance(host_list, string_types):
            if "," in host_list:
                host_list = host_list.split(",")
                host_list = [ h for h in host_list if h and h.strip() ]

        self.parser = None

        # Always create the 'all' and 'ungrouped' groups, even if host_list is
        # empty: in this case we will subsequently add the implicit 'localhost' to it.

        ungrouped = Group('ungrouped')
        all = Group('all')
        all.add_child_group(ungrouped)
        base_groups = frozenset([all, ungrouped])

        self.groups = dict(all=all, ungrouped=ungrouped)

        if host_list is None:
            pass
        elif isinstance(host_list, list):
            for h in host_list:
                try:
                    (host, port) = parse_address(h, allow_ranges=False)
                except AnsibleError as e:
                    display.vvv("Unable to parse address from hostname, leaving unchanged: %s" % to_text(e))
                    host = h
                    port = None

                new_host = Host(host, port)
                if h in C.LOCALHOST:
                    # set default localhost from inventory to avoid creating an implicit one. Last localhost defined 'wins'.
                    if self.localhost is not None:
                        display.warning("A duplicate localhost-like entry was found (%s). First found localhost was %s" % (h, self.localhost.name))
                    display.vvvv("Set default localhost to %s" % h)
                    self.localhost = new_host
                all.add_host(new_host)
        elif self._loader.path_exists(host_list):
            # TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
            if self.is_directory(host_list):
                # Ensure basedir is inside the directory
                host_list = os.path.join(self.host_list, "")
                self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list)
            else:
                self.parser = get_file_parser(host_list, self.groups, self._loader)
                vars_loader.add_directory(self._basedir, with_subdir=True)

            if not self.parser:
                # should never happen, but JIC
                raise AnsibleError("Unable to parse %s as an inventory source" % host_list)
        else:
            display.warning("Host file not found: %s" % to_text(host_list))

        self._vars_plugins = [ x for x in vars_loader.all(self) ]

        ### POST PROCESS groups and hosts after specific parser was invoked

        group_names = set()
        # set group vars from group_vars/ files and vars plugins
        for g in self.groups:
            group = self.groups[g]
            group.vars = combine_vars(group.vars, self.get_group_variables(group.name))
            self.get_group_vars(group)
            group_names.add(group.name)

        host_names = set()
        # get host vars from host_vars/ files and vars plugins
        for host in self.get_hosts(ignore_limits=True, ignore_restrictions=True):
            host.vars = combine_vars(host.vars, self.get_host_variables(host.name))
            self.get_host_vars(host)
            host_names.add(host.name)

            mygroups = host.get_groups()

            # ensure hosts are always in 'all'
            if all not in mygroups:
                all.add_host(host)

            if ungrouped in mygroups:
                # clear ungrouped of any incorrectly stored by parser
                if set(mygroups).difference(base_groups):
                    host.remove_group(ungrouped)
            else:
                # add ungrouped hosts to ungrouped
                length = len(mygroups)
                if length == 0 or (length == 1 and all in mygroups):
                    ungrouped.add_host(host)

        # warn if overloading identifier as both group and host
        for conflict in group_names.intersection(host_names):
            display.warning("Found both group and host with same name: %s" % conflict)
コード例 #37
0
    def _parse_base_groups(self):
        # FIXME: refactor

        ungrouped = Group(name='ungrouped')
        all = Group(name='all')
        all.add_child_group(ungrouped)

        self.groups = dict(all=all, ungrouped=ungrouped)
        active_group_name = 'ungrouped'

        for line in self.lines:
            line = utils.before_comment(line).strip()
            if line.startswith("[") and line.endswith("]"):
                active_group_name = line.replace("[", "").replace("]", "")
                if ":vars" in line or ":children" in line:
                    active_group_name = active_group_name.rsplit(":", 1)[0]
                    if active_group_name not in self.groups:
                        new_group = self.groups[active_group_name] = Group(
                            name=active_group_name)
                    active_group_name = None
                elif active_group_name not in self.groups:
                    new_group = self.groups[active_group_name] = Group(
                        name=active_group_name)
            elif line.startswith(";") or line == '':
                pass
            elif active_group_name:
                tokens = shlex.split(line)
                if len(tokens) == 0:
                    continue
                hostname = tokens[0]
                port = C.DEFAULT_REMOTE_PORT
                # Three cases to check:
                # 0. A hostname that contains a range pesudo-code and a port
                # 1. A hostname that contains just a port
                if hostname.count(":") > 1:
                    # Possible an IPv6 address, or maybe a host line with multiple ranges
                    # IPv6 with Port  XXX:XXX::XXX.port
                    # FQDN            foo.example.com
                    if hostname.count(".") == 1:
                        (hostname, port) = hostname.rsplit(".", 1)
                elif ("[" in hostname and "]" in hostname and ":" in hostname
                      and (hostname.rindex("]") < hostname.rindex(":"))
                      or ("]" not in hostname and ":" in hostname)):
                    (hostname, port) = hostname.rsplit(":", 1)

                hostnames = []
                if detect_range(hostname):
                    hostnames = expand_hostname_range(hostname)
                else:
                    hostnames = [hostname]

                for hn in hostnames:
                    host = None
                    if hn in self.hosts:
                        host = self.hosts[hn]
                    else:
                        host = Host(name=hn, port=port)
                        self.hosts[hn] = host
                    if len(tokens) > 1:
                        for t in tokens[1:]:
                            if t.startswith('#'):
                                break
                            try:
                                (k, v) = t.split("=", 1)
                            except ValueError, e:
                                raise errors.AnsibleError(
                                    "Invalid ini entry: %s - %s" % (t, str(e)))
                            host.set_variable(k, self._parse_value(v))
                    self.groups[active_group_name].add_host(host)
コード例 #38
0
ファイル: script.py プロジェクト: bopopescu/ansible-1
    def _parse(self, err):

        all_hosts = {}

        # not passing from_remote because data from CMDB is trusted
        self.raw  = utils.parse_json(self.data) # 还是使用self.data来解析标准输出,需要self.data为json格式数据
        self.raw  = json_dict_bytes_to_unicode(self.raw) # 将self.raw中的kv都转换成unicode格式。

        all       = Group('all') # 设置Group("all")
        groups    = dict(all=all) # 初始化groups字典
        group     = None


        if 'failed' in self.raw: # 如果self.raw中有failed字段,则报错。不过在上面parser_json的时候no_exception是false,不会出现failed情况
            sys.stderr.write(err + "\n")
            raise errors.AnsibleError("failed to parse executable inventory script results: %s" % self.raw)

        for (group_name, data) in self.raw.items():
            # 1.3 以上版本使用--list的时返回结果中会包含_meta这样的key,该key的value中会有一个hostvars变量,该变量包含每个host的主机变量
            # 1.2及以下版本仍然需要使用--host命令为每一个host返回主机变量

            # in Ansible 1.3 and later, a "_meta" subelement may contain
            # a variable "hostvars" which contains a hash for each host
            # if this "hostvars" exists at all then do not call --host for each
            # host.  This is for efficiency and scripts should still return data
            # if called with --host for backwards compat with 1.2 and earlier.


            """
            {
                "databases"   : {
                    "hosts"   : [ "host1.example.com", "host2.example.com" ],
                    "vars"    : {
                        "a"   : true
                    }
                },
                "webservers"  : [ "host2.example.com", "host3.example.com" ],
                "atlanta"     : {
                    "hosts"   : [ "host1.example.com", "host4.example.com", "host5.example.com" ],
                    "vars"    : {
                        "b"   : false
                    },
                    "children": [ "marietta", "5points" ]
                },
                "marietta"    : [ "host6.example.com" ],
                "5points"     : [ "host7.example.com" ]
            }

            {

                # results of inventory script as above go here
                # ...

                "_meta" : {
                   "hostvars" : {
                      "moocow.example.com"     : { "asdf" : 1234 },
                      "llama.example.com"      : { "asdf" : 5678 },
                   }
                }


            {
                "moocow.example.com"     : { "asdf" : 1234 },
                "llama.example.com"      : { "asdf" : 5678 }
            }
            """

            if group_name == '_meta': # 如果key为_meta,则该value为meta数据。
                if 'hostvars' in data:
                    self.host_vars_from_top = data['hostvars'] # 如果meta数据中包含hostvars,则缓存到self.host_vars_from_top中。
                    continue # 跳过之后的处理

            if group_name != all.name: # group_name不是all则创建新的Group对象,并加入groups字典。
                group = groups[group_name] = Group(group_name) # 如果data中出现无group的hostname,则会出现以hostname为名称的组
            else:
                group = all
            host = None

            if not isinstance(data, dict): # 如果data不是字典类型,则表示data为主机列表
                data = {'hosts': data}
            # is not those subkeys, then simplified syntax, host with vars
            elif not any(k in data for k in ('hosts','vars','children')): # any函数表示可迭代对象中任何一个为True,则为True.否则为False
                # 如果data对象是字典类型,但key中不存在hosts、vars、children时,既该行数据为主机变量数据时,group_name为主机名
                data = {'hosts': [group_name], 'vars': data}

            # 上面两步为了统一data的格式,不带变量的data,格式为{'hosts': [host1,host2...]
            # 带变量的data,格式为: {'hosts': [group_name], 'vars': data }

            if 'hosts' in data:
                if not isinstance(data['hosts'], list): # 主机列表必须是list对象,上面的'hosts': [group_name] 也是为校验统一格式
                    raise errors.AnsibleError("You defined a group \"%s\" with bad "
                        "data for the host list:\n %s" % (group_name, data))

                for hostname in data['hosts']: # 遍历主机名
                    if not hostname in all_hosts:
                        all_hosts[hostname] = Host(hostname) # 如果主机对象不存在, 则创建并添加到all_hosts列表中,去重
                    host = all_hosts[hostname] # 将Host对象赋值给host变量
                    group.add_host(host) # 将Host对象添加到该group中

            if 'vars' in data: # 如果是带有vars的data
                if not isinstance(data['vars'], dict):
                    raise errors.AnsibleError("You defined a group \"%s\" with bad "
                        "data for variables:\n %s" % (group_name, data))

                for k, v in data['vars'].iteritems(): # 遍历所有的变量
                    if group.name == all.name: # 如果当前组名为“all",则将变量加到all group中,否则加到当前group中。
                        all.set_variable(k, v)
                    else:
                        group.set_variable(k, v)

        # Separate loop to ensure all groups are defined
        for (group_name, data) in self.raw.items():
            if group_name == '_meta':
                continue
            if isinstance(data, dict) and 'children' in data: # 如果data中包含子组,遍历子组并将子组添加到父组中
                for child_name in data['children']:
                    if child_name in groups:
                        groups[group_name].add_child_group(groups[child_name])

        for group in groups.values():
            if group.depth == 0 and group.name != 'all': # 如果该组深度为0,且名称不是"all",则加入all组的子组列表中。
                all.add_child_group(group)

        return groups