Skip to content

Commit

Permalink
Merge pull request #60 from nokia/load_config_from_dict
Browse files Browse the repository at this point in the history
Load config from dict
  • Loading branch information
emcek authored Oct 17, 2018
2 parents c3ee884 + df292ab commit a83f3c3
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 29 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ on that machine (and some info about the file):
remote_unix.goto_state(state="UNIX_REMOTE") # make it go to remote shell

ls_cmd = remote_unix.get_cmd(cmd_name="ls", cmd_params={"options": "-l"})
ls_cmd.connection.newline = '\r\n' # tweak since rebex remote console uses such one

remote_files = ls_cmd()

Expand Down Expand Up @@ -134,7 +133,6 @@ ping_cmd = my_unix.get_cmd(cmd_name="ping", cmd_params={"destination": host, "op
remote_unix = DeviceFactory.get_device(name='RebexTestMachine')
remote_unix.goto_state(state="UNIX_REMOTE")
ls_cmd = remote_unix.get_cmd(cmd_name="ls", cmd_params={"options": "-l"})
ls_cmd.connection.newline = '\r\n' # tweak since rebex remote console uses such one
print("Start pinging {} ...".format(host))
ping_cmd.start() # run command in background
Expand Down Expand Up @@ -318,6 +316,11 @@ Please note also that connection is context manager doing open/close actions.
## Reuse freedom
Library gives you freedom which part you want to reuse. We are fan's of "take what you need only".
* You may use configuration files or configure things by Python calls.

```python
load_config(config={'DEVICES': {'MyMachine': {'DEVICE_CLASS': 'moler.device.unixremote.UnixLocal'}}},
config_type='dict')
```
* You may use devices or create commands manually
* You can take connection or build it yourself:

Expand Down
5 changes: 0 additions & 5 deletions examples/command/my_devices.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ DEVICES:

RebexTestMachine:
DEVICE_CLASS: moler.device.unixremote.UnixRemote
STATE_PARAMS: # modify defaults
UNIX_LOCAL:
newline: \n # default (may be skipped)
UNIX_REMOTE:
newline: \r\n
CONNECTION_HOPS:
UNIX_LOCAL: # from state
UNIX_REMOTE: # to state
Expand Down
16 changes: 14 additions & 2 deletions examples/command/unix_ls_on_device.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
from moler.config import load_config
from moler.device.device import DeviceFactory

load_config(path='my_devices.yml')
# configure library directly from dict
load_config(config={'DEVICES': {'DEFAULT_CONNECTION':
{'CONNECTION_DESC': {'io_type': 'terminal', 'variant': 'threaded'}},
'RebexTestMachine':
{'DEVICE_CLASS': 'moler.device.unixremote.UnixRemote',
'CONNECTION_HOPS': {'UNIX_LOCAL':
{'UNIX_REMOTE':
{'execute_command': 'ssh',
'command_params': {'expected_prompt': 'demo@',
'host': 'test.rebex.net',
'login': 'demo',
'password': 'password',
'set_timeout': None}}}}}}},
config_type='dict')

remote_unix = DeviceFactory.get_device(name='RebexTestMachine') # it starts in local shell
remote_unix.goto_state(state="UNIX_REMOTE") # make it go to remote shell

ls_cmd = remote_unix.get_cmd(cmd_name="ls", cmd_params={"options": "-l"})
ls_cmd.connection.newline = '\r\n' # tweak since rebex remote console uses such one

remote_files = ls_cmd()

Expand Down
3 changes: 1 addition & 2 deletions examples/command/unix_ping_and_ls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from moler.config import load_config
from moler.device.device import DeviceFactory

load_config(path='my_devices.yml')
load_config(config='my_devices.yml')

my_unix = DeviceFactory.get_device(name='MyMachine')
host = 'www.google.com'
Expand All @@ -10,7 +10,6 @@
remote_unix = DeviceFactory.get_device(name='RebexTestMachine')
remote_unix.goto_state(state="UNIX_REMOTE")
ls_cmd = remote_unix.get_cmd(cmd_name="ls", cmd_params={"options": "-l"})
ls_cmd.connection.newline = '\r\n' # tweak since rebex remote console uses such one

print("Start pinging {} ...".format(host))
ping_cmd.start() # run command in background
Expand Down
4 changes: 3 additions & 1 deletion examples/command/unix_ps_on_device.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from moler.config import load_config
from moler.device.device import DeviceFactory

load_config(path='my_devices.yml') # description of available devices
load_config(config='my_devices.yml') # description of available devices
# load_config(config={'DEVICES': {'MyMachine': {'DEVICE_CLASS': 'moler.device.unixremote.UnixLocal'}}},
# config_type='dict')
my_unix = DeviceFactory.get_device(name='MyMachine') # take specific device out of available ones
ps_cmd = my_unix.get_cmd(cmd_name="ps", # take command of that device
cmd_params={"options": "-ef"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def ping_observing_task(ext_io_connection, ping_ip):
# -------------------------------------------------------------------
# Configure moler connections (backend code)
# 1) select variant of TCP
load_config(path=os.path.join(os.path.dirname(__file__), "connection_variant.yml"))
load_config(config=os.path.join(os.path.dirname(__file__), "connection_variant.yml"))

# 2) ver.1 - configure named connections by python code
conn_cfg.define_connection(name='net_1', io_type='tcp', host='localhost', port=5671)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def ping_observing_task(ext_io_connection, ping_ip):
# Configure moler connections (backend code)
# 1) configure variant by YAML config file
# 2) ver.2 - configure named connections by YAML config file
load_config(path=os.path.join(os.path.dirname(__file__), "named_connections.yml"))
load_config(config=os.path.join(os.path.dirname(__file__), "named_connections.yml"))

# 3) take default class used to realize tcp-threaded-connection
# -------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion examples/layer_3/network_down_detectors_on_tcp_conn_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def ping_observing_task(ext_io_connection, ping_ip):
# -------------------------------------------------------------------
# Configure moler connections (backend code)
# ver.3 - configure by YAML config file
load_config(path=os.path.join(os.path.dirname(__file__), "connections_new_variant.yml"))
load_config(config=os.path.join(os.path.dirname(__file__), "connections_new_variant.yml"))

# configure class used to realize tcp-threaded-connection
# (default one tcp.ThreadedTcp has no logger)
Expand Down
23 changes: 15 additions & 8 deletions moler/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
__email__ = '[email protected], [email protected], [email protected]'

import yaml
import six
from contextlib import contextmanager

from . import connections as conn_cfg
Expand Down Expand Up @@ -40,23 +41,29 @@ def read_yaml_configfile(path):
return yaml.load(content)


def load_config(path=None, from_env_var=None, config_type='yaml'):
def load_config(config=None, from_env_var=None, config_type='yaml'):
"""
Load Moler's configuration from config file
:param path: config filename directly provided (overwrites 'from_env_var' if both given)
:param config: either dict or config filename directly provided (overwrites 'from_env_var' if both given)
:param from_env_var: name of environment variable storing config filename
:param config_type: 'yaml' (the only one supported now)
:param config_type: 'dict' ('config' param is dict) or 'yaml' ('config' is filename of file with YAML content)
:return: None
"""
if (not path) and (not from_env_var):
raise AssertionError("Provide either 'path' or 'from_env_var' parameter (none given)")
if (not path):
assert (config_type == 'dict') or (config_type == 'yaml') # no other format supported yet
if not config:
if not from_env_var:
raise AssertionError("Provide either 'config' or 'from_env_var' parameter (none given)")
if from_env_var not in os.environ:
raise KeyError("Environment variable '{}' is not set".format(from_env_var))
path = os.environ[from_env_var]
assert config_type == 'yaml' # no other format supported yet
config = read_yaml_configfile(path)
config = read_yaml_configfile(path)
elif config_type == 'yaml':
assert isinstance(config, six.string_types)
path = config
config = read_yaml_configfile(path)
elif config_type == 'dict':
assert isinstance(config, dict)
# TODO: check schema
load_logger_from_config(config)
load_connection_from_config(config)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

setup(
name='moler', # Required
version='0.5.1', # Required
version='0.5.2', # Required
description='Moler is library to help in building automated tests', # Required
long_description=long_description, # Optional
long_description_content_type='text/markdown', # Optional (see note above)
Expand Down
18 changes: 17 additions & 1 deletion test/test_connection_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def test_can_select_connection_loaded_from_config_file(moler_config):
from moler.connection import get_connection

conn_config = os.path.join(os.path.dirname(__file__), "resources", "www_servers_connections.yml")
moler_config.load_config(path=conn_config, config_type='yaml')
moler_config.load_config(config=conn_config, config_type='yaml')

conn = get_connection(name='www_server_1')
assert conn.__module__ == 'moler.io.raw.tcp'
Expand All @@ -121,6 +121,22 @@ def test_can_select_connection_loaded_from_env_variable(moler_config, monkeypatc
assert conn.port == 2345


def test_can_select_connection_loaded_from_dict(moler_config):
from moler.connection import get_connection

configuration_in_dict = {'NAMED_CONNECTIONS':
{'www_server_1': {'io_type': 'tcp', 'host': 'localhost', 'port': 2344}},
'IO_TYPES':
{'default_variant': {'tcp': 'threaded'}}}
moler_config.load_config(config=configuration_in_dict, config_type='dict')

conn = get_connection(name='www_server_1')
assert conn.__module__ == 'moler.io.raw.tcp'
assert conn.__class__.__name__ == 'ThreadedTcp'
assert conn.host == 'localhost'
assert conn.port == 2344


def test_load_config_checks_env_variable_existence(moler_config):
with pytest.raises(KeyError) as err:
moler_config.load_config(from_env_var="MOLER_CONFIG", config_type='yaml')
Expand Down
8 changes: 4 additions & 4 deletions test/test_device_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def test_cannot_select_device_by_nonexisting_name(device_factory):

def test_can_select_device_loaded_from_config_file(moler_config, device_factory):
conn_config = os.path.join(os.path.dirname(__file__), "resources", "device_config.yml")
moler_config.load_config(path=conn_config, config_type='yaml')
moler_config.load_config(config=conn_config, config_type='yaml')

device = device_factory.get_device(name='UNIX')

Expand All @@ -121,7 +121,7 @@ def test_can_select_device_loaded_from_config_file(moler_config, device_factory)

def test_can_select_all_devices_loaded_from_config_file(moler_config, device_factory):
conn_config = os.path.join(os.path.dirname(__file__), "resources", "device_config.yml")
moler_config.load_config(path=conn_config, config_type='yaml')
moler_config.load_config(config=conn_config, config_type='yaml')

device_factory.create_all_devices()

Expand Down Expand Up @@ -151,7 +151,7 @@ def test_load_config_checks_env_variable_existence(moler_config):

def test_return_created_device_when_call_another_time_for_same_named_device(moler_config, device_factory):
conn_config = os.path.join(os.path.dirname(__file__), "resources", "device_config.yml")
moler_config.load_config(path=conn_config, config_type='yaml')
moler_config.load_config(config=conn_config, config_type='yaml')

device = device_factory.get_device(name='UNIX')
same_device = device_factory.get_device(name='UNIX')
Expand Down Expand Up @@ -197,7 +197,7 @@ def test_cannot_load_config_from_when_path_or_from_env_var_not_provide(moler_con
with pytest.raises(AssertionError) as err:
moler_config.load_config()

assert "Provide either 'path' or 'from_env_var' parameter (none given)" in str(err.value)
assert "Provide either 'config' or 'from_env_var' parameter (none given)" in str(err.value)


# --------------------------- resources ---------------------------
Expand Down

0 comments on commit a83f3c3

Please sign in to comment.