Exemple #1
0
    def _state_overridden(want, have):
        """ The command generator when state is overridden

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        for key, extant in have.items():
            if key in want:
                desired = want[key]
            else:
                desired = dict()

            add_config = dict_diff(extant, desired)
            del_config = dict_diff(desired, extant)

            if (
                "speed" in add_config.keys()
                and "duplex" not in add_config.keys()
            ):
                add_config.update({"duplex": desired.get("duplex")})

            commands.extend(generate_commands(key, add_config, del_config))

        return commands
Exemple #2
0
    def _state_replaced(want, have):
        """ The command generator when state is replaced

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        for key, desired in want.items():
            interface_name = normalize_interface(key)
            if interface_name in have:
                extant = have[interface_name]
            else:
                extant = dict()

            add_config = dict_diff(extant, desired)
            del_config = dict_diff(desired, extant)

            if (
                "speed" in add_config.keys()
                and "duplex" not in add_config.keys()
            ):
                add_config.update({"duplex": desired.get("duplex")})

            commands.extend(generate_commands(key, add_config, del_config))

        return commands
Exemple #3
0
    def _state_overridden(want, have):
        """ The command generator when state is overridden

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        for vlan_id, extant in have.items():
            if vlan_id in want:
                desired = want[vlan_id]
            else:
                desired = dict()

            add_config = dict_diff(extant, desired)
            del_config = dict_diff(desired, extant)

            commands.extend(generate_commands(vlan_id, add_config, del_config))

        # Handle vlans not already in config
        new_vlans = [vlan_id for vlan_id in want if vlan_id not in have]
        for vlan_id in new_vlans:
            desired = want[vlan_id]
            extant = dict(vlan_id=vlan_id)
            add_config = dict_diff(extant, desired)

            commands.extend(generate_commands(vlan_id, add_config, {}))

        return commands
Exemple #4
0
def get_ace_diff(want_ace, have_ace):
    # gives the diff of the aces passed.
    if not have_ace:
        return dict_diff({}, want_ace)
    for h_a in have_ace:
        d = dict_diff(want_ace, h_a)
        if not d:
            break
    return d
    def _state_replaced(self, want, have):
        """ The command generator when state is replaced

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        for name, value in iteritems(want):
            if name in have:
                to_clear = dict_diff(value, have[name])
                commands.extend(_clear_config(name, to_clear))
                to_set = dict_diff(have[name], value)
                commands.extend(_set_config(name, to_set))
        return remove_duplicate_interface(commands)
    def _state_merged(self, want, have):
        """The command generator when state is merged

        :rtype: A list
        :returns: the commands necessary to merge the provided into
                  the current configuration
        """
        commands = []
        want_copy = deepcopy(remove_empties(want))
        have_copy = deepcopy(have)

        want_vifs = want_copy.pop("vifs", [])
        have_vifs = have_copy.pop("vifs", [])

        updates = dict_diff(have_copy, want_copy)

        if updates:
            for key, value in iteritems(updates):
                commands.append(
                    self._compute_commands(
                        key=key, value=value, interface=want_copy["name"]
                    )
                )

        if want_vifs:
            for want_vif in want_vifs:
                have_vif = search_obj_in_list(
                    want_vif["vlan_id"], have_vifs, key="vlan_id"
                )
                if not have_vif:
                    have_vif = {
                        "vlan_id": want_vif["vlan_id"],
                        "enabled": True,
                    }

                vif_updates = dict_diff(have_vif, want_vif)
                if vif_updates:
                    for key, value in iteritems(vif_updates):
                        commands.append(
                            self._compute_commands(
                                key=key,
                                value=value,
                                interface=want_copy["name"],
                                vif=want_vif["vlan_id"],
                            )
                        )

        return commands
    def _render_updates(self, want, have):
        commands = []
        if have:
            temp_have_legacy_protos = have.pop("legacy_protocols", None)
        else:
            have = {}
            temp_want_legacy_protos = want.pop("legacy_protocols", None)

        updates = dict_diff(have, want)

        if have and temp_have_legacy_protos:
            have["legacy_protocols"] = temp_have_legacy_protos
        if not have and temp_want_legacy_protos:
            want["legacy_protocols"] = temp_want_legacy_protos

        commands.extend(self._add_lldp_protocols(want, have))

        if updates:
            for key, value in iteritems(updates):
                if value:
                    if key == "enable":
                        commands.append(self._compute_command())
                    elif key == "address":
                        commands.append(
                            self._compute_command("management-address",
                                                  str(value)))
                    elif key == "snmp":
                        if value == "disable":
                            commands.append(
                                self._compute_command(key, remove=True))
                        else:
                            commands.append(
                                self._compute_command(key, str(value)))
        return commands
    def _state_merged(self, want, have):
        """ The requests generator when state is merged

        :rtype: A list
        :returns: the requests necessary to merge the provided into
                  the current configuration
        """
        requests = []

        request_patch = deepcopy(self.VLAN_PATCH)

        for w in want:
            if w.get('vlan_id'):
                h = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
                if h:
                    if dict_diff(w, h):
                        request_body = self._update_patch_request(w)
                        request_patch["data"]["openconfig-vlan:vlans"]["vlan"].append(request_body)
                else:
                    request_post = self._update_post_request(w)
                    requests.append(request_post)

        if len(request_patch["data"]["openconfig-vlan:vlans"]["vlan"]):
            request_patch["data"] = json.dumps(request_patch["data"])
            requests.append(request_patch)
        return requests
    def _state_overridden(self, want, have):
        """ The request generator when state is overridden

        :rtype: A list
        :returns: the requests necessary to migrate the current configuration
                  to the desired configuration
        """
        requests = []
        request_patch = deepcopy(self.VLAN_PATCH)

        have_copy = []
        for w in want:
            if w.get('vlan_id'):
                h = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
                if h:
                    if dict_diff(w, h):
                        request_body = self._update_patch_request(w)
                        request_patch["data"]["openconfig-vlan:vlans"]["vlan"].append(request_body)
                    have_copy.append(h)
                else:
                    request_post = self._update_post_request(w)
                    requests.append(request_post)

        for h in have:
            if h not in have_copy and h['vlan_id'] != 1:
                request_delete = self._update_delete_request(h)
                requests.append(request_delete)

        if len(request_patch["data"]["openconfig-vlan:vlans"]["vlan"]):
            request_patch["data"] = json.dumps(request_patch["data"])
            requests.append(request_patch)

        return requests
    def _render_updates(self, want, have):
        commands = []

        temp_have_members = have.pop("members", None)
        temp_want_members = want.pop("members", None)

        updates = dict_diff(have, want)

        if temp_have_members:
            have["members"] = temp_have_members
        if temp_want_members:
            want["members"] = temp_want_members

        commands.extend(self._add_bond_members(want, have))

        if updates:
            for key, value in iteritems(updates):
                if value:
                    if key == "arp_monitor":
                        commands.extend(
                            self._add_arp_monitor(updates, key, want, have)
                        )
                    else:
                        commands.append(
                            self._compute_command(
                                have["name"], key, str(value)
                            )
                        )
        return commands
Exemple #11
0
    def _render_updates(self, want, have, opr=True):
        """
        This function takes the diff between want and have and
        invokes the appropriate functions to create the commands
        to update the attributes.
        :param want:
        :param have:
        :return: list of commands
        """
        commands = []
        want_nh = want.get('next_hops') or []
        # delete static route operation per destination
        if not opr and not want_nh:
            commands.append(self._compute_command(dest=want['dest'], remove=True))

        else:
            temp_have_next_hops = have.pop('next_hops', None)
            temp_want_next_hops = want.pop('next_hops', None)
            updates = dict_diff(have, want)
            if temp_have_next_hops:
                have['next_hops'] = temp_have_next_hops
            if temp_want_next_hops:
                want['next_hops'] = temp_want_next_hops
            commands.extend(self._add_next_hop(want, have, opr=opr))

            if opr and updates:
                for key, value in iteritems(updates):
                    if value:
                        if key == 'blackhole_config':
                            commands.extend(self._add_blackhole(key, want, have))
        return commands
Exemple #12
0
    def _state_overridden(self, want, have):
        """ The request generator when state is overridden

        :rtype: A list
        :returns: the requests necessary to migrate the current configuration
                  to the desired configuration
        """
        requests = []
        have_copy = []
        for w in want:
            for h in have:
                if w["name"] == h["name"]:
                    if dict_diff(w, h):
                        l2_request = self._update_patch_request(w, h)
                        l2_request["data"] = json.dumps(l2_request["data"])
                        requests.append(l2_request)
                    have_copy.append(h)
                    break

        for h in have:
            if h not in have_copy:
                l2_delete = self._update_delete_request(h)
                if l2_delete["path"]:
                    l2_delete["data"] = json.dumps(l2_delete["data"])
                    requests.append(l2_delete)

        return requests
Exemple #13
0
    def _compare_seq(self, afi, w, h):
        wl_child = {}
        hl_child = {}
        parser = ["prefixlist.entry", "prefixlist.resequence"]
        for seq, ent in iteritems(w):
            seq_diff = {}
            wl_child = {"afi": afi, "prefix_lists": {"entries": {seq: ent}}}
            if h.get(seq):
                hl_child = {
                    "afi": afi,
                    "prefix_lists": {
                        "entries": {
                            seq: h.pop(seq)
                        }
                    },
                }
                seq_diff = dict_diff(
                    hl_child["prefix_lists"]["entries"][seq],
                    wl_child["prefix_lists"]["entries"][seq],
                )
            if seq_diff:
                if self.state == "merged":
                    self._module.fail_json(
                        msg="Sequence number " + str(seq) +
                        " is already present. Use replaced/overridden operation to change the configuration"
                    )

                self.compare(parsers="prefixlist.entry",
                             want={},
                             have=hl_child)
            self.compare(parsers=parser, want=wl_child, have=hl_child)
def _set_config(name, want, have, module):
    commands = []

    diff = dict_diff(have, want)
    if diff.get('trunk') and diff.get('access'):
        module.fail_json(msg='Interface should either be trunk or access')

    if diff.get('access'):
        value = diff['access']
        if not have.get('access'):
            commands.append('switchport mode access')
        if value['vlan'] != have.get('access', {}).get('vlan'):
            commands.append('switchport access vlan {}'.format(value['vlan']))

    elif diff.get('trunk'):
        value = diff['trunk']
        if not have.get('trunk'):
            commands.append('switchport mode trunk')
        if value.get('allowed_vlans'):
            for vlan in value.get('allowed_vlans'):
                if vlan not in have.get('trunk', {}).get('allowed_vlans', []):
                    commands.append(
                        'switchport trunk allowed vlan add {}'.format(vlan))
        if value.get('native_vlan') and value.get('native_vlan') != have.get(
                'trunk', {}).get('native_vlan'):
            commands.append('switchport trunk native vlan {}'.format(
                value['native_vlan']))

    if commands:
        commands.insert(0, 'interface {}'.format(name))

    return commands
Exemple #15
0
    def _state_merged(self, want, have):
        """ The request generator when state is merged

        :rtype: A list
        :returns: the requests necessary to merge the provided into
                  the current configuration
        """
        requests = []
        commands = []
        for w in want:
            for h in have:
                if w['name'] == h['name']:
                    diff = dict_diff(h, w)
                    if diff:
                        interface_request, interface_command = self._update_patch_request(
                            diff, h, w)
                        for request in interface_request:
                            if request["data"].get(
                                    "openconfig-interfaces:config") and len(
                                        request["data"]
                                        ["openconfig-interfaces:config"]):
                                request['data'] = json.dumps(request['data'])
                                requests.append(request)
                            elif request['data'].get(
                                    'openconfig-if-ethernet:config') and len(
                                        request['data']
                                        ['openconfig-if-ethernet:config']):
                                request['data'] = json.dumps(request['data'])
                                requests.append(request)
                        commands.extend(interface_command)
                    break
        return requests, commands
Exemple #16
0
    def _state_replaced(self, w, have):
        """ The command generator when state is replaced

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        obj_in_have = flatten_dict(search_obj_in_list(w['name'], have, 'name'))
        if obj_in_have:
            diff = dict_diff(w, obj_in_have)
        else:
            diff = w
        merged_commands = self.set_commands(w, have, True)
        if 'name' not in diff:
            diff['name'] = w['name']

        dkeys = diff.keys()
        for k in w.copy():
            if k in self.exclude_params and k in dkeys:
                del diff[k]
        replaced_commands = self.del_attribs(diff)

        if merged_commands:
            cmds = set(replaced_commands).intersection(set(merged_commands))
            for cmd in cmds:
                merged_commands.remove(cmd)
            commands.extend(replaced_commands)
            commands.extend(merged_commands)
        return commands
Exemple #17
0
    def _add_location(self, name, want_item, have_item):
        commands = []
        have_dict = {}
        have_ca = {}
        set_cmd = name + " location "
        want_location_type = want_item.get("location") or {}
        have_location_type = have_item.get("location") or {}

        if want_location_type["coordinate_based"]:
            want_dict = want_location_type.get("coordinate_based") or {}
            if is_dict_element_present(have_location_type, "coordinate_based"):
                have_dict = have_location_type.get("coordinate_based") or {}
            location_type = "coordinate-based"
            updates = dict_diff(have_dict, want_dict)
            for key, value in iteritems(updates):
                if value:
                    commands.append(
                        self._compute_command(set_cmd + location_type, key,
                                              str(value)))

        elif want_location_type["civic_based"]:
            location_type = "civic-based"
            want_dict = want_location_type.get("civic_based") or {}
            want_ca = want_dict.get("ca_info") or []
            if is_dict_element_present(have_location_type, "civic_based"):
                have_dict = have_location_type.get("civic_based") or {}
                have_ca = have_dict.get("ca_info") or []
                if want_dict["country_code"] != have_dict["country_code"]:
                    commands.append(
                        self._compute_command(
                            set_cmd + location_type,
                            "country-code",
                            str(want_dict["country_code"]),
                        ))
            else:
                commands.append(
                    self._compute_command(
                        set_cmd + location_type,
                        "country-code",
                        str(want_dict["country_code"]),
                    ))
            commands.extend(self._add_civic_address(name, want_ca, have_ca))

        elif want_location_type["elin"]:
            location_type = "elin"
            if is_dict_element_present(have_location_type, "elin"):
                if want_location_type.get("elin") != have_location_type.get(
                        "elin"):
                    commands.append(
                        self._compute_command(
                            set_cmd + location_type,
                            value=str(want_location_type["elin"]),
                        ))
            else:
                commands.append(
                    self._compute_command(
                        set_cmd + location_type,
                        value=str(want_location_type["elin"]),
                    ))
        return commands
Exemple #18
0
def test_dict_diff():
    base = dict(
        obj2=dict(),
        b1=True,
        b2=False,
        b3=False,
        one=1,
        two=2,
        three=3,
        obj1=dict(key1=1, key2=2),
        l1=[1, 3],
        l2=[1, 2, 3],
        l4=[4],
        nested=dict(n1=dict(n2=2)),
    )

    other = dict(
        b1=True,
        b2=False,
        b3=True,
        b4=True,
        one=1,
        three=4,
        four=4,
        obj1=dict(key1=2),
        l1=[2, 1],
        l2=[3, 2, 1],
        l3=[1],
        nested=dict(n1=dict(n2=2, n3=3)),
    )

    result = dict_diff(base, other)

    # string assertions
    assert "one" not in result
    assert "two" not in result
    assert result["three"] == 4
    assert result["four"] == 4

    # dict assertions
    assert "obj1" in result
    assert "key1" in result["obj1"]
    assert "key2" not in result["obj1"]

    # list assertions
    assert result["l1"] == [2, 1]
    assert "l2" not in result
    assert result["l3"] == [1]
    assert "l4" not in result

    # nested assertions
    assert "obj1" in result
    assert result["obj1"]["key1"] == 2
    assert "key2" not in result["obj1"]

    # bool assertions
    assert "b1" not in result
    assert "b2" not in result
    assert result["b3"]
    assert result["b4"]
Exemple #19
0
    def _state_replaced(self, want, have):
        """ The command generator when state is replaced

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        cmds = []
        obj_in_have = search_obj_in_list(want["name"], have, "name")
        if obj_in_have:
            diff = dict_diff(want, obj_in_have)
        else:
            diff = want
        merged_cmds = self.set_commands(want, have)
        if "name" not in diff:
            diff["name"] = want["name"]

        replaced_cmds = []
        if obj_in_have:
            replaced_cmds = self.del_attribs(diff)
        if replaced_cmds or merged_cmds:
            for cmd in set(replaced_cmds).intersection(set(merged_cmds)):
                merged_cmds.remove(cmd)
            cmds.extend(replaced_cmds)
            cmds.extend(merged_cmds)
        return cmds
Exemple #20
0
    def _set_commands(self, want_ace, have_ace):
        """A helped method that checks if there is
           a delta between the `have_ace` and `want_ace`.
           If there is a delta then it calls `_compute_commands`
           to create the ACE line.

        :rtype: A string
        :returns: An ACE generated from a structured ACE dictionary
                  via a call to `_compute_commands`
        """

        if 'line' in want_ace:
            if want_ace['line'] != have_ace.get('line'):
                return self._compute_commands(want_ace)

        else:
            if ('prefix' in want_ace.get('source',
                                         {})) or ('prefix' in want_ace.get(
                                             'destination', {})):
                self._prepare_for_diff(want_ace)

            protocol_opt_delta = {}
            delta = dict_diff(have_ace, want_ace)

            # `dict_diff` doesn't work properly for `protocol_options` diff,
            # so we need to handle it separately
            if want_ace.get('protocol_options', {}):
                protocol_opt_delta = set(flatten_dict(have_ace.get('protocol_options', {}))) ^ \
                    set(flatten_dict(want_ace.get('protocol_options', {})))

            if delta or protocol_opt_delta:
                want_ace = self._dict_merge(have_ace, want_ace)
                return self._compute_commands(want_ace)
Exemple #21
0
    def _state_replaced(self, want, have):
        """ The command generator when state is replaced.
        Scope is limited to vlan objects defined in the playbook.
        :rtype: A list
        :returns: The minimum command set required to migrate the current
                  configuration to the desired configuration.
        """
        obj_in_have = search_obj_in_list(want['vlan_id'], have, 'vlan_id')
        if obj_in_have:
            # ignore states that are already reset, then diff what's left
            obj_in_have = self.remove_default_states(obj_in_have)
            diff = dict_diff(want, obj_in_have)
            # Remove merge items from diff; what's left will be used to
            # remove states not specified in the playbook
            for k in dict(set(want.items()) - set(obj_in_have.items())).keys():
                diff.pop(k, None)
        else:
            diff = want

        # merged_cmds: 'want' cmds to update 'have' states that don't match
        # replaced_cmds: remaining 'have' cmds that need to be reset to default
        merged_cmds = self.set_commands(want, have)
        replaced_cmds = []
        if obj_in_have:
            # Remaining diff items are used to reset states to default
            replaced_cmds = self.del_attribs(diff)
        cmds = []
        if replaced_cmds or merged_cmds:
            cmds += ['vlan %s' % str(want['vlan_id'])]
            cmds += merged_cmds + replaced_cmds
        return cmds
Exemple #22
0
 def get_diff(self, comparable, base):
     diff = {}
     if not base:
         diff = comparable
     else:
         diff = dict_diff(base, comparable)
     return diff
Exemple #23
0
    def _compare_lists(self, want, have):
        """
            Handles list attributes from config_data
        """
        for x in [
                "communities",
                "community_maps",
                "correlator.rule_sets",
                "correlator.rules",
                "context",
                "groups",
                "hosts",
                "interfaces",
                "mib_object_lists",
                "mib_schema",
                "mib_bulkstat_transfer_ids",
                "users",
                "targets",
        ]:

            wantx = want.get(x, {})
            havex = have.get(x, {})
            if "." in x:
                complex_parser = x.split(".")
                wantx = want.get(complex_parser[0],
                                 {}).get(complex_parser[1], {})
                havex = have.get(complex_parser[0],
                                 {}).get(complex_parser[1], {})

            if x in [
                    "interfaces",
                    "correlator.rules",
                    "mib_schema",
                    "mib_bulkstat_transfer_ids",
            ]:
                # handling complex parsers for replaced and overridden state

                for key, wentry in iteritems(wantx):
                    hentry = havex.pop(key, {})
                    updates = dict_diff(hentry, wentry)
                    if updates and x in [
                            "interfaces",
                            "mib_schema",
                            "mib_bulkstat_transfer_ids",
                    ]:
                        updates.update(name=wentry["name"])
                        self.addcmd(updates, x)
                    elif updates and x == "correlator.rules":
                        updates.update(rule_name=wentry["rule_name"])
                        self.addcmd(updates, x)
            else:
                for key, wentry in iteritems(wantx):
                    hentry = havex.pop(key, {})
                    if wentry != hentry:
                        self.addcmd(wentry, x)

            for key, hentry in iteritems(havex):
                self.addcmd(hentry, x, negate=True)
Exemple #24
0
def test_dict_diff():
    base = dict(obj2=dict(),
                b1=True,
                b2=False,
                b3=False,
                one=1,
                two=2,
                three=3,
                obj1=dict(key1=1, key2=2),
                l1=[1, 3],
                l2=[1, 2, 3],
                l4=[4],
                nested=dict(n1=dict(n2=2)))

    other = dict(b1=True,
                 b2=False,
                 b3=True,
                 b4=True,
                 one=1,
                 three=4,
                 four=4,
                 obj1=dict(key1=2),
                 l1=[2, 1],
                 l2=[3, 2, 1],
                 l3=[1],
                 nested=dict(n1=dict(n2=2, n3=3)))

    result = dict_diff(base, other)

    # string assertions
    assert 'one' not in result
    assert 'two' not in result
    assert result['three'] == 4
    assert result['four'] == 4

    # dict assertions
    assert 'obj1' in result
    assert 'key1' in result['obj1']
    assert 'key2' not in result['obj1']

    # list assertions
    assert result['l1'] == [2, 1]
    assert 'l2' not in result
    assert result['l3'] == [1]
    assert 'l4' not in result

    # nested assertions
    assert 'obj1' in result
    assert result['obj1']['key1'] == 2
    assert 'key2' not in result['obj1']

    # bool assertions
    assert 'b1' not in result
    assert 'b2' not in result
    assert result['b3']
    assert result['b4']
def set_config(want, have):
    commands = []
    to_set = dict_diff(have, want)
    for member in to_set.get("members", []):
        channel_id = want["name"][12:]
        commands.extend([
            "interface {0}".format(member["member"]),
            "channel-group {0} mode {1}".format(channel_id, member["mode"]),
        ])

    return commands
    def _state_overridden(want, have):
        """The command generator when state is overridden

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        for key, extant in have.items():
            if key in want:
                desired = want[key]
            else:
                desired = dict(name=key)

            add_config = dict_diff(extant, desired)
            del_config = dict_diff(desired, extant)

            commands.extend(generate_commands(key, add_config, del_config))

        return commands
    def _state_merged(self, want, have):
        """ The command generator when state is merged

        :rtype: A list
        :returns: the commands necessary to merge the provided into
                  the current configuration
        """
        commands = []
        diff = dict_diff(have, want)
        commands.extend(self.set_commands(diff))
        return commands
Exemple #28
0
    def _state_replaced(want, have):
        """ The command generator when state is replaced

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        for vlan_id, desired in want.items():
            if vlan_id in have:
                extant = have[vlan_id]
            else:
                extant = dict()

            add_config = dict_diff(extant, desired)
            del_config = dict_diff(desired, extant)

            commands.extend(generate_commands(vlan_id, add_config, del_config))

        return commands
Exemple #29
0
def remove_config(want, have):
    commands = []
    if not want.get("members"):
        return ["no interface {0}".format(want["name"])]

    to_remove = dict_diff(want, have)
    for member in to_remove.get("members", []):
        commands.extend(
            ["interface {0}".format(member["member"]), "no channel-group"])

    return commands
Exemple #30
0
def get_updated_ace(w, h):
    # gives the ace to be updated in case of merge update.
    if not dict_diff(w, h):
        return
    w_updated = w.copy()
    for hkey in h.keys():
        if hkey not in w.keys():
            w_updated.update({hkey: h[hkey]})
        else:
            w_updated.update({hkey: w[hkey]})
    return w_updated