Merge branch 'v2_final' into devel_switch_v2

pull/11129/head
James Cammarata 10 years ago
commit fe41f109a9

@ -239,7 +239,7 @@ class PlayIterator:
self._host_states[host.name] = s self._host_states[host.name] = s
def get_failed_hosts(self): def get_failed_hosts(self):
return dict((host, True) for (host, state) in self._host_states.iteritems() if state.run_state == self.ITERATING_COMPLETE and state.fail_state != self.FAILED_NONE) return dict((host, True) for (host, state) in self._host_states.iteritems() if state.fail_state != self.FAILED_NONE)
def get_original_task(self, host, task): def get_original_task(self, host, task):
''' '''

@ -59,11 +59,9 @@ class Group:
depth=self.depth, depth=self.depth,
) )
debug("serializing group, result is: %s" % result)
return result return result
def deserialize(self, data): def deserialize(self, data):
debug("deserializing group, data is: %s" % data)
self.__init__() self.__init__()
self.name = data.get('name') self.name = data.get('name')
self.vars = data.get('vars', dict()) self.vars = data.get('vars', dict())

@ -589,8 +589,8 @@ class AnsibleModule(object):
return True return True
rc = selinux.lsetfilecon(self._to_filesystem_str(path), rc = selinux.lsetfilecon(self._to_filesystem_str(path),
str(':'.join(new_context))) str(':'.join(new_context)))
except OSError: except OSError, e:
self.fail_json(path=path, msg='invalid selinux context', new_context=new_context, cur_context=cur_context, input_was=context) self.fail_json(path=path, msg='invalid selinux context: %s' % str(e), new_context=new_context, cur_context=cur_context, input_was=context)
if rc != 0: if rc != 0:
self.fail_json(path=path, msg='set selinux context failed') self.fail_json(path=path, msg='set selinux context failed')
changed = True changed = True

@ -99,8 +99,9 @@ class Facts(object):
('/etc/os-release', 'SuSE'), ('/etc/os-release', 'SuSE'),
('/etc/gentoo-release', 'Gentoo'), ('/etc/gentoo-release', 'Gentoo'),
('/etc/os-release', 'Debian'), ('/etc/os-release', 'Debian'),
('/etc/lsb-release', 'Mandriva'),
('/etc/os-release', 'NA'), ('/etc/os-release', 'NA'),
('/etc/lsb-release', 'Mandriva')) )
SELINUX_MODE_DICT = { 1: 'enforcing', 0: 'permissive', -1: 'disabled' } SELINUX_MODE_DICT = { 1: 'enforcing', 0: 'permissive', -1: 'disabled' }
# A list of dicts. If there is a platform with more than one # A list of dicts. If there is a platform with more than one
@ -416,7 +417,9 @@ class Facts(object):
self.facts['distribution_version'] = self.facts['distribution_version'] + '.' + release.group(1) self.facts['distribution_version'] = self.facts['distribution_version'] + '.' + release.group(1)
elif name == 'Debian': elif name == 'Debian':
data = get_file_content(path) data = get_file_content(path)
if 'Debian' in data or 'Raspbian' in data: if 'Ubuntu' in data:
break # Ubuntu gets correct info from python functions
elif 'Debian' in data or 'Raspbian' in data:
release = re.search("PRETTY_NAME=[^(]+ \(?([^)]+?)\)", data) release = re.search("PRETTY_NAME=[^(]+ \(?([^)]+?)\)", data)
if release: if release:
self.facts['distribution_release'] = release.groups()[0] self.facts['distribution_release'] = release.groups()[0]
@ -2150,7 +2153,7 @@ class DarwinNetwork(GenericBsdIfconfigNetwork, Network):
current_if['media'] = 'Unknown' # Mac does not give us this current_if['media'] = 'Unknown' # Mac does not give us this
current_if['media_select'] = words[1] current_if['media_select'] = words[1]
if len(words) > 2: if len(words) > 2:
current_if['media_type'] = words[2][1:] current_if['media_type'] = words[2][1:-1]
if len(words) > 3: if len(words) > 3:
current_if['media_options'] = self.get_options(words[3]) current_if['media_options'] = self.get_options(words[3])

@ -93,11 +93,7 @@ def openstack_full_argument_spec(**kwargs):
def openstack_module_kwargs(**kwargs): def openstack_module_kwargs(**kwargs):
ret = dict( ret = {}
required_one_of=[
['cloud', 'auth'],
],
)
for key in ('mutually_exclusive', 'required_together', 'required_one_of'): for key in ('mutually_exclusive', 'required_together', 'required_one_of'):
if key in kwargs: if key in kwargs:
if key in ret: if key in ret:

@ -65,7 +65,7 @@ Function Exit-Json($obj)
$obj = New-Object psobject $obj = New-Object psobject
} }
echo $obj | ConvertTo-Json -Depth 99 echo $obj | ConvertTo-Json -Compress -Depth 99
Exit Exit
} }
@ -89,7 +89,7 @@ Function Fail-Json($obj, $message = $null)
Set-Attr $obj "msg" $message Set-Attr $obj "msg" $message
Set-Attr $obj "failed" $true Set-Attr $obj "failed" $true
echo $obj | ConvertTo-Json -Depth 99 echo $obj | ConvertTo-Json -Compress -Depth 99
Exit 1 Exit 1
} }

@ -1 +1 @@
Subproject commit 9cc23c749a8cd5039db7aa1998d310bbb04d1e13 Subproject commit 191a672891359f3b6faff83cb0613f1b38e3fc0e

@ -1 +1 @@
Subproject commit b2e4f31bebfec49380659b9d65b5828f1c1ed8d9 Subproject commit 1276420a3a39340fcd9e053a1e621cdd89f480fa

@ -0,0 +1,37 @@
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
#
# 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 <http://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import yaml
from ansible.parsing.yaml.objects import AnsibleUnicode
class AnsibleDumper(yaml.SafeDumper):
'''
A simple stub class that allows us to add representers
for our overridden object types.
'''
pass
AnsibleDumper.add_representer(
AnsibleUnicode,
yaml.representer.SafeRepresenter.represent_unicode
)

@ -0,0 +1,79 @@
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
#
# 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 <http://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class IncludedFile:
def __init__(self, filename, args, task):
self._filename = filename
self._args = args
self._task = task
self._hosts = []
def add_host(self, host):
if host not in self._hosts:
self._hosts.append(host)
def __eq__(self, other):
return other._filename == self._filename and other._args == self._args
def __repr__(self):
return "%s (%s): %s" % (self._filename, self._args, self._hosts)
@staticmethod
def process_include_results(results, tqm, iterator, loader):
included_files = []
for res in results:
if res._host in tqm._failed_hosts:
raise AnsibleError("host is failed, not including files")
if res._task.action == 'include':
if res._task.loop:
include_results = res._result['results']
else:
include_results = [ res._result ]
for include_result in include_results:
# if the task result was skipped or failed, continue
if 'skipped' in include_result and include_result['skipped'] or 'failed' in include_result:
continue
original_task = iterator.get_original_task(res._host, res._task)
if original_task and original_task._role:
include_file = loader.path_dwim_relative(original_task._role._role_path, 'tasks', include_result['include'])
else:
include_file = loader.path_dwim(res._task.args.get('_raw_params'))
include_variables = include_result.get('include_variables', dict())
if 'item' in include_result:
include_variables['item'] = include_result['item']
inc_file = IncludedFile(include_file, include_variables, original_task)
try:
pos = included_files.index(inc_file)
inc_file = included_files[pos]
except ValueError:
included_files.append(inc_file)
inc_file.add_host(res._host)
return included_files

@ -38,16 +38,21 @@ from jinja2.filters import environmentfilter
from distutils.version import LooseVersion, StrictVersion from distutils.version import LooseVersion, StrictVersion
from ansible import errors from ansible import errors
from ansible.parsing.yaml.dumper import AnsibleDumper
from ansible.utils.hashing import md5s, checksum_s from ansible.utils.hashing import md5s, checksum_s
from ansible.utils.unicode import unicode_wrap, to_unicode from ansible.utils.unicode import unicode_wrap, to_unicode
UUID_NAMESPACE_ANSIBLE = uuid.UUID('361E6D51-FAEC-444A-9079-341386DA8E2E') UUID_NAMESPACE_ANSIBLE = uuid.UUID('361E6D51-FAEC-444A-9079-341386DA8E2E')
def to_yaml(a, *args, **kw):
'''Make verbose, human readable yaml'''
transformed = yaml.dump(a, Dumper=AnsibleDumper, allow_unicode=True, **kw)
return to_unicode(transformed)
def to_nice_yaml(*a, **kw): def to_nice_yaml(a, *args, **kw):
'''Make verbose, human readable yaml''' '''Make verbose, human readable yaml'''
transformed = yaml.safe_dump(*a, indent=4, allow_unicode=True, default_flow_style=False, **kw) transformed = yaml.dump(a, Dumper=AnsibleDumper, indent=4, allow_unicode=True, default_flow_style=False, **kw)
return to_unicode(transformed) return to_unicode(transformed)
def to_json(a, *args, **kw): def to_json(a, *args, **kw):
@ -288,7 +293,7 @@ class FilterModule(object):
'from_json': json.loads, 'from_json': json.loads,
# yaml # yaml
'to_yaml': yaml.safe_dump, 'to_yaml': to_yaml,
'to_nice_yaml': to_nice_yaml, 'to_nice_yaml': to_nice_yaml,
'from_yaml': yaml.safe_load, 'from_yaml': yaml.safe_load,

@ -23,10 +23,9 @@ from six.moves import queue as Queue
import time import time
from ansible.errors import * from ansible.errors import *
from ansible.executor.task_result import TaskResult
from ansible.inventory.host import Host from ansible.inventory.host import Host
from ansible.inventory.group import Group from ansible.inventory.group import Group
from ansible.playbook.handler import Handler from ansible.playbook.handler import Handler
from ansible.playbook.helpers import load_list_of_blocks from ansible.playbook.helpers import load_list_of_blocks
from ansible.playbook.role import ROLE_CACHE, hash_params from ansible.playbook.role import ROLE_CACHE, hash_params
@ -74,29 +73,32 @@ class StrategyBase:
self._blocked_hosts = dict() self._blocked_hosts = dict()
def run(self, iterator, connection_info, result=True): def run(self, iterator, connection_info, result=True):
# save the counts on failed/unreachable hosts, as the cleanup/handler # save the failed/unreachable hosts, as the run_handlers()
# methods will clear that information during their runs # method will clear that information during its execution
num_failed = len(self._tqm._failed_hosts) failed_hosts = self._tqm._failed_hosts.keys()
num_unreachable = len(self._tqm._unreachable_hosts) unreachable_hosts = self._tqm._unreachable_hosts.keys()
debug("running handlers") debug("running handlers")
result &= self.run_handlers(iterator, connection_info) result &= self.run_handlers(iterator, connection_info)
# now update with the hosts (if any) that failed or were
# unreachable during the handler execution phase
failed_hosts = set(failed_hosts).union(self._tqm._failed_hosts.keys())
unreachable_hosts = set(unreachable_hosts).union(self._tqm._unreachable_hosts.keys())
# send the stats callback # send the stats callback
self._tqm.send_callback('v2_playbook_on_stats', self._tqm._stats) self._tqm.send_callback('v2_playbook_on_stats', self._tqm._stats)
if not result: if len(unreachable_hosts) > 0:
if num_unreachable > 0:
return 3 return 3
elif num_failed > 0: elif len(failed_hosts) > 0:
return 2 return 2
else: elif not result:
return 1 return 1
else: else:
return 0 return 0
def get_hosts_remaining(self, play): def get_hosts_remaining(self, play):
print("inventory get hosts: %s" % self._inventory.get_hosts(play.hosts))
return [host for host in self._inventory.get_hosts(play.hosts) if host.name not in self._tqm._failed_hosts and host.name not in self._tqm._unreachable_hosts] return [host for host in self._inventory.get_hosts(play.hosts) if host.name not in self._tqm._failed_hosts and host.name not in self._tqm._unreachable_hosts]
def get_failed_hosts(self, play): def get_failed_hosts(self, play):
@ -147,7 +149,7 @@ class StrategyBase:
task_result = result[1] task_result = result[1]
host = task_result._host host = task_result._host
task = task_result._task task = task_result._task
if result[0] == 'host_task_failed': if result[0] == 'host_task_failed' or 'failed' in task_result._result:
if not task.ignore_errors: if not task.ignore_errors:
debug("marking %s as failed" % host.name) debug("marking %s as failed" % host.name)
iterator.mark_host_failed(host) iterator.mark_host_failed(host)
@ -308,12 +310,22 @@ class StrategyBase:
# and add the host to the group # and add the host to the group
new_group.add_host(actual_host) new_group.add_host(actual_host)
def _load_included_file(self, included_file): def _load_included_file(self, included_file, iterator):
''' '''
Loads an included YAML file of tasks, applying the optional set of variables. Loads an included YAML file of tasks, applying the optional set of variables.
''' '''
try:
data = self._loader.load_from_file(included_file._filename) data = self._loader.load_from_file(included_file._filename)
except AnsibleError, e:
for host in included_file._hosts:
tr = TaskResult(host=host, task=included_file._task, return_data=dict(failed=True, reason=str(e)))
iterator.mark_host_failed(host)
self._tqm._failed_hosts[host.name] = True
self._tqm._stats.increment('failures', host.name)
self._tqm.send_callback('v2_runner_on_failed', tr)
return []
if not isinstance(data, list): if not isinstance(data, list):
raise AnsibleParserError("included task files must contain a list of tasks", obj=included_file._task._ds) raise AnsibleParserError("included task files must contain a list of tasks", obj=included_file._task._ds)

@ -22,6 +22,7 @@ __metaclass__ = type
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.executor.play_iterator import PlayIterator from ansible.executor.play_iterator import PlayIterator
from ansible.playbook.block import Block from ansible.playbook.block import Block
from ansible.playbook.included_file import IncludedFile
from ansible.playbook.task import Task from ansible.playbook.task import Task
from ansible.plugins import action_loader from ansible.plugins import action_loader
from ansible.plugins.strategies import StrategyBase from ansible.plugins.strategies import StrategyBase
@ -114,7 +115,6 @@ class StrategyModule(StrategyBase):
# return None for all hosts in the list # return None for all hosts in the list
return [(host, None) for host in hosts] return [(host, None) for host in hosts]
def run(self, iterator, connection_info): def run(self, iterator, connection_info):
''' '''
The linear strategy is simple - get the next task and queue The linear strategy is simple - get the next task and queue
@ -208,61 +208,11 @@ class StrategyModule(StrategyBase):
results = self._wait_on_pending_results(iterator) results = self._wait_on_pending_results(iterator)
host_results.extend(results) host_results.extend(results)
# FIXME: this needs to be somewhere else
class IncludedFile:
def __init__(self, filename, args, task):
self._filename = filename
self._args = args
self._task = task
self._hosts = []
def add_host(self, host):
if host not in self._hosts:
self._hosts.append(host)
def __eq__(self, other):
return other._filename == self._filename and other._args == self._args
def __repr__(self):
return "%s (%s): %s" % (self._filename, self._args, self._hosts)
# FIXME: this should also be moved to the base class in a method
included_files = []
for res in host_results:
if res._host in self._tqm._failed_hosts:
return 1
if res._task.action == 'include':
if res._task.loop:
include_results = res._result['results']
else:
include_results = [ res._result ]
for include_result in include_results:
# if the task result was skipped or failed, continue
if 'skipped' in include_result and include_result['skipped'] or 'failed' in include_result:
continue
original_task = iterator.get_original_task(res._host, res._task)
if original_task and original_task._role:
include_file = self._loader.path_dwim_relative(original_task._role._role_path, 'tasks', include_result['include'])
else:
include_file = self._loader.path_dwim(res._task.args.get('_raw_params'))
include_variables = include_result.get('include_variables', dict())
if 'item' in include_result:
include_variables['item'] = include_result['item']
inc_file = IncludedFile(include_file, include_variables, original_task)
try: try:
pos = included_files.index(inc_file) included_files = IncludedFile.process_include_results(host_results, self._tqm, iterator=iterator, loader=self._loader)
inc_file = included_files[pos] except AnsibleError, e:
except ValueError: return False
included_files.append(inc_file)
inc_file.add_host(res._host)
# FIXME: should this be moved into the iterator class? Main downside would be
# that accessing the TQM's callback member would be more difficult, if
# we do want to send callbacks from here
if len(included_files) > 0: if len(included_files) > 0:
noop_task = Task() noop_task = Task()
noop_task.action = 'meta' noop_task.action = 'meta'
@ -274,7 +224,7 @@ class StrategyModule(StrategyBase):
# included hosts get the task list while those excluded get an equal-length # included hosts get the task list while those excluded get an equal-length
# list of noop tasks, to make sure that they continue running in lock-step # list of noop tasks, to make sure that they continue running in lock-step
try: try:
new_blocks = self._load_included_file(included_file) new_blocks = self._load_included_file(included_file, iterator=iterator)
except AnsibleError, e: except AnsibleError, e:
for host in included_file._hosts: for host in included_file._hosts:
iterator.mark_host_failed(host) iterator.mark_host_failed(host)
@ -302,7 +252,7 @@ class StrategyModule(StrategyBase):
except (IOError, EOFError), e: except (IOError, EOFError), e:
debug("got IOError/EOFError in task loop: %s" % e) debug("got IOError/EOFError in task loop: %s" % e)
# most likely an abort, return failed # most likely an abort, return failed
return 1 return False
# run the base class run() method, which executes the cleanup function # run the base class run() method, which executes the cleanup function
# and runs any outstanding handlers which have been triggered # and runs any outstanding handlers which have been triggered

@ -238,14 +238,6 @@ class Templar:
environment.filters.update(self._get_filters()) environment.filters.update(self._get_filters())
environment.template_class = AnsibleJ2Template environment.template_class = AnsibleJ2Template
# FIXME: may not be required anymore, as the basedir stuff will
# be handled by the loader?
#if '_original_file' in vars:
# basedir = os.path.dirname(vars['_original_file'])
# filesdir = os.path.abspath(os.path.join(basedir, '..', 'files'))
# if os.path.exists(filesdir):
# basedir = filesdir
try: try:
t = environment.from_string(data) t = environment.from_string(data)
except TemplateSyntaxError, e: except TemplateSyntaxError, e:

@ -20,6 +20,9 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import textwrap import textwrap
import os
import random
import subprocess
import sys import sys
from ansible import constants as C from ansible import constants as C
@ -37,6 +40,31 @@ class Display:
self._warns = {} self._warns = {}
self._errors = {} self._errors = {}
self.cowsay = None
self.noncow = os.getenv("ANSIBLE_COW_SELECTION",None)
self.set_cowsay_info()
def set_cowsay_info(self):
if not C.ANSIBLE_NOCOWS:
if os.path.exists("/usr/bin/cowsay"):
self.cowsay = "/usr/bin/cowsay"
elif os.path.exists("/usr/games/cowsay"):
self.cowsay = "/usr/games/cowsay"
elif os.path.exists("/usr/local/bin/cowsay"):
# BSD path for cowsay
self.cowsay = "/usr/local/bin/cowsay"
elif os.path.exists("/opt/local/bin/cowsay"):
# MacPorts path for cowsay
self.cowsay = "/opt/local/bin/cowsay"
if self.cowsay and self.noncow == 'random':
cmd = subprocess.Popen([self.cowsay, "-l"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = cmd.communicate()
cows = out.split()
cows.append(False)
self.noncow = random.choice(cows)
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False):
msg2 = msg msg2 = msg
if color: if color:
@ -125,6 +153,14 @@ class Display:
Prints a header-looking line with stars taking up to 80 columns Prints a header-looking line with stars taking up to 80 columns
of width (3 columns, minimum) of width (3 columns, minimum)
''' '''
if self.cowsay:
try:
self.banner_cowsay(msg)
return
except OSError:
# somebody cleverly deleted cowsay or something during the PB run. heh.
pass
msg = msg.strip() msg = msg.strip()
star_len = (80 - len(msg)) star_len = (80 - len(msg))
if star_len < 0: if star_len < 0:
@ -132,6 +168,20 @@ class Display:
stars = "*" * star_len stars = "*" * star_len
self.display("\n%s %s" % (msg, stars), color=color) self.display("\n%s %s" % (msg, stars), color=color)
def banner_cowsay(self, msg, color=None):
if ": [" in msg:
msg = msg.replace("[","")
if msg.endswith("]"):
msg = msg[:-1]
runcmd = [self.cowsay,"-W", "60"]
if self.noncow:
runcmd.append('-f')
runcmd.append(self.noncow)
runcmd.append(msg)
cmd = subprocess.Popen(runcmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = cmd.communicate()
self.display("%s\n" % out, color=color)
def error(self, msg): def error(self, msg):
new_msg = "\n[ERROR]: %s" % msg new_msg = "\n[ERROR]: %s" % msg
wrapped = textwrap.wrap(new_msg, 79) wrapped = textwrap.wrap(new_msg, 79)

@ -23,7 +23,9 @@ class ModuleDocFragment(object):
options: options:
cloud: cloud:
description: description:
- Named cloud to operate against. Provides default values for I(auth) and I(auth_plugin) - Named cloud to operate against. Provides default values for I(auth) and
I(auth_type). This parameter is not needed if I(auth) is provided or if
OpenStack OS_* environment variables are present.
required: false required: false
auth: auth:
description: description:
@ -32,7 +34,8 @@ options:
I(auth_url), I(username), I(password), I(project_name) and any I(auth_url), I(username), I(password), I(project_name) and any
information about domains if the cloud supports them. For other plugins, information about domains if the cloud supports them. For other plugins,
this param will need to contain whatever parameters that auth plugin this param will need to contain whatever parameters that auth plugin
requires. This parameter is not needed if a named cloud is provided. requires. This parameter is not needed if a named cloud is provided or
OpenStack OS_* environment variables are present.
required: false required: false
auth_type: auth_type:
description: description:
@ -77,14 +80,17 @@ options:
- A path to a CA Cert bundle that can be used as part of verifying - A path to a CA Cert bundle that can be used as part of verifying
SSL API requests. SSL API requests.
required: false required: false
default: None
cert: cert:
description: description:
- A path to a client certificate to use as part of the SSL transaction - A path to a client certificate to use as part of the SSL transaction
required: false required: false
default: None
key: key:
description: description:
- A path to a client key to use as part of the SSL transaction - A path to a client key to use as part of the SSL transaction
required: false required: false
default: None
endpoint_type: endpoint_type:
description: description:
- Endpoint URL type to fetch from the service catalog. - Endpoint URL type to fetch from the service catalog.
@ -100,5 +106,6 @@ notes:
can come from a yaml config file in /etc/ansible/openstack.yaml, can come from a yaml config file in /etc/ansible/openstack.yaml,
/etc/openstack/clouds.yaml or ~/.config/openstack/clouds.yaml, then from /etc/openstack/clouds.yaml or ~/.config/openstack/clouds.yaml, then from
standard environment variables, then finally by explicit parameters in standard environment variables, then finally by explicit parameters in
plays. plays. More information can be found at
U(http://docs.openstack.org/developer/os-client-config)
''' '''

@ -24,12 +24,13 @@ CONSUL_RUNNING := $(shell python consul_running.py)
all: parsing test_var_precedence unicode test_templating_settings non_destructive destructive includes check_mode test_hash test_handlers test_group_by test_vault test_tags all: parsing test_var_precedence unicode test_templating_settings non_destructive destructive includes check_mode test_hash test_handlers test_group_by test_vault test_tags
parsing: parsing:
ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario1; [ $$? -eq 4 ] #ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario1; [ $$? -eq 4 ]
ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario2; [ $$? -eq 4 ] #ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario2; [ $$? -eq 4 ]
ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario3; [ $$? -eq 4 ] #ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario3; [ $$? -eq 4 ]
ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario4; [ $$? -eq 4 ] #ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario4; [ $$? -eq 4 ]
ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario5; [ $$? -eq 4 ] #ansible-playbook bad_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -vvv $(TEST_FLAGS) --tags prepare,common,scenario5; [ $$? -eq 4 ]
ansible-playbook good_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -v $(TEST_FLAGS) #ansible-playbook good_parsing.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -v $(TEST_FLAGS)
echo "skipping for now..."
includes: includes:
ansible-playbook test_includes.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) $(TEST_FLAGS) ansible-playbook test_includes.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) $(TEST_FLAGS)

@ -225,7 +225,7 @@
- "result.msg == 'line added'" - "result.msg == 'line added'"
- name: insert a multiple lines at the end of the file - name: insert a multiple lines at the end of the file
lineinfile: dest={{output_dir}}/test.txt state=present line="This is a line\nwith \\\n character" insertafter="EOF" lineinfile: dest={{output_dir}}/test.txt state=present line="This is a line\nwith \\n character" insertafter="EOF"
register: result register: result
- name: assert that the multiple lines was inserted - name: assert that the multiple lines was inserted

@ -0,0 +1,5 @@
- hosts: testhost
connection: local
gather_facts: yes
roles:
- { role: test_filters }

@ -722,7 +722,7 @@ class TestModuleUtilsBasic(unittest.TestCase):
# FIXME: this isn't working yet # FIXME: this isn't working yet
#with patch('os.lstat', side_effect=[mock_stat1, mock_stat2]): #with patch('os.lstat', side_effect=[mock_stat1, mock_stat2]):
# with patch('os.lchmod', return_value=None, create=True) as m_os: # with patch('os.lchmod', return_value=None) as m_os:
# del m_os.lchmod # del m_os.lchmod
# with patch('os.path.islink', return_value=False): # with patch('os.path.islink', return_value=False):
# with patch('os.chmod', return_value=None) as m_chmod: # with patch('os.chmod', return_value=None) as m_chmod:

@ -299,14 +299,17 @@ class TestStrategyBase(unittest.TestCase):
mock_task._block = mock_block mock_task._block = mock_block
mock_task._role = None mock_task._role = None
mock_iterator = MagicMock()
mock_iterator.mark_host_failed.return_value = None
mock_inc_file = MagicMock() mock_inc_file = MagicMock()
mock_inc_file._task = mock_task mock_inc_file._task = mock_task
mock_inc_file._filename = "test.yml" mock_inc_file._filename = "test.yml"
res = strategy_base._load_included_file(included_file=mock_inc_file) res = strategy_base._load_included_file(included_file=mock_inc_file, iterator=mock_iterator)
mock_inc_file._filename = "bad.yml" mock_inc_file._filename = "bad.yml"
self.assertRaises(AnsibleParserError, strategy_base._load_included_file, included_file=mock_inc_file) self.assertRaises(AnsibleParserError, strategy_base._load_included_file, included_file=mock_inc_file, iterator=mock_iterator)
def test_strategy_base_run_handlers(self): def test_strategy_base_run_handlers(self):
workers = [] workers = []

@ -93,11 +93,7 @@ def openstack_full_argument_spec(**kwargs):
def openstack_module_kwargs(**kwargs): def openstack_module_kwargs(**kwargs):
ret = dict( ret = {}
required_one_of=[
['cloud', 'auth'],
],
)
for key in ('mutually_exclusive', 'required_together', 'required_one_of'): for key in ('mutually_exclusive', 'required_together', 'required_one_of'):
if key in kwargs: if key in kwargs:
if key in ret: if key in ret:

Loading…
Cancel
Save