Merge "Refactor "yaml modification"-related methods" into stable/mitaka

This commit is contained in:
Jenkins 2016-07-26 08:14:05 +00:00 committed by Gerrit Code Review
commit 8b3f7db3b5
2 changed files with 98 additions and 79 deletions

View File

@ -14,13 +14,15 @@
import os
import re
from six.moves import cStringIO
from warnings import warn
from devops.helpers.helpers import wait
from devops.models import DiskDevice
from devops.models import Node
from devops.models import Volume
from proboscis.asserts import assert_equal
# noinspection PyUnresolvedReferences
from six.moves import cStringIO
import yaml
from fuelweb_test import logger
@ -36,6 +38,7 @@ from fuelweb_test.settings import MIRROR_UBUNTU
from fuelweb_test.settings import PLUGIN_PACKAGE_VERSION
from fuelweb_test.settings import FUEL_SETTINGS_YAML
from fuelweb_test.settings import NESSUS_IMAGE_PATH
from fuelweb_test.helpers.utils import YamlEditor
class BaseActions(object):
@ -69,18 +72,13 @@ class BaseActions(object):
to identify which element should be used
:return: nothing
"""
with open(old_file, 'r') as f_old:
yaml_dict = yaml.load(f_old)
origin_yaml = yaml_dict
for k in element[:-1]:
yaml_dict = yaml_dict[k]
yaml_dict[element[-1]] = value
with open(new_file, 'w') as f_new:
yaml.dump(origin_yaml, f_new, default_flow_style=False,
default_style='"')
warn("Function is deprecated, use utils.YamlEditor instead",
DeprecationWarning)
old_content = YamlEditor(old_file).get_content()
open(new_file, "a").close()
with YamlEditor(new_file) as editor:
editor.content = old_content
editor.change_value(element, value)
@staticmethod
def get_value_from_local_yaml(yaml_file, element):
@ -94,21 +92,11 @@ class BaseActions(object):
to identify which element should be used
:return obj: value
"""
with open(yaml_file, 'r') as f_old:
yaml_dict = yaml.load(f_old)
warn("Function is deprecated, use utils.YamlEditor instead",
DeprecationWarning)
return YamlEditor(yaml_file).get_value(element)
for i, k in enumerate(element):
try:
yaml_dict = yaml_dict[k]
except IndexError:
raise IndexError("Element {0} not found in the file {1}"
.format(element[: i + 1], f_old))
except KeyError:
raise KeyError("Element {0} not found in the file {1}"
.format(element[: i + 1], f_old))
return yaml_dict
def change_remote_yaml(self, path_to_file, element, value):
def change_remote_yaml(self, path_to_file, element, value, ip=None):
"""Changes values in the yaml file stored
There is no need to copy file manually
:param path_to_file: absolute path to the file
@ -116,22 +104,10 @@ class BaseActions(object):
:param value: new value for element
:return: Nothing
"""
old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid()))
new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid()))
self.ssh_manager.download_from_remote(
ip=self.admin_ip,
destination=path_to_file,
target=old_file
)
self.put_value_to_local_yaml(old_file, new_file, element, value)
self.ssh_manager.upload_to_remote(
ip=self.admin_ip,
source=new_file,
target=path_to_file
)
os.remove(old_file)
os.remove(new_file)
warn("Function is deprecated, use utils.YamlEditor instead",
DeprecationWarning)
with YamlEditor(path_to_file, self.admin_ip) as editor:
editor.change_value(element, value)
def get_value_from_remote_yaml(self, path_to_file, element):
"""Get a value from the yaml file stored
@ -141,41 +117,9 @@ class BaseActions(object):
:param list element: list with path to the element
:return obj: value
"""
host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
self.ssh_manager.download_from_remote(
ip=self.admin_ip,
destination=path_to_file,
target=host_tmp_file
)
value = self.get_value_from_local_yaml(host_tmp_file, element)
os.remove(host_tmp_file)
return value
def put_value_to_remote_yaml(self, path_to_file, element, value):
"""Put a value to the yaml file stored
on the master node
:param str path_to_file: absolute path to the file
:param list element: list with path to the element be changed
:param value: new value for element
:return: None
"""
host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
self.ssh_manager.download_from_remote(
ip=self.admin_ip,
destination=path_to_file,
target=host_tmp_file
)
self.put_value_to_local_yaml(host_tmp_file, host_tmp_file,
element, value)
self.ssh_manager.upload_to_remote(
ip=self.admin_ip,
source=host_tmp_file,
target=path_to_file
)
os.remove(host_tmp_file)
warn("Function is deprecated, use utils.YamlEditor instead",
DeprecationWarning)
return YamlEditor(path_to_file, self.admin_ip).get_value(element)
class AdminActions(BaseActions):
@ -520,7 +464,7 @@ class FuelPluginBuilder(BaseActions):
self.change_remote_yaml(metadata_path, ['fuel_version'], fuel_version)
releases = self.get_value_from_remote_yaml(metadata_path, ['releases'])
releases[0]['version'] = openstack_version
self.put_value_to_remote_yaml(metadata_path, ['releases'], releases)
self.change_remote_yaml(metadata_path, ['releases'], releases)
def fpb_validate_plugin(self, path):
"""

View File

@ -1485,3 +1485,78 @@ class SettingsChanger(object):
def attrs(self, attrs):
self._attrs = attrs['editable']
# pylint: enable=eval-used
class YamlEditor(object):
"""Manipulations with local or remote .yaml files.
Usage:
with YamlEditor("tasks.yaml") as editor:
editor.content[key] = "value"
with YamlEditor("astute.yaml", ip=self.admin_ip) as editor:
editor.content[key] = "value"
"""
def __init__(self, file_path, ip=None, port=None):
self.file_path = file_path
self.ip = ip
self.port = port or 22
self.content = None
self.original_content = None
def __get_file(self, mode="r"):
if self.ip:
return SSHManager().open_on_remote(self.ip, self.file_path,
mode=mode, port=self.port)
else:
return open(self.file_path, mode)
def get_content(self):
with self.__get_file() as file_obj:
return yaml.safe_load(file_obj)
def write_content(self, content=None):
if content:
self.content = content
with self.__get_file("w") as file_obj:
yaml.dump(self.content, file_obj,
default_flow_style=False,
default_style='"')
def __enter__(self):
self.content = self.get_content()
self.original_content = copy.deepcopy(self.content)
return self
def change_value(self, element, value):
"""Change 'value' of 'element' (backward compatibility)
THIS METHOD WILL BE REMOVED AFTER PLUGIN TESTS REFACTORING!
Try to use 'content' field first before executing this method!"""
self.content = self.get_content()
result_dict = temp_dict = copy.deepcopy(self.content)
for k in element[:-1]:
temp_dict = temp_dict[k]
temp_dict[element[-1]] = value
self.content = result_dict
return self.content
def get_value(self, element):
"""Return 'value' of 'element' (backward compatibility)
THIS METHOD WILL BE REMOVED AFTER PLUGIN TESTS REFACTORING!
Try to use 'content' field first before executing this method!"""
self.content = self.get_content()
temp = self.content
for k in element[:-1]:
try:
temp = temp[k]
except (KeyError, IndexError):
logger.error("Element {0!r} was not found in the config:\n"
"{1!r}".format(k, self.content))
raise
return temp[element[-1]]
def __exit__(self, x, y, z):
if self.content == self.original_content:
return
self.write_content()