Commit 4455fea5 by Philippe Makowski

Merge remote-tracking branch 'upstream/devel' into devel

parents a4ff6174 6dd81f25
...@@ -102,6 +102,9 @@ filter_plugins = /usr/share/ansible_plugins/filter_plugins ...@@ -102,6 +102,9 @@ filter_plugins = /usr/share/ansible_plugins/filter_plugins
# set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1 # set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1
#nocolor = 1 #nocolor = 1
# default URL for `etcd' lookup plugin
etcd_url = 'http://127.0.0.1:4001'
[paramiko_connection] [paramiko_connection]
# uncomment this line to cause the paramiko connection plugin to not record new host # uncomment this line to cause the paramiko connection plugin to not record new host
......
...@@ -152,6 +152,9 @@ PARAMIKO_PTY = get_config(p, 'paramiko_connection', 'pty', 'AN ...@@ -152,6 +152,9 @@ PARAMIKO_PTY = get_config(p, 'paramiko_connection', 'pty', 'AN
# characters included in auto-generated passwords # characters included in auto-generated passwords
DEFAULT_PASSWORD_CHARS = ascii_letters + digits + ".,:-_" DEFAULT_PASSWORD_CHARS = ascii_letters + digits + ".,:-_"
# LOOKUP PLUGIN RELATED
ANSIBLE_ETCD_URL = get_config(p, DEFAULTS, 'etcd_url', 'ANSIBLE_ETCD_URL', 'http://127.0.0.1:4001')
# non-configurable things # non-configurable things
DEFAULT_SUDO_PASS = None DEFAULT_SUDO_PASS = None
DEFAULT_REMOTE_PASS = None DEFAULT_REMOTE_PASS = None
......
...@@ -544,12 +544,23 @@ class PlayBook(object): ...@@ -544,12 +544,23 @@ class PlayBook(object):
for handler in play.handlers(): for handler in play.handlers():
if len(handler.notified_by) > 0: if len(handler.notified_by) > 0:
self.inventory.restrict_to(handler.notified_by) self.inventory.restrict_to(handler.notified_by)
# Resolve the variables first # Resolve the variables first
handler_name = template(play.basedir, handler.name, handler.module_vars) handler_name = template(play.basedir, handler.name, handler.module_vars)
if handler_name not in fired_names: if handler_name not in fired_names:
self._run_task(play, handler, True) self._run_task(play, handler, True)
# prevent duplicate handler includes from running more than once # prevent duplicate handler includes from running more than once
fired_names[handler_name] = 1 fired_names[handler_name] = 1
host_list = self._list_available_hosts(play.hosts)
if handler.any_errors_fatal and len(host_list) < hosts_count:
play.max_fail_pct = 0
if (hosts_count - len(host_list)) > int((play.max_fail_pct)/100.0 * hosts_count):
host_list = None
if not host_list:
self.callbacks.on_no_hosts_remaining()
return False
self.inventory.lift_restriction() self.inventory.lift_restriction()
new_list = handler.notified_by[:] new_list = handler.notified_by[:]
for host in handler.notified_by: for host in handler.notified_by:
......
# (c) 2013, Michael DeHaan <michael.dehaan@gmail.com>
# Stephen Fromm <sfromm@gmail.com>
# Brian Coca <briancoca+dev@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
import os
import os.path
import pipes
import shutil
import tempfile
from ansible import utils
class ActionModule(object):
def __init__(self, runner):
self.runner = runner
def _assemble_from_fragments(src_path, delimiter=None):
''' assemble a file from a directory of fragments '''
tmpfd, temp_path = tempfile.mkstemp()
tmp = os.fdopen(tmpfd,'w')
delimit_me = False
for f in sorted(os.listdir(src_path)):
fragment = "%s/%s" % (src_path, f)
if delimit_me and delimiter:
tmp.write(delimiter)
if os.path.isfile(fragment):
tmp.write(file(fragment).read())
delimit_me = True
tmp.close()
return temp_path
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
# load up options
options = {}
if complex_args:
options.update(complex_args)
options.update(utils.parse_kv(module_args))
src = options.get('src', None)
dest = options.get('dest', None)
delimiter = options.get('delimiter', None)
remote_src = options.get('remote_src', True)
if src is None or dest is None:
result = dict(failed=True, msg="src and dest are required")
return ReturnData(conn=conn, comm_ok=False, result=result)
if remote_src:
return self.runner._execute_module(conn, tmp, 'assemble', module_args, inject=inject, complex_args=complex_args)
# Does all work assembling the file
path = assemble_from_fragments(src, delimiter)
pathmd5 = utils.md5s(path)
remote_md5 = self.runner._remote_md5(conn, tmp, dest)
if pathmd5 != remote_md5:
if self.runner.diff:
dest_result = self.runner._execute_module(conn, tmp, 'slurp', "path=%s" % dest, inject=inject, persist_files=True)
if 'content' in dest_result.result:
dest_contents = dest_result.result['content']
if dest_result.result['encoding'] == 'base64':
dest_contents = base64.b64decode(dest_contents)
else:
raise Exception("unknown encoding, failed: %s" % dest_result.result)
xfered = self.runner._transfer_str(conn, tmp, 'src', resultant)
# fix file permissions when the copy is done as a different user
if self.runner.sudo and self.runner.sudo_user != 'root':
self.runner._low_level_exec_command(conn, "chmod a+r %s" % xfered, tmp)
# run the copy module
module_args = "%s src=%s dest=%s original_basename=%s" % (module_args, pipes.quote(xfered), pipes.quote(dest), pipes.quote(os.path.basename(src)))
if self.runner.noop_on_check(inject):
return ReturnData(conn=conn, comm_ok=True, result=dict(changed=True), diff=dict(before_header=dest, after_header=src, before=dest_contents, after=resultant))
else:
res = self.runner._execute_module(conn, tmp, 'copy', module_args, inject=inject, complex_args=complex_args)
res.diff = dict(before=dest_contents, after=resultant)
return res
else:
return self.runner._execute_module(conn, tmp, 'file', module_args, inject=inject, complex_args=complex_args)
...@@ -98,8 +98,8 @@ class ActionModule(object): ...@@ -98,8 +98,8 @@ class ActionModule(object):
if rsync_path: if rsync_path:
options['rsync_path'] = '"' + rsync_path + '"' options['rsync_path'] = '"' + rsync_path + '"'
self.runner.module_args = ' '.join(['%s=%s' % (k, v) for (k, module_items = ' '.join(['%s=%s' % (k, v) for (k,
v) in options.items()]) v) in options.items()])
return self.runner._execute_module(conn, tmp, 'synchronize', return self.runner._execute_module(conn, tmp, 'synchronize',
self.runner.module_args, inject=inject) module_items, inject=inject)
# (c) 2013, Jan-Piet Mens <jpmens(at)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/>.
from ansible import utils, errors, constants
import os
import urllib2
try:
import json
except ImportError:
import simplejson as json
class etcd():
def __init__(self, url='http://127.0.0.1:4001'):
self.url = url
self.baseurl = '%s/v1/keys' % (self.url)
def get(self, key):
url = "%s/%s" % (self.baseurl, key)
data = None
value = ""
try:
r = urllib2.urlopen(url)
data = r.read()
except:
return value
try:
# {"action":"get","key":"/name","value":"Jane Jolie","index":5}
item = json.loads(data)
if 'value' in item:
value = item['value']
if 'errorCode' in item:
value = "ENOENT"
except:
raise
pass
return value
class LookupModule(object):
def __init__(self, basedir=None, **kwargs):
self.basedir = basedir
self.etcd = etcd(constants.ANSIBLE_ETCD_URL)
def run(self, terms, inject=None, **kwargs):
terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject)
if isinstance(terms, basestring):
terms = [ terms ]
ret = []
for term in terms:
key = term.split()[0]
value = self.etcd.get(key)
ret.append(value)
return ret
...@@ -60,6 +60,14 @@ options: ...@@ -60,6 +60,14 @@ options:
required: true required: true
default: null default: null
aliases: [] aliases: []
tags:
description:
- Dictionary of tags to associate with stack and it's resources during stack creation. Cannot be updated later.
Requires at least Boto version 2.6.0.
required: false
default: null
aliases: []
version_added: "1.4"
requirements: [ "boto" ] requirements: [ "boto" ]
author: James S. Martin author: James S. Martin
...@@ -79,12 +87,15 @@ tasks: ...@@ -79,12 +87,15 @@ tasks:
DiskType: ephemeral DiskType: ephemeral
InstanceType: m1.small InstanceType: m1.small
ClusterSize: 3 ClusterSize: 3
tags:
Stack: ansible-cloudformation
''' '''
import json import json
import time import time
try: try:
import boto
import boto.cloudformation.connection import boto.cloudformation.connection
except ImportError: except ImportError:
print "failed=True msg='boto required for this module'" print "failed=True msg='boto required for this module'"
...@@ -118,6 +129,17 @@ def boto_exception(err): ...@@ -118,6 +129,17 @@ def boto_exception(err):
return error return error
def boto_version_required(version_tuple):
parts = boto.Version.split('.')
boto_version = []
try:
for part in parts:
boto_version.append(int(part))
except:
boto_version.append(-1)
return tuple(boto_version) >= tuple(version_tuple)
def stack_operation(cfn, stack_name, operation): def stack_operation(cfn, stack_name, operation):
'''gets the status of a stack while it is created/updated/deleted''' '''gets the status of a stack while it is created/updated/deleted'''
existed = [] existed = []
...@@ -163,7 +185,8 @@ def main(): ...@@ -163,7 +185,8 @@ def main():
region=dict(aliases=['aws_region', 'ec2_region'], required=True, choices=AWS_REGIONS), region=dict(aliases=['aws_region', 'ec2_region'], required=True, choices=AWS_REGIONS),
state=dict(default='present', choices=['present', 'absent']), state=dict(default='present', choices=['present', 'absent']),
template=dict(default=None, required=True), template=dict(default=None, required=True),
disable_rollback=dict(default=False) disable_rollback=dict(default=False),
tags=dict(default=None)
) )
) )
...@@ -173,14 +196,20 @@ def main(): ...@@ -173,14 +196,20 @@ def main():
template_body = open(module.params['template'], 'r').read() template_body = open(module.params['template'], 'r').read()
disable_rollback = module.params['disable_rollback'] disable_rollback = module.params['disable_rollback']
template_parameters = module.params['template_parameters'] template_parameters = module.params['template_parameters']
tags = module.params['tags']
if not r: if not r:
if 'AWS_REGION' in os.environ: if 'AWS_REGION' in os.environ:
r = os.environ['AWS_REGION'] r = os.environ['AWS_REGION']
elif 'EC2_REGION' in os.environ: elif 'EC2_REGION' in os.environ:
r = os.environ['EC2_REGION'] r = os.environ['EC2_REGION']
kwargs = dict()
if tags is not None:
if not boto_version_required((2,6,0)):
module.fail_json(msg='Module parameter "tags" requires at least Boto version 2.6.0')
kwargs['tags'] = tags
# convert the template parameters ansible passes into a tuple for boto # convert the template parameters ansible passes into a tuple for boto
template_parameters_tup = [(k, v) for k, v in template_parameters.items()] template_parameters_tup = [(k, v) for k, v in template_parameters.items()]
...@@ -203,7 +232,8 @@ def main(): ...@@ -203,7 +232,8 @@ def main():
cfn.create_stack(stack_name, parameters=template_parameters_tup, cfn.create_stack(stack_name, parameters=template_parameters_tup,
template_body=template_body, template_body=template_body,
disable_rollback=disable_rollback, disable_rollback=disable_rollback,
capabilities=['CAPABILITY_IAM']) capabilities=['CAPABILITY_IAM'],
**kwargs)
operation = 'CREATE' operation = 'CREATE'
except Exception, err: except Exception, err:
error_msg = boto_exception(err) error_msg = boto_exception(err)
......
...@@ -165,8 +165,8 @@ def main(): ...@@ -165,8 +165,8 @@ def main():
record_in = module.params.get('record') record_in = module.params.get('record')
type_in = module.params.get('type') type_in = module.params.get('type')
value_in = module.params.get('value') value_in = module.params.get('value')
aws_secret_key = module.params.get('aws_secret_key')
aws_access_key = module.params.get('aws_access_key') ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
value_list = () value_list = ()
...@@ -186,19 +186,6 @@ def main(): ...@@ -186,19 +186,6 @@ def main():
if not value_in: if not value_in:
module.fail_json(msg = "parameter 'value' required for create/delete") module.fail_json(msg = "parameter 'value' required for create/delete")
# allow environment variables to be used if ansible vars aren't set
if not aws_secret_key:
if 'AWS_SECRET_KEY' in os.environ:
aws_secret_key = os.environ['AWS_SECRET_KEY']
elif 'EC2_SECRET_KEY' in os.environ:
aws_secret_key = os.environ['EC2_SECRET_KEY']
if not aws_access_key:
if 'AWS_ACCESS_KEY' in os.environ:
aws_access_key = os.environ['AWS_ACCESS_KEY']
elif 'EC2_ACCESS_KEY' in os.environ:
aws_access_key = os.environ['EC2_ACCESS_KEY']
# connect to the route53 endpoint # connect to the route53 endpoint
try: try:
conn = boto.route53.connection.Route53Connection(aws_access_key, aws_secret_key) conn = boto.route53.connection.Route53Connection(aws_access_key, aws_secret_key)
...@@ -263,7 +250,8 @@ def main(): ...@@ -263,7 +250,8 @@ def main():
module.exit_json(changed=True) module.exit_json(changed=True)
# this is magic, see lib/ansible/module_common.py # import module snippets
#<<INCLUDE_ANSIBLE_MODULE_COMMON>> from ansible.module_utils.basic import *
from ansible.module_utils.ec2 import *
main() main()
...@@ -272,9 +272,9 @@ def main(): ...@@ -272,9 +272,9 @@ def main():
mode = module.params.get('mode') mode = module.params.get('mode')
expiry = int(module.params['expiry']) expiry = int(module.params['expiry'])
s3_url = module.params.get('s3_url') s3_url = module.params.get('s3_url')
aws_secret_key = module.params.get('aws_secret_key')
aws_access_key = module.params.get('aws_access_key')
overwrite = module.params.get('overwrite') overwrite = module.params.get('overwrite')
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
if module.params.get('object'): if module.params.get('object'):
obj = os.path.expanduser(module.params['object']) obj = os.path.expanduser(module.params['object'])
...@@ -283,18 +283,6 @@ def main(): ...@@ -283,18 +283,6 @@ def main():
if not s3_url and 'S3_URL' in os.environ: if not s3_url and 'S3_URL' in os.environ:
s3_url = os.environ['S3_URL'] s3_url = os.environ['S3_URL']
if not aws_secret_key:
if 'AWS_SECRET_KEY' in os.environ:
aws_secret_key = os.environ['AWS_SECRET_KEY']
elif 'EC2_SECRET_KEY' in os.environ:
aws_secret_key = os.environ['EC2_SECRET_KEY']
if not aws_access_key:
if 'AWS_ACCESS_KEY' in os.environ:
aws_access_key = os.environ['AWS_ACCESS_KEY']
elif 'EC2_ACCESS_KEY' in os.environ:
aws_access_key = os.environ['EC2_ACCESS_KEY']
# If we have an S3_URL env var set, this is likely to be Walrus, so change connection method # If we have an S3_URL env var set, this is likely to be Walrus, so change connection method
if is_walrus(s3_url): if is_walrus(s3_url):
try: try:
...@@ -463,8 +451,8 @@ def main(): ...@@ -463,8 +451,8 @@ def main():
module.exit_json(failed=False) module.exit_json(failed=False)
# import module snippets
# this is magic, see lib/ansible/module_common.py from ansible.module_utils.basic import *
#<<INCLUDE_ANSIBLE_MODULE_COMMON>> from ansible.module_utils.ec2 import *
main() main()
...@@ -31,9 +31,9 @@ description: ...@@ -31,9 +31,9 @@ description:
- Assembles a configuration file from fragments. Often a particular - Assembles a configuration file from fragments. Often a particular
program will take a single configuration file and does not support a program will take a single configuration file and does not support a
C(conf.d) style structure where it is easy to build up the configuration C(conf.d) style structure where it is easy to build up the configuration
from multiple sources. M(assemble) will take a directory of files that have from multiple sources. M(assemble) will take a directory of files that can be
already been transferred to the system, and concatenate them together to local or have already been transferred to the system, and concatenate them
produce a destination file. Files are assembled in string sorting order. together to produce a destination file. Files are assembled in string sorting order.
Puppet calls this idea I(fragments). Puppet calls this idea I(fragments).
version_added: "0.5" version_added: "0.5"
options: options:
...@@ -62,6 +62,14 @@ options: ...@@ -62,6 +62,14 @@ options:
version_added: "1.4" version_added: "1.4"
required: false required: false
default: null default: null
remote_src:
description:
- If False, it will search for src at originating/master machine, if True it will
go to the remote/target machine for the src. Default is True.
choices: [ "True", "False" ]
required: false
default: "True"
version_added: "1.4"
others: others:
description: description:
- all arguments accepted by the M(file) module also work here - all arguments accepted by the M(file) module also work here
...@@ -107,6 +115,7 @@ def main(): ...@@ -107,6 +115,7 @@ def main():
delimiter = dict(required=False), delimiter = dict(required=False),
dest = dict(required=True), dest = dict(required=True),
backup=dict(default=False, type='bool'), backup=dict(default=False, type='bool'),
remote_src=dict(default=False, type='bool'),
), ),
add_file_common_args=True add_file_common_args=True
) )
......
...@@ -186,12 +186,8 @@ def main(): ...@@ -186,12 +186,8 @@ def main():
prev_state = 'file' prev_state = 'file'
if prev_state is not None and state is None: if prev_state is not None and state is None:
if not params.get('src', None): # set state to current type of file
# idempotent exit if state is not specified state = prev_state
module.exit_json(path=path, changed=False)
else:
# src is defined, need to process other operations
state = prev_state
elif state is None: elif state is None:
# set default state to file # set default state to file
state = 'file' state = 'file'
......
#!/usr/bin/env python2
#coding: utf-8 -*-
# This module 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.
#
# This software 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 this software. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
module: openvswitch_bridge
short_description: Manage Open vSwitch bridges
requirements: [ ovs-vsctl ]
description:
- Manage Open vSwitch bridges
options:
bridge:
required: true
description:
- Name of bridge to manage
state:
required: false
default: "present"
choices: [ present, absent ]
description:
- Whether the bridge should exist
timeout:
required: false
default: 5
description:
- How long to wait for ovs-vswitchd to respond
'''
EXAMPLES = '''
# Create a bridge named br-int
- openvswitch_bridge: bridge=br-int state=present
'''
class OVSBridge(object):
def __init__(self, module):
self.module = module
self.bridge = module.params['bridge']
self.state = module.params['state']
self.timeout = module.params['timeout']
def _vsctl(self, command):
'''Run ovs-vsctl command'''
return self.module.run_command(['ovs-vsctl', '-t', str(self.timeout)] + command)
def exists(self):
'''Check if the bridge already exists'''
rc, _, err = self._vsctl(['br-exists', self.bridge])
if rc == 0: # See ovs-vsctl(8) for status codes
return True
if rc == 2:
return False
raise Exception(err)
def add(self):
'''Create the bridge'''
rc, _, err = self._vsctl(['add-br', self.bridge])
if rc != 0:
raise Exception(err)
def delete(self):
'''Delete the bridge'''
rc, _, err = self._vsctl(['del-br', self.bridge])
if rc != 0:
raise Exception(err)
def check(self):
'''Run check mode'''
try:
if self.state == 'absent' and self.exists():
changed = True
elif self.state == 'present' and not self.exists():
changed = True
else:
changed = False
except Exception, e:
self.module.fail_json(msg=str(e))
self.module.exit_json(changed=changed)
def run(self):
'''Make the necessary changes'''
changed = False
try:
if self.state == 'absent':
if self.exists():
self.delete()
changed = True
elif self.state == 'present':
if not self.exists():
self.add()
changed = True
except Exception, e:
self.module.fail_json(msg=str(e))
self.module.exit_json(changed=changed)
def main():
module = AnsibleModule(
argument_spec={
'bridge': {'required': True},
'state': {'default': 'present', 'choices': ['present', 'absent']},
'timeout': {'default': 5, 'type': 'int'}
},
supports_check_mode=True,
)
br = OVSBridge(module)
if module.check_mode:
br.check()
else:
br.run()
# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()
#!/usr/bin/env python2
#coding: utf-8 -*-
# This module 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.
#
# This software 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 this software. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
module: openvswitch_port
short_description: Manage Open vSwitch ports
requirements: [ ovs-vsctl ]
description:
- Manage Open vSwitch ports
options:
bridge:
required: true
description:
- Name of bridge to manage
port:
required: true
description:
- Name of port to manage on the bridge
state:
required: false
default: "present"
choices: [ present, absent ]
description:
- Whether the port should exist
timeout:
required: false
default: 5
description:
- How long to wait for ovs-vswitchd to respond
'''
EXAMPLES = '''
# Creates port eth2 on bridge br-ex
- openvswitch_port: bridge=br-ex port=eth2 state=present
'''
class OVSPort(object):
def __init__(self, module):
self.module = module
self.bridge = module.params['bridge']
self.port = module.params['port']
self.state = module.params['state']
self.timeout = module.params['timeout']
def _vsctl(self, command):
'''Run ovs-vsctl command'''
return self.module.run_command(['ovs-vsctl', '-t', str(self.timeout)] + command)
def exists(self):
'''Check if the port already exists'''
rc, out, err = self._vsctl(['list-ports', self.bridge])
if rc != 0:
raise Exception(err)
return any(port.rstrip() == self.port for port in out.split('\n'))
def add(self):
'''Add the port'''
rc, _, err = self._vsctl(['add-port', self.bridge, self.port])
if rc != 0:
raise Exception(err)
def delete(self):
'''Remove the port'''
rc, _, err = self._vsctl(['del-port', self.bridge, self.port])
if rc != 0:
raise Exception(err)
def check(self):
'''Run check mode'''
try:
if self.state == 'absent' and self.exists():
changed = True
elif self.state == 'present' and not self.exists():
changed = True
else:
changed = False
except Exception, e:
self.module.fail_json(msg=str(e))
self.module.exit_json(changed=changed)
def run(self):
'''Make the necessary changes'''
changed = False
try:
if self.state == 'absent':
if self.exists():
self.delete()
changed = True
elif self.state == 'present':
if not self.exists():
self.add()
changed = True
except Exception, e:
self.module.fail_json(msg=str(e))
self.module.exit_json(changed=changed)
def main():
module = AnsibleModule(
argument_spec={
'bridge': {'required': True},
'port': {'required': True},
'state': {'default': 'present', 'choices': ['present', 'absent']},
'timeout': {'default': 5, 'type': 'int'}
},
supports_check_mode=True,
)
port = OVSPort(module)
if module.check_mode:
port.check()
else:
port.run()
# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()
...@@ -123,8 +123,8 @@ def install_packages(module, pkgin_path, packages, cached, pkgsite): ...@@ -123,8 +123,8 @@ def install_packages(module, pkgin_path, packages, cached, pkgsite):
if not module.check_mode: if not module.check_mode:
rc, out, err = module.run_command("%s %s install -U -y %s" % (pkgsite, pkgin_path, package)) rc, out, err = module.run_command("%s %s install -U -y %s" % (pkgsite, pkgin_path, package))
if not module.check_mode and query_package(module, pkgin_path, package): if not module.check_mode and not query_package(module, pkgin_path, package):
module.fail_json(msg="failed to install %s: %s" % (package, out)) module.fail_json(msg="failed to install %s: %s" % (package, out), stderr=err)
install_c += 1 install_c += 1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment