diff options
-rw-r--r-- | lib/ansible/executor/play_iterator.py | 62 | ||||
-rw-r--r-- | lib/ansible/module_utils/eos.py | 35 | ||||
-rw-r--r-- | lib/ansible/module_utils/iosxr.py | 35 | ||||
-rw-r--r-- | lib/ansible/module_utils/netcmd.py | 35 | ||||
-rw-r--r-- | lib/ansible/module_utils/network.py | 36 | ||||
-rw-r--r-- | lib/ansible/module_utils/urls.py | 71 | ||||
-rw-r--r-- | lib/ansible/module_utils/vyos.py | 35 | ||||
m--------- | lib/ansible/modules/core | 14 | ||||
m--------- | lib/ansible/modules/extras | 18 | ||||
-rw-r--r-- | lib/ansible/playbook/base.py | 44 | ||||
-rw-r--r-- | lib/ansible/playbook/block.py | 1 | ||||
-rw-r--r-- | test/integration/Makefile | 4 | ||||
-rw-r--r-- | test/units/executor/test_play_iterator.py | 2 |
13 files changed, 236 insertions, 156 deletions
diff --git a/lib/ansible/executor/play_iterator.py b/lib/ansible/executor/play_iterator.py index d1366bbbc5..a8c00833e7 100644 --- a/lib/ansible/executor/play_iterator.py +++ b/lib/ansible/executor/play_iterator.py @@ -154,6 +154,8 @@ class PlayIterator: self._play = play self._blocks = [] + self._task_uuid_cache = dict() + # Default options to gather gather_subset = C.DEFAULT_GATHER_SUBSET gather_timeout = C.DEFAULT_GATHER_TIMEOUT @@ -179,12 +181,17 @@ class PlayIterator: setup_block = setup_block.filter_tagged_tasks(play_context, all_vars) self._blocks.append(setup_block) + self.cache_block_tasks(setup_block) for block in self._play.compile(): new_block = block.filter_tagged_tasks(play_context, all_vars) if new_block.has_tasks(): + self.cache_block_tasks(new_block) self._blocks.append(new_block) + for handler_block in self._play.handlers: + self.cache_block_tasks(handler_block) + self._host_states = {} start_at_matched = False for host in inventory.get_hosts(self._play.hosts): @@ -227,6 +234,18 @@ class PlayIterator: return self._host_states[host.name].copy() + def cache_block_tasks(self, block): + def _cache_portion(p): + for t in p: + if isinstance(t, Block): + self.cache_block_tasks(t) + elif t._uuid not in self._task_uuid_cache: + self._task_uuid_cache[t._uuid] = t + + for portion in (block.block, block.rescue, block.always): + if portion is not None: + _cache_portion(portion) + def get_next_task_for_host(self, host, peek=False): display.debug("getting the next task for host %s" % host.name) @@ -514,46 +533,7 @@ class PlayIterator: else: the_uuid = task - def _search_block(block): - ''' - helper method to check a block's task lists (block/rescue/always) - for a given task uuid. If a Block is encountered in the place of a - task, it will be recursively searched (this happens when a task - include inserts one or more blocks into a task list). - ''' - for b in (block.block, block.rescue, block.always): - for t in b: - if isinstance(t, Block): - res = _search_block(t) - if res: - return res - elif t._uuid == the_uuid: - return t - return None - - def _search_state(state): - for block in state._blocks: - res = _search_block(block) - if res: - return res - for child_state in (state.tasks_child_state, state.rescue_child_state, state.always_child_state): - if child_state is not None: - res = _search_state(child_state) - if res: - return res - return None - - s = self.get_host_state(host) - res = _search_state(s) - if res: - return res - - for block in self._play.handlers: - res = _search_block(block) - if res: - return res - - return None + return self._task_uuid_cache.get(the_uuid, None) def _insert_tasks_into_state(self, state, task_list): # if we've failed at all, or if the task list is empty, just return the current state @@ -590,5 +570,7 @@ class PlayIterator: return state def add_tasks(self, host, task_list): + for b in task_list: + self.cache_block_tasks(b) self._host_states[host.name] = self._insert_tasks_into_state(self.get_host_state(host), task_list) diff --git a/lib/ansible/module_utils/eos.py b/lib/ansible/module_utils/eos.py index 355453ce8d..8f596df50d 100644 --- a/lib/ansible/module_utils/eos.py +++ b/lib/ansible/module_utils/eos.py @@ -1,20 +1,29 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. # -# (c) 2015 Peter Sprygada, <psprygada@ansible.com> +# Copyright (c) 2015 Peter Sprygada, <psprygada@ansible.com> # -# This file is part of Ansible +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: # -# 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. +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. # -# 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 <http://www.gnu.org/licenses/>. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # import re diff --git a/lib/ansible/module_utils/iosxr.py b/lib/ansible/module_utils/iosxr.py index 33c5888447..357ef6b42d 100644 --- a/lib/ansible/module_utils/iosxr.py +++ b/lib/ansible/module_utils/iosxr.py @@ -1,20 +1,29 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. # -# (c) 2015 Peter Sprygada, <psprygada@ansible.com> +# Copyright (c) 2015 Peter Sprygada, <psprygada@ansible.com> # -# This file is part of Ansible +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: # -# 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. +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. # -# 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 <http://www.gnu.org/licenses/>. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # import re diff --git a/lib/ansible/module_utils/netcmd.py b/lib/ansible/module_utils/netcmd.py index 651c437dd0..fc77af8d12 100644 --- a/lib/ansible/module_utils/netcmd.py +++ b/lib/ansible/module_utils/netcmd.py @@ -1,20 +1,29 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. # -# (c) 2015 Peter Sprygada, <psprygada@ansible.com> +# Copyright (c) 2015 Peter Sprygada, <psprygada@ansible.com> # -# This file is part of Ansible +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: # -# 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. +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. # -# 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 <http://www.gnu.org/licenses/>. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # import re diff --git a/lib/ansible/module_utils/network.py b/lib/ansible/module_utils/network.py index c16c6895df..27acbb7f8e 100644 --- a/lib/ansible/module_utils/network.py +++ b/lib/ansible/module_utils/network.py @@ -1,21 +1,31 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. # -# (c) 2015 Peter Sprygada, <psprygada@ansible.com> +# Copyright (c) 2015 Peter Sprygada, <psprygada@ansible.com> # -# This file is part of Ansible +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: # -# 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. +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. # -# 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 <http://www.gnu.org/licenses/>. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # + import itertools from ansible.module_utils.basic import AnsibleModule diff --git a/lib/ansible/module_utils/urls.py b/lib/ansible/module_utils/urls.py index bbbf0d8544..2ed8e10f15 100644 --- a/lib/ansible/module_utils/urls.py +++ b/lib/ansible/module_utils/urls.py @@ -81,6 +81,21 @@ # agrees to be bound by the terms and conditions of this License # Agreement. +''' +The **urls** utils module offers a replacement for the urllib2 python library. + +urllib2 is the python stdlib way to retrieve files from the Internet but it +lacks some security features (around verifying SSL certificates) that users +should care about in most situations. Using the functions in this module corrects +deficiencies in the urllib2 module wherever possible. + +There are also third-party libraries (for instance, requests) which can be used +to replace urllib2 with a more secure library. However, all third party libraries +require that the library be installed on the managed machine. That is an extra step +for users making use of a module. If possible, avoid third party libraries by using +this code instead. +''' + import netrc import os import re @@ -728,11 +743,11 @@ def maybe_add_ssl_handler(url, validate_certs): def open_url(url, data=None, headers=None, method=None, use_proxy=True, - force=False, last_mod_time=None, timeout=10, validate_certs=True, - url_username=None, url_password=None, http_agent=None, - force_basic_auth=False, follow_redirects='urllib2'): + force=False, last_mod_time=None, timeout=10, validate_certs=True, + url_username=None, url_password=None, http_agent=None, + force_basic_auth=False, follow_redirects='urllib2'): ''' - Fetches a file from an HTTP/FTP server using urllib2 + Sends a request via HTTP(S) or FTP using urllib2 (Python2) or urllib (Python3) Does not require the module environment ''' @@ -870,23 +885,49 @@ def url_argument_spec(): that will be requesting content via urllib/urllib2 ''' return dict( - url = dict(), - force = dict(default='no', aliases=['thirsty'], type='bool'), - http_agent = dict(default='ansible-httpget'), - use_proxy = dict(default='yes', type='bool'), - validate_certs = dict(default='yes', type='bool'), - url_username = dict(required=False), - url_password = dict(required=False), - force_basic_auth = dict(required=False, type='bool', default='no'), + url=dict(), + force=dict(default='no', aliases=['thirsty'], type='bool'), + http_agent=dict(default='ansible-httpget'), + use_proxy=dict(default='yes', type='bool'), + validate_certs=dict(default='yes', type='bool'), + url_username=dict(required=False), + url_password=dict(required=False), + force_basic_auth=dict(required=False, type='bool', default='no'), ) def fetch_url(module, url, data=None, headers=None, method=None, use_proxy=True, force=False, last_mod_time=None, timeout=10): - ''' - Fetches a file from an HTTP/FTP server using urllib2. Requires the module environment - ''' + '''Sends a request via HTTP(S) or FTP (needs the module as parameter) + + :arg module: The AnsibleModule (used to get username, password etc. (s.b.). + :arg url: The url to use. + + :kwarg data: The data to be sent (in case of POST/PUT). + :kwarg headers: A dict with the request headers. + :kwarg method: "POST", "PUT", etc. + :kwarg boolean use_proxy: Default: True + :kwarg boolean force: If True: Do not get a cached copy (Default: False) + :kwarg last_mod_time: Default: None + :kwarg int timeout: Default: 10 + + :returns: A tuple of (**response**, **info**). Use ``response.body()`` to read the data. + The **info** contains the 'status' and other meta data. When a HttpError (status > 400) + occurred then ``info['body']`` contains the error response data:: + + Example:: + + data={...} + resp, info = fetch_url("http://example.com", + data=module.jsonify(data) + header={Content-type': 'application/json'}, + method="POST") + status_code = info["status"] + body = resp.read() + if status_code >= 400 : + body = info['body'] +''' if not HAS_URLPARSE: module.fail_json(msg='urlparse is not installed') diff --git a/lib/ansible/module_utils/vyos.py b/lib/ansible/module_utils/vyos.py index 7002e46d74..840d3b0b2e 100644 --- a/lib/ansible/module_utils/vyos.py +++ b/lib/ansible/module_utils/vyos.py @@ -1,20 +1,29 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. # -# (c) 2015 Peter Sprygada, <psprygada@ansible.com> +# Copyright (c) 2015 Peter Sprygada, <psprygada@ansible.com> # -# This file is part of Ansible +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: # -# 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. +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. # -# 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 <http://www.gnu.org/licenses/>. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # import itertools diff --git a/lib/ansible/modules/core b/lib/ansible/modules/core -Subproject 5d7b46e0ddb7f55f1dbc6f69b973f1bcd385102 +Subproject a216ef210b3d8fc332afb252cdf787f4744585f diff --git a/lib/ansible/modules/extras b/lib/ansible/modules/extras -Subproject eaa71f51d652d803bff527a5941c027cb206d88 +Subproject 39153ea1548d208545a31d4fa581c70c22e90c9 diff --git a/lib/ansible/playbook/base.py b/lib/ansible/playbook/base.py index ca6ad67c17..b9edce54e4 100644 --- a/lib/ansible/playbook/base.py +++ b/lib/ansible/playbook/base.py @@ -65,9 +65,6 @@ class Base: _ignore_errors = FieldAttribute(isa='bool') _check_mode = FieldAttribute(isa='bool') - # other internal params - _finalized = False - # param names which have been deprecated/removed DEPRECATED_ATTRIBUTES = [ 'sudo', 'sudo_user', 'sudo_pass', 'sudo_exe', 'sudo_flags', @@ -81,9 +78,12 @@ class Base: self._loader = None self._variable_manager = None + # other internal params + self._validated = False + self._finalized = False + # every object gets a random uuid: self._uuid = uuid.uuid4() - #self._uuid = 1 # and initialize the base attributes self._initialize_base_attributes() @@ -272,20 +272,25 @@ class Base: def validate(self, all_vars=dict()): ''' validation that is done at parse time, not load time ''' - # walk all fields in the object - for (name, attribute) in iteritems(self._get_base_attributes()): + if not self._validated: + # walk all fields in the object + for (name, attribute) in iteritems(self._get_base_attributes()): - # run validator only if present - method = getattr(self, '_validate_%s' % name, None) - if method: - method(attribute, name, getattr(self, name)) - else: - # and make sure the attribute is of the type it should be - value = getattr(self, name) - if value is not None: - if attribute.isa == 'string' and isinstance(value, (list, dict)): - raise AnsibleParserError("The field '%s' is supposed to be a string type," - " however the incoming data structure is a %s" % (name, type(value)), obj=self.get_ds()) + # run validator only if present + method = getattr(self, '_validate_%s' % name, None) + if method: + method(attribute, name, getattr(self, name)) + else: + # and make sure the attribute is of the type it should be + value = getattr(self, name) + if value is not None: + if attribute.isa == 'string' and isinstance(value, (list, dict)): + raise AnsibleParserError( + "The field '%s' is supposed to be a string type," + " however the incoming data structure is a %s" % (name, type(value)), obj=self.get_ds() + ) + + self._validated = True def copy(self): ''' @@ -303,9 +308,10 @@ class Base: else: setattr(new_me, name, attr_val) - new_me._loader = self._loader + new_me._loader = self._loader new_me._variable_manager = self._variable_manager - + new_me._validated = self._validated + new_me._finalized = self._finalized new_me._uuid = self._uuid # if the ds value was set on the object, copy it to the new copy too diff --git a/lib/ansible/playbook/block.py b/lib/ansible/playbook/block.py index 493cec2b22..ec6298a2c1 100644 --- a/lib/ansible/playbook/block.py +++ b/lib/ansible/playbook/block.py @@ -192,6 +192,7 @@ class Block(Base, Become, Conditional, Taggable): if self._role: new_me._role = self._role + new_me.validate() return new_me def serialize(self): diff --git a/test/integration/Makefile b/test/integration/Makefile index cc5d26a02e..bf861f641d 100644 --- a/test/integration/Makefile +++ b/test/integration/Makefile @@ -202,13 +202,13 @@ blocks: setup # remove old output log rm -f block_test.out # run the test and check to make sure the right number of completions was logged - ansible-playbook -vv -e outputdir=$(TEST_DIR) test_blocks/main.yml | tee block_test.out + ansible-playbook -vv $(TEST_FLAGS) -e outputdir=$(TEST_DIR) test_blocks/main.yml | tee block_test.out env python -c 'import sys, re; sys.stdout.write(re.sub("\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]", "", sys.stdin.read()))' <block_test.out >block_test_wo_colors.out [ "$$(grep 'TEST COMPLETE' block_test.out | wc -l | sed 's/ *//')" = "$$(egrep '^[0-9]+ plays in' block_test_wo_colors.out | cut -f1 -d' ')" ] # cleanup the output log again, to make sure the test is clean rm -f block_test.out block_test_wo_colors.out # run test with free strategy and again count the completions - ansible-playbook -vv -e outputdir=$(TEST_DIR) test_blocks/main.yml -e test_strategy=free | tee block_test.out + ansible-playbook -vv $(TEST_FLAGS) -e outputdir=$(TEST_DIR) test_blocks/main.yml -e test_strategy=free | tee block_test.out env python -c 'import sys, re; sys.stdout.write(re.sub("\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]", "", sys.stdin.read()))' <block_test.out >block_test_wo_colors.out [ "$$(grep 'TEST COMPLETE' block_test.out | wc -l | sed 's/ *//')" = "$$(egrep '^[0-9]+ plays in' block_test_wo_colors.out | cut -f1 -d' ')" ] diff --git a/test/units/executor/test_play_iterator.py b/test/units/executor/test_play_iterator.py index c0f23e531d..671deaf279 100644 --- a/test/units/executor/test_play_iterator.py +++ b/test/units/executor/test_play_iterator.py @@ -329,7 +329,7 @@ class TestPlayIterator(unittest.TestCase): # test the high-level add_tasks() method s = HostState(blocks=[0,1,2]) itr._insert_tasks_into_state = MagicMock(return_value=s) - itr.add_tasks(hosts[0], [3,4,5]) + itr.add_tasks(hosts[0], [MagicMock(), MagicMock(), MagicMock()]) self.assertEqual(itr._host_states[hosts[0].name], s) # now actually test the lower-level method that does the work |