diff --git a/lib/ansible/module_utils/junos.py b/lib/ansible/module_utils/junos.py
index 2475feb7242..17873b39373 100644
--- a/lib/ansible/module_utils/junos.py
+++ b/lib/ansible/module_utils/junos.py
@@ -31,8 +31,6 @@ JSON_ACTIONS = frozenset(['merge', 'override', 'update'])
FORMATS = frozenset(['xml', 'text', 'json'])
CONFIG_FORMATS = frozenset(['xml', 'text', 'json', 'set'])
-_DEVICE_CONFIGS = {}
-
junos_argument_spec = {
'host': dict(),
'port': dict(type='int'),
@@ -41,17 +39,17 @@ junos_argument_spec = {
'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
'timeout': dict(type='int', default=10),
'provider': dict(type='dict'),
- 'transport': dict(choices=['cli', 'netconf'])
+ 'transport': dict()
}
def check_args(module, warnings):
provider = module.params['provider'] or {}
for key in junos_argument_spec:
- if key in ('provider', 'transport') and module.params[key]:
+ if key in ('provider',) and module.params[key]:
warnings.append('argument %s has been deprecated and will be '
'removed in a future version' % key)
-def validate_rollback_id(value):
+def _validate_rollback_id(value):
try:
if not 0 <= int(value) <= 49:
raise ValueError
@@ -77,7 +75,7 @@ def load_configuration(module, candidate=None, action='merge', rollback=None, fo
module.fail_json(msg='format must be text when action is set')
if rollback is not None:
- validate_rollback_id(rollback)
+ _validate_rollback_id(rollback)
xattrs = {'rollback': str(rollback)}
else:
xattrs = {'action': action, 'format': format}
@@ -102,7 +100,7 @@ def get_configuration(module, compare=False, format='xml', rollback='0'):
module.fail_json(msg='invalid config format specified')
xattrs = {'format': format}
if compare:
- validate_rollback_id(rollback)
+ _validate_rollback_id(rollback)
xattrs['compare'] = 'rollback'
xattrs['rollback'] = str(rollback)
return send_request(module, Element('get-configuration', xattrs))
@@ -119,6 +117,13 @@ def commit_configuration(module, confirm=False, check=False, comment=None, confi
children(obj, ('confirm-timeout', int(confirm_timeout)))
return send_request(module, obj)
+def command(module, command, format='text', rpc_only=False):
+ xattrs = {'format': format}
+ if rpc_only:
+ command += ' | display xml rpc'
+ xattrs['format'] = 'text'
+ return send_request(module, Element('command', xattrs, text=command))
+
lock_configuration = lambda x: send_request(x, Element('lock-configuration'))
unlock_configuration = lambda x: send_request(x, Element('unlock-configuration'))
@@ -136,9 +141,9 @@ def get_diff(module):
if output:
return output[0].text
-def load(module, candidate, action='merge', commit=False, format='xml'):
- """Loads a configuration element into the target system
- """
+def load_config(module, candidate, action='merge', commit=False, format='xml',
+ comment=None, confirm=False, confirm_timeout=None):
+
with locked_config(module):
resp = load_configuration(module, candidate, action=action, format=format)
@@ -148,72 +153,10 @@ def load(module, candidate, action='merge', commit=False, format='xml'):
if diff:
diff = str(diff).strip()
if commit:
- commit_configuration(module)
+ commit_configuration(module, confirm=confirm, comment=comment,
+ confirm_timeout=confirm_timeout)
else:
discard_changes(module)
return diff
-
-
-# START CLI FUNCTIONS
-
-def get_config(module, flags=[]):
- cmd = 'show configuration '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return _DEVICE_CONFIGS[cmd]
- except KeyError:
- rc, out, err = exec_command(module, cmd)
- if rc != 0:
- module.fail_json(msg='unable to retrieve current config', stderr=err)
- cfg = str(out).strip()
- _DEVICE_CONFIGS[cmd] = cfg
- return cfg
-
-def run_commands(module, commands, check_rc=True):
- responses = list()
- for cmd in to_list(commands):
- cmd = module.jsonify(cmd)
- rc, out, err = exec_command(module, cmd)
- if check_rc and rc != 0:
- module.fail_json(msg=err, rc=rc)
-
- try:
- out = module.from_json(out)
- except ValueError:
- out = str(out).strip()
-
- responses.append(out)
- return responses
-
-def load_config(module, config, commit=False, comment=None,
- confirm=False, confirm_timeout=None):
-
- exec_command(module, 'configure')
-
- for item in to_list(config):
- rc, out, err = exec_command(module, item)
- if rc != 0:
- module.fail_json(msg=str(err))
-
- exec_command(module, 'top')
- rc, diff, err = exec_command(module, 'show | compare')
-
- if commit:
- cmd = 'commit'
- if commit:
- cmd = 'commit confirmed'
- if confirm_timeout:
- cmd +' %s' % confirm_timeout
- if comment:
- cmd += ' comment "%s"' % comment
- cmd += ' and-quit'
- exec_command(module, cmd)
- else:
- for cmd in ['rollback 0', 'exit']:
- exec_command(module, cmd)
-
- return str(diff).strip()
diff --git a/lib/ansible/modules/network/junos/junos_netconf.py b/lib/ansible/modules/network/junos/junos_netconf.py
index 0691ba8208d..acf860ed2fe 100644
--- a/lib/ansible/modules/network/junos/junos_netconf.py
+++ b/lib/ansible/modules/network/junos/junos_netconf.py
@@ -77,19 +77,13 @@ commands:
"""
import re
-from ansible.module_utils.junos import load_config, get_config
from ansible.module_utils.junos import junos_argument_spec, check_args
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import exec_command
from ansible.module_utils.six import iteritems
USE_PERSISTENT_CONNECTION = True
-def check_transport(module):
- transport = (module.params['provider'] or {}).get('transport')
-
- if transport == 'netconf':
- module.fail_json(msg='junos_netconf module is only supported over cli transport')
-
def map_obj_to_commands(updates, module):
want, have = updates
@@ -144,6 +138,32 @@ def map_params_to_obj(module):
return obj
+def get_config(module, flags=[]):
+ rc, out, err = exec_command(module, cmd)
+ if rc != 0:
+ module.fail_json(msg='unable to retrieve current config', stderr=err)
+ return str(out).strip()
+
+def load_config(module, config, commit=False):
+
+ exec_command(module, 'configure')
+
+ for item in to_list(config):
+ rc, out, err = exec_command(module, item)
+ if rc != 0:
+ module.fail_json(msg=str(err))
+
+ exec_command(module, 'top')
+ rc, diff, err = exec_command(module, 'show | compare')
+
+ if commit:
+ exec_command(module, 'commit and-quit')
+ else:
+ for cmd in ['rollback 0', 'exit']:
+ exec_command(module, cmd)
+
+ return str(diff).strip()
+
def main():
"""main entry point for module execution
"""
@@ -153,13 +173,10 @@ def main():
)
argument_spec.update(junos_argument_spec)
- argument_spec['transport'] = dict(choices=['cli'], default='cli')
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
- check_transport(module)
-
warnings = list()
check_args(module, warnings)
diff --git a/lib/ansible/plugins/action/junos.py b/lib/ansible/plugins/action/junos.py
index c5cbc2be720..ca00916bf52 100644
--- a/lib/ansible/plugins/action/junos.py
+++ b/lib/ansible/plugins/action/junos.py
@@ -29,9 +29,6 @@ from ansible.plugins import connection_loader, module_loader
from ansible.compat.six import iteritems
from ansible.module_utils.junos import junos_argument_spec
from ansible.module_utils.basic import AnsibleFallbackNotFound
-from ansible.module_utils._text import to_bytes
-
-from ncclient.xml_ import new_ele, sub_ele, to_xml
try:
from __main__ import display
@@ -56,12 +53,11 @@ class ActionModule(_ActionModule):
return super(ActionModule, self).run(tmp, task_vars)
provider = self.load_provider()
- transport = provider['transport'] or 'cli'
pc = copy.deepcopy(self._play_context)
pc.network_os = 'junos'
- if transport == 'cli':
+ if self._task.action == 'junos_netconf':
pc.connection = 'network_cli'
pc.port = provider['port'] or self._play_context.port or 22
else:
@@ -98,7 +94,6 @@ class ActionModule(_ActionModule):
connection.exec_command('exit')
rc, out, err = connection.exec_command('prompt()')
-
task_vars['ansible_socket'] = socket_path
return super(ActionModule, self).run(tmp, task_vars)
@@ -106,6 +101,9 @@ class ActionModule(_ActionModule):
def _get_socket_path(self, play_context):
ssh = connection_loader.get('ssh', class_only=True)
path = unfrackpath("$HOME/.ansible/pc")
+ # use play_context.connection instea of play_context.port to avoid
+ # collision if netconf is listening on port 22
+ #cp = ssh._create_control_path(play_context.remote_addr, play_context.connection, play_context.remote_user)
cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user)
return cp % dict(directory=path)
diff --git a/test/units/modules/network/junos/__init__.py b/test/units/modules/network/junos/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/test/units/modules/network/junos/fixtures/junos_command_show_version.txt b/test/units/modules/network/junos/fixtures/junos_command_show_version.txt
deleted file mode 100644
index 1e0b8706e54..00000000000
--- a/test/units/modules/network/junos/fixtures/junos_command_show_version.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Hostname: vsrx01
-Model: vSRX
-Junos: 15.1X49-D15.4
-JUNOS Software Release [15.1X49-D15.4]
\ No newline at end of file
diff --git a/test/units/modules/network/junos/junos_module.py b/test/units/modules/network/junos/junos_module.py
deleted file mode 100644
index 0edbff24d8b..00000000000
--- a/test/units/modules/network/junos/junos_module.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# (c) 2016 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-
-# Make coding more python3-ish
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import os
-import json
-import sys
-
-from ansible.compat.tests import unittest
-from ansible.compat.tests.mock import patch, Mock
-from ansible.module_utils import basic
-from ansible.module_utils._text import to_bytes
-
-
-def set_module_args(args):
- args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
- basic._ANSIBLE_ARGS = to_bytes(args)
-
-fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
-fixture_data = {}
-
-def load_fixture(name):
- path = os.path.join(fixture_path, name)
-
- if path in fixture_data:
- return fixture_data[path]
-
- with open(path) as f:
- data = f.read()
-
- try:
- data = json.loads(data)
- except:
- pass
-
- fixture_data[path] = data
- return data
-
-class AnsibleExitJson(Exception):
- pass
-
-class AnsibleFailJson(Exception):
- pass
-
-
-mock_modules = {
- 'ncclient': Mock(),
- 'ncclient.xml_': Mock()
-}
-patch_import = patch.dict('sys.modules', mock_modules)
-patch_import.start()
-
-
-class TestJunosModule(unittest.TestCase):
-
- def execute_module(self, failed=False, changed=False, commands=None,
- sort=True, defaults=False):
-
- self.load_fixtures(commands)
-
- if failed:
- result = self.failed()
- self.assertTrue(result['failed'], result)
- else:
- result = self.changed(changed)
- self.assertEqual(result['changed'], changed, result)
-
- if commands:
- if sort:
- self.assertEqual(sorted(commands), sorted(result['commands']), result['commands'])
- else:
- self.assertEqual(commands, result['commands'], result['commands'])
-
- return result
-
- def failed(self):
- def fail_json(*args, **kwargs):
- kwargs['failed'] = True
- raise AnsibleFailJson(kwargs)
-
- with patch.object(basic.AnsibleModule, 'fail_json', fail_json):
- with self.assertRaises(AnsibleFailJson) as exc:
- self.module.main()
-
- result = exc.exception.args[0]
- self.assertTrue(result['failed'], result)
- return result
-
- def changed(self, changed=False):
- def exit_json(*args, **kwargs):
- if 'changed' not in kwargs:
- kwargs['changed'] = False
- raise AnsibleExitJson(kwargs)
-
- with patch.object(basic.AnsibleModule, 'exit_json', exit_json):
- with self.assertRaises(AnsibleExitJson) as exc:
- self.module.main()
-
- result = exc.exception.args[0]
- self.assertEqual(result['changed'], changed, result)
- return result
-
- def load_fixtures(self, commands=None):
- pass
-
diff --git a/test/units/modules/network/junos/test_junos_command.py b/test/units/modules/network/junos/test_junos_command.py
deleted file mode 100644
index 5907371c448..00000000000
--- a/test/units/modules/network/junos/test_junos_command.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# (c) 2016 Red Hat Inc.
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible. If not, see .
-
-# Make coding more python3-ish
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import json
-
-from ansible.compat.tests.mock import patch
-from .junos_module import TestJunosModule, load_fixture, set_module_args
-
-from ansible.modules.network.junos import junos_command
-
-
-class TestJunosCommandModule(TestJunosModule):
-
- module = junos_command
-
- def setUp(self):
- self.mock_run_commands = patch('ansible.modules.network.junos.junos_command.run_commands')
- self.run_commands = self.mock_run_commands.start()
-
- def tearDown(self):
- self.mock_run_commands.stop()
-
- def load_fixtures(self, commands=None):
-
- def load_from_file(*args, **kwargs):
- module, commands = args
- output = list()
-
- for item in commands:
- try:
- obj = json.loads(item['command'])
- command = obj['command']
- except ValueError:
- command = item['command']
- filename = 'junos_command_%s.txt' % str(command).replace(' ', '_')
- output.append(load_fixture(filename))
- return output
-
- self.run_commands.side_effect = load_from_file
-
- def test_junos_command_format_text(self):
- set_module_args(dict(commands=['show version'], display='text'))
- result = self.execute_module()
- self.assertEqual(len(result['stdout']), 1)
- self.assertTrue(result['stdout'][0].startswith('Hostname'))
-
- def test_junos_command_multiple(self):
- set_module_args(dict(commands=['show version', 'show version'], display='text'))
- result = self.execute_module()
- self.assertEqual(len(result['stdout']), 2)
- self.assertTrue(result['stdout'][0].startswith('Hostname'))
-
- def test_junos_command_wait_for(self):
- wait_for = 'result[0] contains "Hostname"'
- set_module_args(dict(commands=['show version'], wait_for=wait_for, display='text'))
- self.execute_module()
-
- def test_junos_command_wait_for_fails(self):
- wait_for = 'result[0] contains "test string"'
- set_module_args(dict(commands=['show version'], wait_for=wait_for, display='text'))
- self.execute_module(failed=True)
- self.assertEqual(self.run_commands.call_count, 10)
-
- def test_junos_command_retries(self):
- wait_for = 'result[0] contains "test string"'
- set_module_args(dict(commands=['show version'], wait_for=wait_for, retries=2, display='text'))
- self.execute_module(failed=True)
- self.assertEqual(self.run_commands.call_count, 2)
-
- def test_junos_command_match_any(self):
- wait_for = ['result[0] contains "Hostname"',
- 'result[0] contains "test string"']
- set_module_args(dict(commands=['show version'], wait_for=wait_for, match='any', display='text'))
- self.execute_module()
-
- def test_junos_command_match_all(self):
- wait_for = ['result[0] contains "Hostname"',
- 'result[0] contains "Model"']
- set_module_args(dict(commands=['show version'], wait_for=wait_for, match='all', display='text'))
- self.execute_module()
-
- def test_junos_command_match_all_failure(self):
- wait_for = ['result[0] contains "Hostname"',
- 'result[0] contains "test string"']
- commands = ['show version', 'show version']
- set_module_args(dict(commands=commands, wait_for=wait_for, match='all', display='text'))
- self.execute_module(failed=True)