diff --git a/Makefile b/Makefile index b7c84a51fc1..ec2742f89d8 100644 --- a/Makefile +++ b/Makefile @@ -96,10 +96,10 @@ tests: PYTHONPATH=./lib $(NOSETESTS) -d -w test/units -v # Could do: --with-coverage --cover-package=ansible newtests: - PYTHONPATH=./v2:./lib $(NOSETESTS) -d -w test/v2 -v --with-coverage --cover-package=ansible + PYTHONPATH=./v2:./lib $(NOSETESTS) -d -w v2/test -v --with-coverage --cover-package=ansible newtests-py3: - PYTHONPATH=./v2:./lib $(NOSETESTS3) -d -w test/v2 -v --with-coverage --cover-package=ansible + PYTHONPATH=./v2:./lib $(NOSETESTS3) -d -w v2/test -v --with-coverage --cover-package=ansible authors: sh hacking/authors.sh diff --git a/lib/ansible/modules/core b/lib/ansible/modules/core index cb69744bcee..5af8d55b036 160000 --- a/lib/ansible/modules/core +++ b/lib/ansible/modules/core @@ -1 +1 @@ -Subproject commit cb69744bcee4b4217d83b4a30006635ba69e2aa0 +Subproject commit 5af8d55b0365a5c3278c43b5424bf5f2ddf897b8 diff --git a/lib/ansible/modules/extras b/lib/ansible/modules/extras index 8a4f07eecd2..681db4ce2c5 160000 --- a/lib/ansible/modules/extras +++ b/lib/ansible/modules/extras @@ -1 +1 @@ -Subproject commit 8a4f07eecd2bb877f51b7b04b5352efa6076cce5 +Subproject commit 681db4ce2c534eca4fca57c5a83a5be8035c257d diff --git a/test/v2/errors/__init__.py b/test/v2/errors/__init__.py deleted file mode 100644 index 674334b15a3..00000000000 --- a/test/v2/errors/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . - - diff --git a/test/v2/errors/test_errors.py b/test/v2/errors/test_errors.py deleted file mode 100644 index ca5ecc14933..00000000000 --- a/test/v2/errors/test_errors.py +++ /dev/null @@ -1,48 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . - -import unittest - -from mock import mock_open, patch - -from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject -from ansible.errors import AnsibleError - -class TestErrors(unittest.TestCase): - - def setUp(self): - self.message = 'this is the error message' - - def tearDown(self): - pass - - def test_basic_error(self): - e = AnsibleError(self.message) - self.assertEqual(e.message, self.message) - - def test_error_with_object(self): - obj = AnsibleBaseYAMLObject() - obj._data_source = 'foo.yml' - obj._line_number = 1 - obj._column_number = 1 - - m = mock_open() - m.return_value.readlines.return_value = ['this is line 1\n', 'this is line 2\n', 'this is line 3\n'] - with patch('__builtin__.open', m): - e = AnsibleError(self.message, obj) - - self.assertEqual(e.message, 'this is the error message\nThe error occurred on line 1 of the file foo.yml:\nthis is line 1\n^') diff --git a/test/v2/parsing/__init__.py b/test/v2/parsing/__init__.py deleted file mode 100644 index 1f84012e014..00000000000 --- a/test/v2/parsing/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . diff --git a/test/v2/parsing/test_general.py b/test/v2/parsing/test_general.py deleted file mode 100644 index 9373968cc8f..00000000000 --- a/test/v2/parsing/test_general.py +++ /dev/null @@ -1,102 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . - -import unittest -from ansible.parsing import load -from ansible.errors import AnsibleParserError - -import json - -from io import FileIO - -class MockFile(FileIO): - - def __init__(self, ds, method='json'): - self.ds = ds - self.method = method - - def read(self): - if method == 'json': - return json.dumps(ds) - elif method == 'yaml': - return yaml.dumps(ds) - elif method == 'fail': - return """ - AAARGGGGH - THIS WON'T PARSE !!! - NOOOOOOOOOOOOOOOOOO - """ - else: - raise Exception("untestable serializer") - - def close(self): - pass - -class TestGeneralParsing(unittest.TestCase): - - def __init__(self): - pass - - def setUp(self): - pass - - def tearDown(self): - pass - - def parse_json_from_string(self): - input = """ - { - "asdf" : "1234", - "jkl" : 5678 - } - """ - output = load(input) - self.assertEqual(output['asdf'], '1234') - self.assertEqual(output['jkl'], 5678) - - def parse_json_from_file(self): - output = load(MockFile(dict(a=1,b=2,c=3)),'json') - self.assertEqual(ouput, dict(a=1,b=2,c=3)) - - def parse_yaml_from_dict(self): - input = """ - asdf: '1234' - jkl: 5678 - """ - output = load(input) - self.assertEqual(output['asdf'], '1234') - self.assertEqual(output['jkl'], 5678) - - def parse_yaml_from_file(self): - output = load(MockFile(dict(a=1,b=2,c=3),'yaml')) - self.assertEqual(output, dict(a=1,b=2,c=3)) - - def parse_fail(self): - input = """ - TEXT - *** - NOT VALID - """ - self.assertRaises(load(input), AnsibleParserError) - - def parse_fail_from_file(self): - self.assertRaises(load(MockFile(None,'fail')), AnsibleParserError) - - def parse_fail_invalid_type(self): - self.assertRaises(3000, AnsibleParsingError) - self.assertRaises(dict(a=1,b=2,c=3), AnsibleParserError) - diff --git a/test/v2/parsing/test_mod_args.py b/test/v2/parsing/test_mod_args.py deleted file mode 100644 index ddd5c6f6d4a..00000000000 --- a/test/v2/parsing/test_mod_args.py +++ /dev/null @@ -1,103 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . - -from ansible.parsing.mod_args import ModuleArgsParser -import unittest - -class TestModArgsDwim(unittest.TestCase): - - # TODO: add tests that construct ModuleArgsParser with a task reference - # TODO: verify the AnsibleError raised on failure knows the task - # and the task knows the line numbers - - def setUp(self): - self.m = ModuleArgsParser() - pass - - def _debug(self, mod, args, to): - print("RETURNED module = {0}".format(mod)) - print(" args = {0}".format(args)) - print(" to = {0}".format(to)) - - def tearDown(self): - pass - - def test_basic_shell(self): - mod, args, to = self.m.parse(dict(shell='echo hi')) - self._debug(mod, args, to) - self.assertEqual(mod, 'command') - self.assertEqual(args, dict( - _raw_params = 'echo hi', - _uses_shell = True, - )) - assert to is None - - def test_basic_command(self): - mod, args, to = self.m.parse(dict(command='echo hi')) - self._debug(mod, args, to) - self.assertEqual(mod, 'command') - self.assertEqual(args, dict( - _raw_params = 'echo hi', - )) - assert to is None - - def test_shell_with_modifiers(self): - mod, args, to = self.m.parse(dict(shell='/bin/foo creates=/tmp/baz removes=/tmp/bleep')) - self._debug(mod, args, to) - self.assertEqual(mod, 'command') - self.assertEqual(args, dict( - creates = '/tmp/baz', - removes = '/tmp/bleep', - _raw_params = '/bin/foo', - _uses_shell = True, - )) - assert to is None - - def test_normal_usage(self): - mod, args, to = self.m.parse(dict(copy='src=a dest=b')) - self._debug(mod, args, to) - self.assertEqual(mod, 'copy') - self.assertEqual(args, dict(src='a', dest='b')) - assert to is None - - def test_complex_args(self): - mod, args, to = self.m.parse(dict(copy=dict(src='a', dest='b'))) - self._debug(mod, args, to) - self.assertEqual(mod, 'copy') - self.assertEqual(args, dict(src='a', dest='b')) - assert to is None - - def test_action_with_complex(self): - mod, args, to = self.m.parse(dict(action=dict(module='copy', src='a', dest='b'))) - self._debug(mod, args, to) - self.assertEqual(mod, 'copy') - self.assertEqual(args, dict(src='a', dest='b')) - assert to is None - - def test_action_with_complex_and_complex_args(self): - mod, args, to = self.m.parse(dict(action=dict(module='copy', args=dict(src='a', dest='b')))) - self._debug(mod, args, to) - self.assertEqual(mod, 'copy') - self.assertEqual(args, dict(src='a', dest='b')) - assert to is None - - def test_local_action_string(self): - mod, args, to = self.m.parse(dict(local_action='copy src=a dest=b')) - self._debug(mod, args, to) - self.assertEqual(mod, 'copy') - self.assertEqual(args, dict(src='a', dest='b')) - assert to is 'localhost' diff --git a/test/v2/parsing/yaml/__init__.py b/test/v2/parsing/yaml/__init__.py deleted file mode 100644 index 1f84012e014..00000000000 --- a/test/v2/parsing/yaml/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . diff --git a/test/v2/parsing/yaml/test_yaml.py b/test/v2/parsing/yaml/test_yaml.py deleted file mode 100644 index 90a4bc3a843..00000000000 --- a/test/v2/parsing/yaml/test_yaml.py +++ /dev/null @@ -1,96 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . - -import unittest - -from yaml.scanner import ScannerError - -from ansible.parsing.yaml import safe_load -from ansible.parsing.yaml.objects import AnsibleMapping - -# a single dictionary instance -data1 = '''--- -key: value -''' - -# multiple dictionary instances -data2 = '''--- -- key1: value1 -- key2: value2 - -- key3: value3 - - -- key4: value4 -''' - -# multiple dictionary instances with other nested -# dictionaries contained within those -data3 = '''--- -- key1: - subkey1: subvalue1 - subkey2: subvalue2 - subkey3: - subsubkey1: subsubvalue1 -- key2: - subkey4: subvalue4 -- list1: - - list1key1: list1value1 - list1key2: list1value2 - list1key3: list1value3 -''' - -bad_data1 = '''--- -foo: bar - bam: baz -''' - -class TestSafeLoad(unittest.TestCase): - - def setUp(self): - pass - - def tearDown(self): - pass - - def test_safe_load_bad(self): - # test the loading of bad yaml data - self.assertRaises(ScannerError, safe_load, bad_data1) - - def test_safe_load(self): - # test basic dictionary - res = safe_load(data1) - self.assertEqual(type(res), AnsibleMapping) - self.assertEqual(res._line_number, 2) - - # test data with multiple dictionaries - res = safe_load(data2) - self.assertEqual(len(res), 4) - self.assertEqual(res[0]._line_number, 2) - self.assertEqual(res[1]._line_number, 3) - self.assertEqual(res[2]._line_number, 5) - self.assertEqual(res[3]._line_number, 8) - - # test data with multiple sub-dictionaries - res = safe_load(data3) - self.assertEqual(len(res), 3) - self.assertEqual(res[0]._line_number, 2) - self.assertEqual(res[1]._line_number, 7) - self.assertEqual(res[2]._line_number, 9) - self.assertEqual(res[0]['key1']._line_number, 3) - self.assertEqual(res[1]['key2']._line_number, 8) - self.assertEqual(res[2]['list1'][0]._line_number, 10) diff --git a/test/v2/playbook/__init__.py b/test/v2/playbook/__init__.py deleted file mode 100644 index 1f84012e014..00000000000 --- a/test/v2/playbook/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . diff --git a/test/v2/playbook/test_task.py b/test/v2/playbook/test_task.py deleted file mode 100644 index b6f869cd210..00000000000 --- a/test/v2/playbook/test_task.py +++ /dev/null @@ -1,84 +0,0 @@ -# (c) 2012-2014, Michael DeHaan -# -# 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 . - -from ansible.playbook.task import Task -import unittest - -basic_shell_task = dict( - name = 'Test Task', - shell = 'echo hi' -) - -kv_shell_task = dict( - action = 'shell echo hi' -) - -class TestTask(unittest.TestCase): - - def setUp(self): - pass - - def tearDown(self): - pass - - def test_construct_empty_task(self): - t = Task() - - def test_construct_task_with_role(self): - pass - - def test_construct_task_with_block(self): - pass - - def test_construct_task_with_role_and_block(self): - pass - - def test_load_task_simple(self): - t = Task.load(basic_shell_task) - assert t is not None - self.assertEqual(t.name, basic_shell_task['name']) - self.assertEqual(t.action, 'command') - self.assertEqual(t.args, dict(_raw_params='echo hi', _uses_shell=True)) - - def test_load_task_kv_form(self): - t = Task.load(kv_shell_task) - print("task action is %s" % t.action) - self.assertEqual(t.action, 'command') - self.assertEqual(t.args, dict(_raw_params='echo hi', _uses_shell=True)) - - def test_task_auto_name(self): - assert 'name' not in kv_shell_task - t = Task.load(kv_shell_task) - #self.assertEqual(t.name, 'shell echo hi') - - def test_task_auto_name_with_role(self): - pass - - def test_load_task_complex_form(self): - pass - - def test_can_load_module_complex_form(self): - pass - - def test_local_action_implies_delegate(self): - pass - - def test_local_action_conflicts_with_delegate(self): - pass - - def test_delegate_to_parses(self): - pass diff --git a/v2/ansible/constants.py b/v2/ansible/constants.py index 861dd5325c1..d1d9b69fd37 100644 --- a/v2/ansible/constants.py +++ b/v2/ansible/constants.py @@ -18,7 +18,12 @@ import os import pwd import sys -import ConfigParser +try: + import configparser +except ImportError: + # Python 2.7 + import ConfigParser as configparser + from string import ascii_letters, digits # copied from utils, avoid circular reference fun :) @@ -60,7 +65,7 @@ def _get_config(p, section, key, env_var, default): def load_config_file(): ''' Load Config File order(first found is used): ENV, CWD, HOME, /etc/ansible ''' - p = ConfigParser.ConfigParser() + p = configparser.ConfigParser() path0 = os.getenv("ANSIBLE_CONFIG", None) if path0 is not None: @@ -73,8 +78,8 @@ def load_config_file(): if path is not None and os.path.exists(path): try: p.read(path) - except ConfigParser.Error as e: - print "Error reading config file: \n%s" % e + except configparser.Error as e: + print("Error reading config file: \n{0}".format(e)) sys.exit(1) return p return None diff --git a/v2/ansible/parsing/mod_args.py b/v2/ansible/parsing/mod_args.py index 2e5b4016013..534aca8cd80 100644 --- a/v2/ansible/parsing/mod_args.py +++ b/v2/ansible/parsing/mod_args.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . -import exceptions +from six import iteritems, string_types from ansible.errors import AnsibleParserError from ansible.plugins import module_finder @@ -141,7 +141,7 @@ class ModuleArgsParser(object): if isinstance(thing, dict): # form is like: local_action: { module: 'xyz', x: 2, y: 3 } ... uncommon! args = thing - elif isinstance(thing, basestring): + elif isinstance(thing, string_types): # form is like: local_action: copy src=a dest=b ... pretty common args = parse_kv(thing) else: @@ -173,7 +173,7 @@ class ModuleArgsParser(object): args = thing.copy() del args['module'] - elif isinstance(thing, basestring): + elif isinstance(thing, string_types): # form is like: copy: src=a dest=b ... common shorthand throughout ansible (action, args) = self._split_module_string(thing) args = parse_kv(args) @@ -222,7 +222,7 @@ class ModuleArgsParser(object): raise AnsibleParserError("conflicting action statements", obj=self._task) # walk the input dictionary to see we recognize a module name - for (item, value) in ds.iteritems(): + for (item, value) in iteritems(ds): if item in module_finder: # finding more than one module name is a problem if action is not None: diff --git a/v2/ansible/parsing/splitter.py b/v2/ansible/parsing/splitter.py index 17946f663b2..d96a8c313ac 100644 --- a/v2/ansible/parsing/splitter.py +++ b/v2/ansible/parsing/splitter.py @@ -27,7 +27,7 @@ def parse_kv(args, check_raw=False): if args is not None: try: vargs = split_args(args) - except ValueError, ve: + except ValueError as ve: if 'no closing quotation' in str(ve).lower(): raise errors.AnsibleError("error parsing argument string, try quoting the entire line.") else: diff --git a/v2/ansible/playbook/base.py b/v2/ansible/playbook/base.py index 3c07dba29a4..3d236df7616 100644 --- a/v2/ansible/playbook/base.py +++ b/v2/ansible/playbook/base.py @@ -15,6 +15,10 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . +from io import FileIO + +from six import iteritems, string_types + from ansible.playbook.attribute import Attribute, FieldAttribute from ansible.parsing import load as ds_load @@ -25,7 +29,7 @@ class Base(object): # each class knows attributes set upon it, see Task.py for example self._attributes = dict() - for (name, value) in self.__class__.__dict__.iteritems(): + for (name, value) in iteritems(self.__class__.__dict__): aname = name[1:] if isinstance(value, Attribute): self._attributes[aname] = value.default @@ -40,7 +44,7 @@ class Base(object): assert ds is not None - if isinstance(ds, basestring) or isinstance(ds, file): + if isinstance(ds, string_types) or isinstance(ds, FileIO): ds = ds_load(ds) # we currently don't do anything with private attributes but may @@ -49,7 +53,7 @@ class Base(object): ds = self.munge(ds) # walk all attributes in the class - for (name, attribute) in self.__class__.__dict__.iteritems(): + for (name, attribute) in iteritems(self.__class__.__dict__): aname = name[1:] # process Field attributes which get loaded from the YAML