|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# Copyright (c) 2018-2020 Red Hat, Inc.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This file is part of nmstate
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This program is free software: you can redistribute it and/or modify
|
|
Packit Service |
0535c1 |
# it under the terms of the GNU Lesser General Public License as published by
|
|
Packit Service |
0535c1 |
# the Free Software Foundation, either version 2.1 of the License, or
|
|
Packit Service |
0535c1 |
# (at your option) any later version.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# This program is distributed in the hope that it will be useful,
|
|
Packit Service |
0535c1 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
0535c1 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
0535c1 |
# GNU Lesser General Public License for more details.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
# You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
0535c1 |
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
Packit Service |
0535c1 |
#
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
from collections.abc import Mapping
|
|
Packit Service |
0535c1 |
from collections.abc import Sequence
|
|
Packit Service |
0535c1 |
from copy import deepcopy
|
|
Packit Service |
0535c1 |
import difflib
|
|
Packit Service |
0535c1 |
import json
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
import yaml
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
from .schema import DNS
|
|
Packit Service |
0535c1 |
from .schema import Route
|
|
Packit Service |
0535c1 |
from .schema import RouteRule
|
|
Packit Service |
0535c1 |
from .schema import Interface
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
PRIORITY_LIST = (
|
|
Packit Service |
0535c1 |
"name",
|
|
Packit Service |
0535c1 |
"type",
|
|
Packit Service |
0535c1 |
"state",
|
|
Packit Service |
0535c1 |
"enabled",
|
|
Packit Service |
0535c1 |
DNS.KEY,
|
|
Packit Service |
0535c1 |
RouteRule.KEY,
|
|
Packit Service |
0535c1 |
Route.KEY,
|
|
Packit Service |
0535c1 |
Interface.KEY,
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def format_desired_current_state_diff(desired_state, current_state):
|
|
Packit Service |
0535c1 |
pretty_desired_state = PrettyState(desired_state).yaml
|
|
Packit Service |
0535c1 |
pretty_current_state = PrettyState(current_state).yaml
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
diff = "".join(
|
|
Packit Service |
0535c1 |
difflib.unified_diff(
|
|
Packit Service |
0535c1 |
pretty_desired_state.splitlines(True),
|
|
Packit Service |
0535c1 |
pretty_current_state.splitlines(True),
|
|
Packit Service |
0535c1 |
fromfile="desired",
|
|
Packit Service |
0535c1 |
tofile="current",
|
|
Packit Service |
0535c1 |
n=3,
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
return (
|
|
Packit Service |
0535c1 |
"\n"
|
|
Packit Service |
0535c1 |
"desired\n"
|
|
Packit Service |
0535c1 |
"=======\n"
|
|
Packit Service |
0535c1 |
"{}\n"
|
|
Packit Service |
0535c1 |
"current\n"
|
|
Packit Service |
0535c1 |
"=======\n"
|
|
Packit Service |
0535c1 |
"{}\n"
|
|
Packit Service |
0535c1 |
"difference\n"
|
|
Packit Service |
0535c1 |
"==========\n"
|
|
Packit Service |
0535c1 |
"{}\n".format(pretty_desired_state, pretty_current_state, diff)
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
class PrettyState:
|
|
Packit Service |
0535c1 |
def __init__(self, state):
|
|
Packit Service |
0535c1 |
yaml.add_representer(dict, represent_dict)
|
|
Packit Service |
0535c1 |
self.state = _sort_with_priority(state)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
@property
|
|
Packit Service |
0535c1 |
def yaml(self):
|
|
Packit Service |
0535c1 |
return yaml.dump(
|
|
Packit Service |
0535c1 |
self.state, default_flow_style=False, explicit_start=True
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
@property
|
|
Packit Service |
0535c1 |
def json(self):
|
|
Packit Service |
0535c1 |
return json.dumps(self.state, indent=4, separators=(",", ": "))
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def represent_dict(dumper, data):
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
Represent dictionary with insert order
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
value = []
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
for item_key, item_value in data.items():
|
|
Packit Service |
0535c1 |
node_key = dumper.represent_data(item_key)
|
|
Packit Service |
0535c1 |
node_value = dumper.represent_data(item_value)
|
|
Packit Service |
0535c1 |
value.append((node_key, node_value))
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
return yaml.nodes.MappingNode("tag:yaml.org,2002:map", value)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def represent_unicode(_, data):
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
Represent unicode as regular string
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
Source:
|
|
Packit Service |
0535c1 |
https://stackoverflow.com/questions/1950306/pyyaml-dumping-without-tags
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
"""
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
return yaml.ScalarNode(
|
|
Packit Service |
0535c1 |
tag="tag:yaml.org,2002:str", value=data.encode("utf-8")
|
|
Packit Service |
0535c1 |
)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _sort_with_priority(data):
|
|
Packit Service |
0535c1 |
if isinstance(data, Sequence) and not isinstance(data, str):
|
|
Packit Service |
0535c1 |
return [_sort_with_priority(item) for item in data]
|
|
Packit Service |
0535c1 |
elif isinstance(data, Mapping):
|
|
Packit Service |
0535c1 |
new_data = {}
|
|
Packit Service |
0535c1 |
for key in sorted(data.keys(), key=_sort_with_priority_key_func):
|
|
Packit Service |
0535c1 |
new_data[key] = _sort_with_priority(data[key])
|
|
Packit Service |
0535c1 |
return new_data
|
|
Packit Service |
0535c1 |
else:
|
|
Packit Service |
0535c1 |
return deepcopy(data)
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
|
|
Packit Service |
0535c1 |
def _sort_with_priority_key_func(key):
|
|
Packit Service |
0535c1 |
try:
|
|
Packit Service |
0535c1 |
priority = PRIORITY_LIST.index(key)
|
|
Packit Service |
0535c1 |
except ValueError:
|
|
Packit Service |
0535c1 |
priority = len(PRIORITY_LIST)
|
|
Packit Service |
0535c1 |
return (priority, key)
|