172 lines
4.7 KiB
Diff
172 lines
4.7 KiB
Diff
|
From d0bfae4171f0d280241949a928654c84e63ed006 Mon Sep 17 00:00:00 2001
|
||
|
From: Gris Ge <fge@redhat.com>
|
||
|
Date: Mon, 29 Jun 2020 22:30:03 +0800
|
||
|
Subject: [PATCH] pretty state: Dumping state in the sorted order with priority
|
||
|
|
||
|
For OVS bond port, we would like the `name` been shown before other
|
||
|
properties.
|
||
|
|
||
|
To achieve that, we sort the dict keys and honoring the priority list which
|
||
|
means keys in `PRIORITY_LIST` will be shown before others.
|
||
|
|
||
|
Currently the `PRIORITY_LIST` is:
|
||
|
`("name", "type", "state", "enabled", "dns", "route-rules", "routes",
|
||
|
"interfaces")`
|
||
|
|
||
|
Test cases added.
|
||
|
|
||
|
Signed-off-by: Gris Ge <fge@redhat.com>
|
||
|
Signed-off-by: Till Maas <till@redhat.com>
|
||
|
---
|
||
|
libnmstate/prettystate.py | 94 ++++++++++++++++++---------------------
|
||
|
1 file changed, 43 insertions(+), 51 deletions(-)
|
||
|
|
||
|
diff --git a/libnmstate/prettystate.py b/libnmstate/prettystate.py
|
||
|
index da57618..10e22d6 100644
|
||
|
--- a/libnmstate/prettystate.py
|
||
|
+++ b/libnmstate/prettystate.py
|
||
|
@@ -1,5 +1,5 @@
|
||
|
#
|
||
|
-# Copyright (c) 2018-2019 Red Hat, Inc.
|
||
|
+# Copyright (c) 2018-2020 Red Hat, Inc.
|
||
|
#
|
||
|
# This file is part of nmstate
|
||
|
#
|
||
|
@@ -17,15 +17,29 @@
|
||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
#
|
||
|
|
||
|
-from collections import OrderedDict
|
||
|
+from collections.abc import Mapping
|
||
|
+from collections.abc import Sequence
|
||
|
from copy import deepcopy
|
||
|
import difflib
|
||
|
import json
|
||
|
-from operator import itemgetter
|
||
|
|
||
|
import yaml
|
||
|
|
||
|
-from libnmstate.schema import Constants
|
||
|
+from .schema import DNS
|
||
|
+from .schema import Route
|
||
|
+from .schema import RouteRule
|
||
|
+from .schema import Interface
|
||
|
+
|
||
|
+PRIORITY_LIST = (
|
||
|
+ "name",
|
||
|
+ "type",
|
||
|
+ "state",
|
||
|
+ "enabled",
|
||
|
+ DNS.KEY,
|
||
|
+ RouteRule.KEY,
|
||
|
+ Route.KEY,
|
||
|
+ Interface.KEY,
|
||
|
+)
|
||
|
|
||
|
|
||
|
def format_desired_current_state_diff(desired_state, current_state):
|
||
|
@@ -57,8 +71,8 @@ def format_desired_current_state_diff(desired_state, current_state):
|
||
|
|
||
|
class PrettyState:
|
||
|
def __init__(self, state):
|
||
|
- yaml.add_representer(OrderedDict, represent_ordereddict)
|
||
|
- self.state = order_state(deepcopy(state))
|
||
|
+ yaml.add_representer(dict, represent_dict)
|
||
|
+ self.state = _sort_with_priority(state)
|
||
|
|
||
|
@property
|
||
|
def yaml(self):
|
||
|
@@ -71,35 +85,18 @@ class PrettyState:
|
||
|
return json.dumps(self.state, indent=4, separators=(",", ": "))
|
||
|
|
||
|
|
||
|
-def represent_ordereddict(dumper, data):
|
||
|
+def represent_dict(dumper, data):
|
||
|
+ """
|
||
|
+ Represent dictionary with insert order
|
||
|
"""
|
||
|
- Represent OrderedDict as regular dictionary
|
||
|
-
|
||
|
- Source: https://stackoverflow.com/questions/16782112/can-pyyaml-dump-dict-items-in-non-alphabetical-order
|
||
|
- """ # noqa: E501
|
||
|
value = []
|
||
|
|
||
|
for item_key, item_value in data.items():
|
||
|
node_key = dumper.represent_data(item_key)
|
||
|
node_value = dumper.represent_data(item_value)
|
||
|
-
|
||
|
value.append((node_key, node_value))
|
||
|
|
||
|
- return yaml.nodes.MappingNode(u"tag:yaml.org,2002:map", value)
|
||
|
-
|
||
|
-
|
||
|
-def order_state(state):
|
||
|
- iface_states = state.pop(Constants.INTERFACES, None)
|
||
|
-
|
||
|
- state = order_iface_state(state)
|
||
|
-
|
||
|
- if iface_states is not None:
|
||
|
- state[Constants.INTERFACES] = [
|
||
|
- order_iface_state(iface_state)
|
||
|
- for iface_state in sorted(iface_states, key=itemgetter("name"))
|
||
|
- ]
|
||
|
-
|
||
|
- return state
|
||
|
+ return yaml.nodes.MappingNode("tag:yaml.org,2002:map", value)
|
||
|
|
||
|
|
||
|
def represent_unicode(_, data):
|
||
|
@@ -112,30 +109,25 @@ def represent_unicode(_, data):
|
||
|
"""
|
||
|
|
||
|
return yaml.ScalarNode(
|
||
|
- tag=u"tag:yaml.org,2002:str", value=data.encode("utf-8")
|
||
|
+ tag="tag:yaml.org,2002:str", value=data.encode("utf-8")
|
||
|
)
|
||
|
|
||
|
|
||
|
-def order_iface_state(iface_state):
|
||
|
- ordered_state = OrderedDict()
|
||
|
-
|
||
|
- for setting in ("name", "type", "state"):
|
||
|
- try:
|
||
|
- ordered_state[setting] = iface_state.pop(setting)
|
||
|
- except KeyError:
|
||
|
- pass
|
||
|
-
|
||
|
- for key, value in order_dict(iface_state).items():
|
||
|
- ordered_state[key] = value
|
||
|
-
|
||
|
- return ordered_state
|
||
|
-
|
||
|
-
|
||
|
-def order_dict(dict_):
|
||
|
- ordered_dict = OrderedDict()
|
||
|
- for key, value in sorted(dict_.items()):
|
||
|
- if isinstance(value, dict):
|
||
|
- value = order_dict(value)
|
||
|
- ordered_dict[key] = value
|
||
|
-
|
||
|
- return ordered_dict
|
||
|
+def _sort_with_priority(data):
|
||
|
+ if isinstance(data, Sequence) and not isinstance(data, str):
|
||
|
+ return [_sort_with_priority(item) for item in data]
|
||
|
+ elif isinstance(data, Mapping):
|
||
|
+ new_data = {}
|
||
|
+ for key in sorted(data.keys(), key=_sort_with_priority_key_func):
|
||
|
+ new_data[key] = _sort_with_priority(data[key])
|
||
|
+ return new_data
|
||
|
+ else:
|
||
|
+ return deepcopy(data)
|
||
|
+
|
||
|
+
|
||
|
+def _sort_with_priority_key_func(key):
|
||
|
+ try:
|
||
|
+ priority = PRIORITY_LIST.index(key)
|
||
|
+ except ValueError:
|
||
|
+ priority = len(PRIORITY_LIST)
|
||
|
+ return (priority, key)
|
||
|
--
|
||
|
2.27.0
|
||
|
|