summaryrefslogtreecommitdiffstats
path: root/test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/facts/facts.py
blob: 477d3184749b94ac6c48ac93c89c985a8f652319 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
The facts base class
this contains methods common to all facts subsets
"""
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network import (
    get_resource_connection,
)
from ansible.module_utils.six import iteritems


class FactsBase(object):
    """
    The facts base class
    """

    def __init__(self, module):
        self._module = module
        self._warnings = []
        self._gather_subset = module.params.get("gather_subset")
        self._gather_network_resources = module.params.get(
            "gather_network_resources"
        )
        self._connection = None
        if module.params.get("state") not in ["rendered", "parsed"]:
            self._connection = get_resource_connection(module)

        self.ansible_facts = {"ansible_network_resources": {}}
        self.ansible_facts["ansible_net_gather_network_resources"] = list()
        self.ansible_facts["ansible_net_gather_subset"] = list()

        if not self._gather_subset:
            self._gather_subset = ["!config"]
        if not self._gather_network_resources:
            self._gather_network_resources = ["!all"]

    def gen_runable(self, subsets, valid_subsets, resource_facts=False):
        """ Generate the runable subset

        :param module: The module instance
        :param subsets: The provided subsets
        :param valid_subsets: The valid subsets
        :param resource_facts: A boolean flag
        :rtype: list
        :returns: The runable subsets
        """
        runable_subsets = set()
        exclude_subsets = set()
        minimal_gather_subset = set()
        if not resource_facts:
            minimal_gather_subset = frozenset(["default"])

        for subset in subsets:
            if subset == "all":
                runable_subsets.update(valid_subsets)
                continue
            if subset == "min" and minimal_gather_subset:
                runable_subsets.update(minimal_gather_subset)
                continue
            if subset.startswith("!"):
                subset = subset[1:]
                if subset == "min":
                    exclude_subsets.update(minimal_gather_subset)
                    continue
                if subset == "all":
                    exclude_subsets.update(
                        valid_subsets - minimal_gather_subset
                    )
                    continue
                exclude = True
            else:
                exclude = False

            if subset not in valid_subsets:
                self._module.fail_json(
                    msg="Subset must be one of [%s], got %s"
                    % (
                        ", ".join(sorted([item for item in valid_subsets])),
                        subset,
                    )
                )

            if exclude:
                exclude_subsets.add(subset)
            else:
                runable_subsets.add(subset)

        if not runable_subsets:
            runable_subsets.update(valid_subsets)
        runable_subsets.difference_update(exclude_subsets)
        return runable_subsets

    def get_network_resources_facts(
        self, facts_resource_obj_map, resource_facts_type=None, data=None
    ):
        """
        :param fact_resource_subsets:
        :param data: previously collected configuration
        :return:
        """
        if not resource_facts_type:
            resource_facts_type = self._gather_network_resources

        restorun_subsets = self.gen_runable(
            resource_facts_type,
            frozenset(facts_resource_obj_map.keys()),
            resource_facts=True,
        )
        if restorun_subsets:
            self.ansible_facts["ansible_net_gather_network_resources"] = list(
                restorun_subsets
            )
            instances = list()
            for key in restorun_subsets:
                fact_cls_obj = facts_resource_obj_map.get(key)
                if fact_cls_obj:
                    instances.append(fact_cls_obj(self._module))
                else:
                    self._warnings.extend(
                        [
                            "network resource fact gathering for '%s' is not supported"
                            % key
                        ]
                    )

            for inst in instances:
                inst.populate_facts(self._connection, self.ansible_facts, data)

    def get_network_legacy_facts(
        self, fact_legacy_obj_map, legacy_facts_type=None
    ):
        if not legacy_facts_type:
            legacy_facts_type = self._gather_subset

        runable_subsets = self.gen_runable(
            legacy_facts_type, frozenset(fact_legacy_obj_map.keys())
        )
        if runable_subsets:
            facts = dict()
            # default subset should always returned be with legacy facts subsets
            if "default" not in runable_subsets:
                runable_subsets.add("default")
            self.ansible_facts["ansible_net_gather_subset"] = list(
                runable_subsets
            )

            instances = list()
            for key in runable_subsets:
                instances.append(fact_legacy_obj_map[key](self._module))

            for inst in instances:
                inst.populate()
                facts.update(inst.facts)
                self._warnings.extend(inst.warnings)

            for key, value in iteritems(facts):
                key = "ansible_net_%s" % key
                self.ansible_facts[key] = value