Force command action to not be executed by the shell unless specifically enabled

This commit is contained in:
James Tanner 2014-03-10 16:11:24 -05:00 committed by James Cammarata
parent a1b1182662
commit fc33860e5d
16 changed files with 146 additions and 222 deletions

View file

@ -113,13 +113,14 @@ class VMNotFound(Exception):
class LibvirtConnection(object): class LibvirtConnection(object):
def __init__(self, uri): def __init__(self, uri, module):
cmd = subprocess.Popen("uname -r", shell=True, stdout=subprocess.PIPE, self.module = module
close_fds=True)
output = cmd.communicate()[0]
if output.find("xen") != -1: cmd = "uname -r"
rc, stdout, stderr = self.module.run_command(cmd)
if stdout.find("xen") != -1:
conn = libvirt.open(None) conn = libvirt.open(None)
else: else:
conn = libvirt.open(uri) conn = libvirt.open(uri)
@ -221,11 +222,12 @@ class LibvirtConnection(object):
class Virt(object): class Virt(object):
def __init__(self, uri): def __init__(self, uri, module):
self.module = module
self.uri = uri self.uri = uri
def __get_conn(self): def __get_conn(self):
self.conn = LibvirtConnection(self.uri) self.conn = LibvirtConnection(self.uri, self.module)
return self.conn return self.conn
def get_vm(self, vmid): def get_vm(self, vmid):
@ -399,7 +401,7 @@ def core(module):
uri = module.params.get('uri', None) uri = module.params.get('uri', None)
xml = module.params.get('xml', None) xml = module.params.get('xml', None)
v = Virt(uri) v = Virt(uri, module)
res = {} res = {}
if state and command=='list_vms': if state and command=='list_vms':

View file

@ -136,7 +136,7 @@ def main():
args = shlex.split(args) args = shlex.split(args)
startd = datetime.datetime.now() startd = datetime.datetime.now()
rc, out, err = module.run_command(args, executable=executable) rc, out, err = module.run_command(args, executable=executable, use_unsafe_shell=shell)
endd = datetime.datetime.now() endd = datetime.datetime.now()
delta = endd - startd delta = endd - startd

View file

@ -16,8 +16,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import subprocess
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: synchronize module: synchronize
@ -272,6 +270,13 @@ def main():
cmd = cmd + " --rsync-path '%s'" %(rsync_path) cmd = cmd + " --rsync-path '%s'" %(rsync_path)
changed_marker = '<<CHANGED>>' changed_marker = '<<CHANGED>>'
cmd = cmd + " --out-format='" + changed_marker + "%i %n%L'" cmd = cmd + " --out-format='" + changed_marker + "%i %n%L'"
# expand the paths
if '@' not in source:
source = os.path.expanduser(source)
if '@' not in dest:
dest = os.path.expanduser(dest)
cmd = ' '.join([cmd, source, dest]) cmd = ' '.join([cmd, source, dest])
cmdstr = cmd cmdstr = cmd
(rc, out, err) = module.run_command(cmd) (rc, out, err) = module.run_command(cmd)

View file

@ -44,8 +44,6 @@ EXAMPLES = '''
- local_action: osx_say msg="{{inventory_hostname}} is all done" voice=Zarvox - local_action: osx_say msg="{{inventory_hostname}} is all done" voice=Zarvox
''' '''
import subprocess
DEFAULT_VOICE='Trinoids' DEFAULT_VOICE='Trinoids'
def say(module, msg, voice): def say(module, msg, voice):

View file

@ -151,8 +151,8 @@ def main():
command = '%s %s' % (virtualenv, env) command = '%s %s' % (virtualenv, env)
if site_packages: if site_packages:
command += ' --system-site-packages' command += ' --system-site-packages'
os.chdir(tempfile.gettempdir()) cwd = tempfile.gettempdir()
rc_venv, out_venv, err_venv = module.run_command(command) rc_venv, out_venv, err_venv = module.run_command(command, cwd=cwd)
rc += rc_venv rc += rc_venv
out += out_venv out += out_venv

View file

@ -125,10 +125,11 @@ class Npm(object):
cmd.append(self.name_version) cmd.append(self.name_version)
#If path is specified, cd into that path and run the command. #If path is specified, cd into that path and run the command.
cwd = None
if self.path: if self.path:
os.chdir(self.path) cwd = self.path
rc, out, err = self.module.run_command(cmd, check_rc=check_rc) rc, out, err = self.module.run_command(cmd, check_rc=check_rc, cwd=cwd)
return out return out
return '' return ''

View file

@ -90,7 +90,8 @@ def query_package(module, name, state="installed"):
# pacman -Q returns 0 if the package is installed, # pacman -Q returns 0 if the package is installed,
# 1 if it is not installed # 1 if it is not installed
if state == "installed": if state == "installed":
rc = os.system("pacman -Q %s" % (name)) cmd = "pacman -Q %s" % (name)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc == 0: if rc == 0:
return True return True
@ -99,7 +100,8 @@ def query_package(module, name, state="installed"):
def update_package_db(module): def update_package_db(module):
rc = os.system("pacman -Syy > /dev/null") cmd = "pacman -Syy > /dev/null"
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0: if rc != 0:
module.fail_json(msg="could not update package db") module.fail_json(msg="could not update package db")
@ -118,7 +120,8 @@ def remove_packages(module, packages):
if not query_package(module, package): if not query_package(module, package):
continue continue
rc = os.system("pacman -%s %s --noconfirm > /dev/null" % (args, package)) cmd = "pacman -%s %s --noconfirm > /dev/null" % (args, package)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0: if rc != 0:
module.fail_json(msg="failed to remove %s" % (package)) module.fail_json(msg="failed to remove %s" % (package))
@ -145,7 +148,8 @@ def install_packages(module, packages, package_files):
else: else:
params = '-S %s' % package params = '-S %s' % package
rc = os.system("pacman %s --noconfirm > /dev/null" % (params)) cmd = "pacman %s --noconfirm > /dev/null" % (params)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0: if rc != 0:
module.fail_json(msg="failed to install %s" % (package)) module.fail_json(msg="failed to install %s" % (package))

View file

@ -253,10 +253,10 @@ def main():
cmd = '%s --no-site-packages %s' % (virtualenv, env) cmd = '%s --no-site-packages %s' % (virtualenv, env)
else: else:
cmd = '%s %s' % (virtualenv, env) cmd = '%s %s' % (virtualenv, env)
os.chdir(tempfile.gettempdir()) this_dir = tempfile.gettempdir()
if chdir: if chdir:
os.chdir(chdir) this_dir = os.path.join(this_dir, chdir)
rc, out_venv, err_venv = module.run_command(cmd) rc, out_venv, err_venv = module.run_command(cmd, cwd=this_dir)
out += out_venv out += out_venv
err += err_venv err += err_venv
if rc != 0: if rc != 0:
@ -298,10 +298,11 @@ def main():
if module.check_mode: if module.check_mode:
module.exit_json(changed=True) module.exit_json(changed=True)
os.chdir(tempfile.gettempdir()) this_dir = tempfile.gettempdir()
if chdir: if chdir:
os.chdir(chdir) this_dir = os.path.join(this_dir, chdir)
rc, out_pip, err_pip = module.run_command(cmd, path_prefix=path_prefix)
rc, out_pip, err_pip = module.run_command(cmd, path_prefix=path_prefix, cwd=this_dir)
out += out_pip out += out_pip
err += err_pip err += err_pip
if rc == 1 and state == 'absent' and 'not installed' in out_pip: if rc == 1 and state == 'absent' and 'not installed' in out_pip:

View file

@ -75,39 +75,13 @@ EXAMPLES = '''
import os import os
import re import re
import types import types
import subprocess
import ConfigParser import ConfigParser
import shlex import shlex
class CommandException(Exception): class RegistrationBase(object):
pass def __init__(self, module, username=None, password=None):
self.module = module
def run_command(args):
'''
Convenience method to run a command, specified as a list of arguments.
Returns:
* tuple - (stdout, stder, retcode)
'''
# Coerce into a string
if isinstance(args, str):
args = shlex.split(args)
# Run desired command
proc = subprocess.Popen(args, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(stdout, stderr) = proc.communicate()
returncode = proc.poll()
if returncode != 0:
cmd = ' '.join(args)
raise CommandException("Command failed (%s): %s\n%s" % (returncode, cmd, stdout))
return (stdout, stderr, returncode)
class RegistrationBase (object):
def __init__(self, username=None, password=None):
self.username = username self.username = username
self.password = password self.password = password
@ -147,9 +121,10 @@ class RegistrationBase (object):
class Rhsm(RegistrationBase): class Rhsm(RegistrationBase):
def __init__(self, username=None, password=None): def __init__(self, module, username=None, password=None):
RegistrationBase.__init__(self, username, password) RegistrationBase.__init__(self, module, username, password)
self.config = self._read_config() self.config = self._read_config()
self.module = module
def _read_config(self, rhsm_conf='/etc/rhsm/rhsm.conf'): def _read_config(self, rhsm_conf='/etc/rhsm/rhsm.conf'):
''' '''
@ -199,8 +174,8 @@ class Rhsm(RegistrationBase):
for k,v in kwargs.items(): for k,v in kwargs.items():
if re.search(r'^(system|rhsm)_', k): if re.search(r'^(system|rhsm)_', k):
args.append('--%s=%s' % (k.replace('_','.'), v)) args.append('--%s=%s' % (k.replace('_','.'), v))
run_command(args) self.module.run_command(args, check_rc=True)
@property @property
def is_registered(self): def is_registered(self):
@ -216,13 +191,11 @@ class Rhsm(RegistrationBase):
os.path.isfile('/etc/pki/consumer/key.pem') os.path.isfile('/etc/pki/consumer/key.pem')
args = ['subscription-manager', 'identity'] args = ['subscription-manager', 'identity']
try: rc, stdout, stderr = self.module.run_command(args, check_rc=False)
(stdout, stderr, retcode) = run_command(args) if rc == 0:
except CommandException, e:
return False
else:
# Display some debug output
return True return True
else:
return False
def register(self, username, password, autosubscribe, activationkey): def register(self, username, password, autosubscribe, activationkey):
''' '''
@ -244,7 +217,7 @@ class Rhsm(RegistrationBase):
args.extend(['--password', password]) args.extend(['--password', password])
# Do the needful... # Do the needful...
run_command(args) rc, stderr, stdout = self.module.run_command(args, check_rc=True)
def unsubscribe(self): def unsubscribe(self):
''' '''
@ -253,7 +226,7 @@ class Rhsm(RegistrationBase):
* Exception - if error occurs while running command * Exception - if error occurs while running command
''' '''
args = ['subscription-manager', 'unsubscribe', '--all'] args = ['subscription-manager', 'unsubscribe', '--all']
run_command(args) rc, stderr, stdout = self.module.run_command(args, check_rc=True)
def unregister(self): def unregister(self):
''' '''
@ -262,7 +235,7 @@ class Rhsm(RegistrationBase):
* Exception - if error occurs while running command * Exception - if error occurs while running command
''' '''
args = ['subscription-manager', 'unregister'] args = ['subscription-manager', 'unregister']
run_command(args) rc, stderr, stdout = self.module.run_command(args, check_rc=True)
def subscribe(self, regexp): def subscribe(self, regexp):
''' '''
@ -273,7 +246,7 @@ class Rhsm(RegistrationBase):
''' '''
# Available pools ready for subscription # Available pools ready for subscription
available_pools = RhsmPools() available_pools = RhsmPools(self.module)
for pool in available_pools.filter(regexp): for pool in available_pools.filter(regexp):
pool.subscribe() pool.subscribe()
@ -284,7 +257,8 @@ class RhsmPool(object):
Convenience class for housing subscription information Convenience class for housing subscription information
''' '''
def __init__(self, **kwargs): def __init__(self, module, **kwargs):
self.module = module
for k,v in kwargs.items(): for k,v in kwargs.items():
setattr(self, k, v) setattr(self, k, v)
@ -292,15 +266,20 @@ class RhsmPool(object):
return str(self.__getattribute__('_name')) return str(self.__getattribute__('_name'))
def subscribe(self): def subscribe(self):
(stdout, stderr, retcode) = run_command("subscription-manager subscribe --pool %s" % self.PoolId) args = "subscription-manager subscribe --pool %s" % self.PoolId
return True rc, stdout, stderr = self.module.run_command(args, check_rc=True)
if rc == 0:
return True
else:
return False
class RhsmPools(object): class RhsmPools(object):
""" """
This class is used for manipulating pools subscriptions with RHSM This class is used for manipulating pools subscriptions with RHSM
""" """
def __init__(self): def __init__(self, module):
self.module = module
self.products = self._load_product_list() self.products = self._load_product_list()
def __iter__(self): def __iter__(self):
@ -310,7 +289,8 @@ class RhsmPools(object):
""" """
Loads list of all availaible pools for system in data structure Loads list of all availaible pools for system in data structure
""" """
(stdout, stderr, retval) = run_command("subscription-manager list --available") args = "subscription-manager list --available"
rc, stdout, stderr = self.module.run_command(args, check_rc=True)
products = [] products = []
for line in stdout.split('\n'): for line in stdout.split('\n'):
@ -326,7 +306,7 @@ class RhsmPools(object):
value = value.strip() value = value.strip()
if key in ['ProductName', 'SubscriptionName']: if key in ['ProductName', 'SubscriptionName']:
# Remember the name for later processing # Remember the name for later processing
products.append(RhsmPool(_name=value, key=value)) products.append(RhsmPool(self.module, _name=value, key=value))
elif products: elif products:
# Associate value with most recently recorded product # Associate value with most recently recorded product
products[-1].__setattr__(key, value) products[-1].__setattr__(key, value)
@ -348,7 +328,7 @@ class RhsmPools(object):
def main(): def main():
# Load RHSM configuration from file # Load RHSM configuration from file
rhn = Rhsm() rhn = Rhsm(AnsibleModule())
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec = dict(
@ -364,6 +344,7 @@ def main():
) )
) )
rhn.module = module
state = module.params['state'] state = module.params['state']
username = module.params['username'] username = module.params['username']
password = module.params['password'] password = module.params['password']

View file

@ -72,12 +72,7 @@ EXAMPLES = '''
''' '''
import sys import sys
import os
import re
import types import types
import subprocess
import ConfigParser
import shlex
import xmlrpclib import xmlrpclib
import urlparse import urlparse
@ -90,75 +85,9 @@ except ImportError, e:
module.fail_json(msg="Unable to import up2date_client. Is 'rhn-client-tools' installed?\n%s" % e) module.fail_json(msg="Unable to import up2date_client. Is 'rhn-client-tools' installed?\n%s" % e)
class CommandException(Exception):
pass
def run_command(args):
'''
Convenience method to run a command, specified as a list of arguments.
Returns:
* tuple - (stdout, stder, retcode)
'''
# Coerce into a string
if isinstance(args, str):
args = shlex.split(args)
# Run desired command
proc = subprocess.Popen(args, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(stdout, stderr) = proc.communicate()
returncode = proc.poll()
if returncode != 0:
cmd = ' '.join(args)
raise CommandException("Command failed (%s): %s\n%s" % (returncode, cmd, stdout))
return (stdout, stderr, returncode)
class RegistrationBase (object):
def __init__(self, username=None, password=None):
self.username = username
self.password = password
def configure(self):
raise NotImplementedError("Must be implemented by a sub-class")
def enable(self):
# Remove any existing redhat.repo
redhat_repo = '/etc/yum.repos.d/redhat.repo'
if os.path.isfile(redhat_repo):
os.unlink(redhat_repo)
def register(self):
raise NotImplementedError("Must be implemented by a sub-class")
def unregister(self):
raise NotImplementedError("Must be implemented by a sub-class")
def unsubscribe(self):
raise NotImplementedError("Must be implemented by a sub-class")
def update_plugin_conf(self, plugin, enabled=True):
plugin_conf = '/etc/yum/pluginconf.d/%s.conf' % plugin
if os.path.isfile(plugin_conf):
cfg = ConfigParser.ConfigParser()
cfg.read([plugin_conf])
if enabled:
cfg.set('main', 'enabled', 1)
else:
cfg.set('main', 'enabled', 0)
fd = open(plugin_conf, 'rwa+')
cfg.write(fd)
fd.close()
def subscribe(self, **kwargs):
raise NotImplementedError("Must be implemented by a sub-class")
class Rhn(RegistrationBase): class Rhn(RegistrationBase):
def __init__(self, username=None, password=None): def __init__(self, module, username=None, password=None):
RegistrationBase.__init__(self, username, password) RegistrationBase.__init__(self, username, password)
self.config = self.load_config() self.config = self.load_config()
@ -271,7 +200,7 @@ class Rhn(RegistrationBase):
register_cmd += " --activationkey '%s'" % activationkey register_cmd += " --activationkey '%s'" % activationkey
# FIXME - support --profilename # FIXME - support --profilename
# FIXME - support --systemorgid # FIXME - support --systemorgid
run_command(register_cmd) rc, stdout, stderr = self.module.run_command(register_command, check_rc=True)
def api(self, method, *args): def api(self, method, *args):
''' '''
@ -309,14 +238,14 @@ class Rhn(RegistrationBase):
Subscribe to requested yum repositories using 'rhn-channel' command Subscribe to requested yum repositories using 'rhn-channel' command
''' '''
rhn_channel_cmd = "rhn-channel --user='%s' --password='%s'" % (self.username, self.password) rhn_channel_cmd = "rhn-channel --user='%s' --password='%s'" % (self.username, self.password)
(stdout, stderr, rc) = run_command(rhn_channel_cmd + " --available-channels") rc, stdout, stderr = self.module.run_command(rhn_channel_cmd + " --available-channels", check_rc=True)
# Enable requested repoid's # Enable requested repoid's
for wanted_channel in channels: for wanted_channel in channels:
# Each inserted repo regexp will be matched. If no match, no success. # Each inserted repo regexp will be matched. If no match, no success.
for availaible_channel in stdout.rstrip().split('\n'): # .rstrip() because of \n at the end -> empty string at the end for availaible_channel in stdout.rstrip().split('\n'): # .rstrip() because of \n at the end -> empty string at the end
if re.search(wanted_repo, available_channel): if re.search(wanted_repo, available_channel):
run_command(rhn_channel_cmd + " --add --channel=%s" % available_channel) rc, stdout, stderr = self.module.run_command(rhn_channel_cmd + " --add --channel=%s" % available_channel, check_rc=True)
def main(): def main():
@ -379,4 +308,6 @@ def main():
# import module snippets # import module snippets
from ansible.module_utils.basic import * from ansible.module_utils.basic import *
from ansible.module_utils.redhat import *
main() main()

View file

@ -91,7 +91,8 @@ def query_package(module, name):
# rpm -q returns 0 if the package is installed, # rpm -q returns 0 if the package is installed,
# 1 if it is not installed # 1 if it is not installed
rc = os.system("rpm -q %s" % (name)) cmd = "rpm -q %s" % (name)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc == 0: if rc == 0:
return True return True
else: else:
@ -103,13 +104,14 @@ def query_package_provides(module, name):
# rpm -q returns 0 if the package is installed, # rpm -q returns 0 if the package is installed,
# 1 if it is not installed # 1 if it is not installed
rc = os.system("rpm -q --provides %s >/dev/null" % (name)) cmd = "rpm -q --provides %s >/dev/null" % (name)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
return rc == 0 return rc == 0
def update_package_db(module): def update_package_db(module):
rc = os.system("urpmi.update -a -q") cmd = "urpmi.update -a -q"
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0: if rc != 0:
module.fail_json(msg="could not update package db") module.fail_json(msg="could not update package db")
@ -123,7 +125,8 @@ def remove_packages(module, packages):
if not query_package(module, package): if not query_package(module, package):
continue continue
rc = os.system("%s --auto %s > /dev/null" % (URPME_PATH, package)) cmd = "%s --auto %s > /dev/null" % (URPME_PATH, package)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0: if rc != 0:
module.fail_json(msg="failed to remove %s" % (package)) module.fail_json(msg="failed to remove %s" % (package))

View file

@ -75,16 +75,17 @@ class Bzr(object):
self.version = version self.version = version
self.bzr_path = bzr_path self.bzr_path = bzr_path
def _command(self, args_list, **kwargs): def _command(self, args_list, cwd=None, **kwargs):
(rc, out, err) = self.module.run_command( (rc, out, err) = self.module.run_command(
[self.bzr_path] + args_list, **kwargs) [self.bzr_path] + args_list, cwd=cwd, **kwargs)
return (rc, out, err) return (rc, out, err)
def get_version(self): def get_version(self):
'''samples the version of the bzr branch''' '''samples the version of the bzr branch'''
os.chdir(self.dest)
cmd = "%s revno" % self.bzr_path cmd = "%s revno" % self.bzr_path
revno = os.popen(cmd).read().strip() rc, stdout, stderr = self.module.run_command(cmd, cwd=self.dest)
revno = stdout.strip()
return revno return revno
def clone(self): def clone(self):
@ -94,17 +95,18 @@ class Bzr(object):
os.makedirs(dest_dirname) os.makedirs(dest_dirname)
except: except:
pass pass
os.chdir(dest_dirname)
if self.version.lower() != 'head': if self.version.lower() != 'head':
args_list = ["branch", "-r", self.version, self.parent, self.dest] args_list = ["branch", "-r", self.version, self.parent, self.dest]
else: else:
args_list = ["branch", self.parent, self.dest] args_list = ["branch", self.parent, self.dest]
return self._command(args_list, check_rc=True) return self._command(args_list, check_rc=True, cwd=dest_dirname)
def has_local_mods(self): def has_local_mods(self):
os.chdir(self.dest)
cmd = "%s status -S" % self.bzr_path cmd = "%s status -S" % self.bzr_path
lines = os.popen(cmd).read().splitlines() rc, stdout, stderr = self.module.run_command(cmd, cwd=self.dest)
lines = stdout.splitlines()
lines = filter(lambda c: not re.search('^\\?\\?.*$', c), lines) lines = filter(lambda c: not re.search('^\\?\\?.*$', c), lines)
return len(lines) > 0 return len(lines) > 0
@ -114,30 +116,27 @@ class Bzr(object):
Discards any changes to tracked files in the working Discards any changes to tracked files in the working
tree since that commit. tree since that commit.
''' '''
os.chdir(self.dest)
if not force and self.has_local_mods(): if not force and self.has_local_mods():
self.module.fail_json(msg="Local modifications exist in branch (force=no).") self.module.fail_json(msg="Local modifications exist in branch (force=no).")
return self._command(["revert"], check_rc=True) return self._command(["revert"], check_rc=True, cwd=self.dest)
def fetch(self): def fetch(self):
'''updates branch from remote sources''' '''updates branch from remote sources'''
os.chdir(self.dest)
if self.version.lower() != 'head': if self.version.lower() != 'head':
(rc, out, err) = self._command(["pull", "-r", self.version]) (rc, out, err) = self._command(["pull", "-r", self.version], cwd=self.dest)
else: else:
(rc, out, err) = self._command(["pull"]) (rc, out, err) = self._command(["pull"], cwd=self.dest)
if rc != 0: if rc != 0:
self.module.fail_json(msg="Failed to pull") self.module.fail_json(msg="Failed to pull")
return (rc, out, err) return (rc, out, err)
def switch_version(self): def switch_version(self):
'''once pulled, switch to a particular revno or revid''' '''once pulled, switch to a particular revno or revid'''
os.chdir(self.dest)
if self.version.lower() != 'head': if self.version.lower() != 'head':
args_list = ["revert", "-r", self.version] args_list = ["revert", "-r", self.version]
else: else:
args_list = ["revert"] args_list = ["revert"]
return self._command(args_list, check_rc=True) return self._command(args_list, check_rc=True, cwd=self.dest)
# =========================================== # ===========================================

View file

@ -181,11 +181,12 @@ def set_git_ssh(ssh_wrapper, key_file, ssh_opts):
if ssh_opts: if ssh_opts:
os.environ["GIT_SSH_OPTS"] = ssh_opts os.environ["GIT_SSH_OPTS"] = ssh_opts
def get_version(git_path, dest, ref="HEAD"): def get_version(module, git_path, dest, ref="HEAD"):
''' samples the version of the git repo ''' ''' samples the version of the git repo '''
os.chdir(dest)
cmd = "%s rev-parse %s" % (git_path, ref) cmd = "%s rev-parse %s" % (git_path, ref)
sha = os.popen(cmd).read().rstrip("\n") rc, stdout, stderr = module.run_command(cmd, cwd=dest)
sha = stdout.rstrip('\n')
return sha return sha
def clone(git_path, module, repo, dest, remote, depth, version, bare, reference): def clone(git_path, module, repo, dest, remote, depth, version, bare, reference):
@ -195,7 +196,6 @@ def clone(git_path, module, repo, dest, remote, depth, version, bare, reference)
os.makedirs(dest_dirname) os.makedirs(dest_dirname)
except: except:
pass pass
os.chdir(dest_dirname)
cmd = [ git_path, 'clone' ] cmd = [ git_path, 'clone' ]
if bare: if bare:
cmd.append('--bare') cmd.append('--bare')
@ -209,19 +209,19 @@ def clone(git_path, module, repo, dest, remote, depth, version, bare, reference)
if reference: if reference:
cmd.extend([ '--reference', str(reference) ]) cmd.extend([ '--reference', str(reference) ])
cmd.extend([ repo, dest ]) cmd.extend([ repo, dest ])
module.run_command(cmd, check_rc=True) module.run_command(cmd, check_rc=True, cwd=dest_dirname)
if bare: if bare:
os.chdir(dest)
if remote != 'origin': if remote != 'origin':
module.run_command([git_path, 'remote', 'add', remote, repo], check_rc=True) module.run_command([git_path, 'remote', 'add', remote, repo], check_rc=True, cwd=dest)
def has_local_mods(git_path, dest, bare): def has_local_mods(module, git_path, dest, bare):
if bare: if bare:
return False return False
os.chdir(dest)
cmd = "%s status -s" % (git_path,) cmd = "%s status -s" % (git_path)
lines = os.popen(cmd).read().splitlines() rc, stdout, stderr = module.run_command(cmd, cwd=dest)
lines = filter(lambda c: not re.search('^\\?\\?.*$', c), lines) lines = stdout.splitlines()
return len(lines) > 0 return len(lines) > 0
def reset(git_path, module, dest): def reset(git_path, module, dest):
@ -230,16 +230,16 @@ def reset(git_path, module, dest):
Discards any changes to tracked files in working Discards any changes to tracked files in working
tree since that commit. tree since that commit.
''' '''
os.chdir(dest)
cmd = "%s reset --hard HEAD" % (git_path,) cmd = "%s reset --hard HEAD" % (git_path,)
return module.run_command(cmd, check_rc=True) return module.run_command(cmd, check_rc=True, cwd=dest)
def get_remote_head(git_path, module, dest, version, remote, bare): def get_remote_head(git_path, module, dest, version, remote, bare):
cloning = False cloning = False
cwd = None
if remote == module.params['repo']: if remote == module.params['repo']:
cloning = True cloning = True
else: else:
os.chdir(dest) cwd = dest
if version == 'HEAD': if version == 'HEAD':
if cloning: if cloning:
# cloning the repo, just get the remote's HEAD version # cloning the repo, just get the remote's HEAD version
@ -255,7 +255,7 @@ def get_remote_head(git_path, module, dest, version, remote, bare):
# appears to be a sha1. return as-is since it appears # appears to be a sha1. return as-is since it appears
# cannot check for a specific sha1 on remote # cannot check for a specific sha1 on remote
return version return version
(rc, out, err) = module.run_command(cmd, check_rc=True ) (rc, out, err) = module.run_command(cmd, check_rc=True, cwd=cwd)
if len(out) < 1: if len(out) < 1:
module.fail_json(msg="Could not determine remote revision for %s" % version) module.fail_json(msg="Could not determine remote revision for %s" % version)
rev = out.split()[0] rev = out.split()[0]
@ -270,10 +270,9 @@ def is_remote_tag(git_path, module, dest, remote, version):
return False return False
def get_branches(git_path, module, dest): def get_branches(git_path, module, dest):
os.chdir(dest)
branches = [] branches = []
cmd = '%s branch -a' % (git_path,) cmd = '%s branch -a' % (git_path,)
(rc, out, err) = module.run_command(cmd) (rc, out, err) = module.run_command(cmd, cwd=dest)
if rc != 0: if rc != 0:
module.fail_json(msg="Could not determine branch data - received %s" % out) module.fail_json(msg="Could not determine branch data - received %s" % out)
for line in out.split('\n'): for line in out.split('\n'):
@ -281,10 +280,9 @@ def get_branches(git_path, module, dest):
return branches return branches
def get_tags(git_path, module, dest): def get_tags(git_path, module, dest):
os.chdir(dest)
tags = [] tags = []
cmd = '%s tag' % (git_path,) cmd = '%s tag' % (git_path,)
(rc, out, err) = module.run_command(cmd) (rc, out, err) = module.run_command(cmd, cwd=dest)
if rc != 0: if rc != 0:
module.fail_json(msg="Could not determine tag data - received %s" % out) module.fail_json(msg="Could not determine tag data - received %s" % out)
for line in out.split('\n'): for line in out.split('\n'):
@ -352,18 +350,17 @@ def get_head_branch(git_path, module, dest, remote, bare=False):
def fetch(git_path, module, repo, dest, version, remote, bare): def fetch(git_path, module, repo, dest, version, remote, bare):
''' updates repo from remote sources ''' ''' updates repo from remote sources '''
os.chdir(dest)
if bare: if bare:
(rc, out1, err1) = module.run_command([git_path, 'fetch', remote, '+refs/heads/*:refs/heads/*']) (rc, out1, err1) = module.run_command([git_path, 'fetch', remote, '+refs/heads/*:refs/heads/*'], cwd=dest)
else: else:
(rc, out1, err1) = module.run_command("%s fetch %s" % (git_path, remote)) (rc, out1, err1) = module.run_command("%s fetch %s" % (git_path, remote), cwd=dest)
if rc != 0: if rc != 0:
module.fail_json(msg="Failed to download remote objects and refs") module.fail_json(msg="Failed to download remote objects and refs")
if bare: if bare:
(rc, out2, err2) = module.run_command([git_path, 'fetch', remote, '+refs/tags/*:refs/tags/*']) (rc, out2, err2) = module.run_command([git_path, 'fetch', remote, '+refs/tags/*:refs/tags/*'], cwd=dest)
else: else:
(rc, out2, err2) = module.run_command("%s fetch --tags %s" % (git_path, remote)) (rc, out2, err2) = module.run_command("%s fetch --tags %s" % (git_path, remote), cwd=dest)
if rc != 0: if rc != 0:
module.fail_json(msg="Failed to download remote objects and refs") module.fail_json(msg="Failed to download remote objects and refs")
(rc, out3, err3) = submodule_update(git_path, module, dest) (rc, out3, err3) = submodule_update(git_path, module, dest)
@ -371,28 +368,26 @@ def fetch(git_path, module, repo, dest, version, remote, bare):
def submodule_update(git_path, module, dest): def submodule_update(git_path, module, dest):
''' init and update any submodules ''' ''' init and update any submodules '''
os.chdir(dest)
# skip submodule commands if .gitmodules is not present # skip submodule commands if .gitmodules is not present
if not os.path.exists(os.path.join(dest, '.gitmodules')): if not os.path.exists(os.path.join(dest, '.gitmodules')):
return (0, '', '') return (0, '', '')
cmd = [ git_path, 'submodule', 'sync' ] cmd = [ git_path, 'submodule', 'sync' ]
(rc, out, err) = module.run_command(cmd, check_rc=True) (rc, out, err) = module.run_command(cmd, check_rc=True, cwd=dest)
cmd = [ git_path, 'submodule', 'update', '--init', '--recursive' ] cmd = [ git_path, 'submodule', 'update', '--init', '--recursive' ]
(rc, out, err) = module.run_command(cmd) (rc, out, err) = module.run_command(cmd, cwd=dest)
if rc != 0: if rc != 0:
module.fail_json(msg="Failed to init/update submodules") module.fail_json(msg="Failed to init/update submodules")
return (rc, out, err) return (rc, out, err)
def switch_version(git_path, module, dest, remote, version): def switch_version(git_path, module, dest, remote, version):
''' once pulled, switch to a particular SHA, tag, or branch ''' ''' once pulled, switch to a particular SHA, tag, or branch '''
os.chdir(dest)
cmd = '' cmd = ''
if version != 'HEAD': if version != 'HEAD':
if is_remote_branch(git_path, module, dest, remote, version): if is_remote_branch(git_path, module, dest, remote, version):
if not is_local_branch(git_path, module, dest, version): if not is_local_branch(git_path, module, dest, version):
cmd = "%s checkout --track -b %s %s/%s" % (git_path, version, remote, version) cmd = "%s checkout --track -b %s %s/%s" % (git_path, version, remote, version)
else: else:
(rc, out, err) = module.run_command("%s checkout --force %s" % (git_path, version)) (rc, out, err) = module.run_command("%s checkout --force %s" % (git_path, version), cwd=dest)
if rc != 0: if rc != 0:
module.fail_json(msg="Failed to checkout branch %s" % version) module.fail_json(msg="Failed to checkout branch %s" % version)
cmd = "%s reset --hard %s/%s" % (git_path, remote, version) cmd = "%s reset --hard %s/%s" % (git_path, remote, version)
@ -400,11 +395,11 @@ def switch_version(git_path, module, dest, remote, version):
cmd = "%s checkout --force %s" % (git_path, version) cmd = "%s checkout --force %s" % (git_path, version)
else: else:
branch = get_head_branch(git_path, module, dest, remote) branch = get_head_branch(git_path, module, dest, remote)
(rc, out, err) = module.run_command("%s checkout --force %s" % (git_path, branch)) (rc, out, err) = module.run_command("%s checkout --force %s" % (git_path, branch), cwd=dest)
if rc != 0: if rc != 0:
module.fail_json(msg="Failed to checkout branch %s" % branch) module.fail_json(msg="Failed to checkout branch %s" % branch)
cmd = "%s reset --hard %s" % (git_path, remote) cmd = "%s reset --hard %s" % (git_path, remote)
(rc, out1, err1) = module.run_command(cmd) (rc, out1, err1) = module.run_command(cmd, cwd=dest)
if rc != 0: if rc != 0:
if version != 'HEAD': if version != 'HEAD':
module.fail_json(msg="Failed to checkout %s" % (version)) module.fail_json(msg="Failed to checkout %s" % (version))
@ -484,12 +479,12 @@ def main():
# Just return having found a repo already in the dest path # Just return having found a repo already in the dest path
# this does no checking that the repo is the actual repo # this does no checking that the repo is the actual repo
# requested. # requested.
before = get_version(git_path, dest) before = get_version(module, git_path, dest)
module.exit_json(changed=False, before=before, after=before) module.exit_json(changed=False, before=before, after=before)
else: else:
# else do a pull # else do a pull
local_mods = has_local_mods(git_path, dest, bare) local_mods = has_local_mods(module, git_path, dest, bare)
before = get_version(git_path, dest) before = get_version(module, git_path, dest)
if local_mods: if local_mods:
# failure should happen regardless of check mode # failure should happen regardless of check mode
if not force: if not force:
@ -519,7 +514,7 @@ def main():
switch_version(git_path, module, dest, remote, version) switch_version(git_path, module, dest, remote, version)
# determine if we changed anything # determine if we changed anything
after = get_version(git_path, dest) after = get_version(module, git_path, dest)
changed = False changed = False
if before != after or local_mods: if before != after or local_mods:

View file

@ -207,7 +207,9 @@ class Service(object):
os._exit(0) os._exit(0)
# Start the command # Start the command
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=lambda: os.close(pipe[1])) if isinstance(cmd, basestring):
cmd = shlex.split(cmd)
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=lambda: os.close(pipe[1]))
stdout = "" stdout = ""
stderr = "" stderr = ""
fds = [p.stdout, p.stderr] fds = [p.stdout, p.stderr]

View file

@ -29,7 +29,6 @@ import socket
import struct import struct
import datetime import datetime
import getpass import getpass
import subprocess
import ConfigParser import ConfigParser
import StringIO import StringIO
@ -1432,7 +1431,8 @@ class LinuxNetwork(Network):
""" """
platform = 'Linux' platform = 'Linux'
def __init__(self): def __init__(self, module):
self.module = module
Network.__init__(self) Network.__init__(self)
def populate(self): def populate(self):
@ -1618,12 +1618,15 @@ class LinuxNetwork(Network):
ips['all_ipv6_addresses'].append(address) ips['all_ipv6_addresses'].append(address)
ip_path = module.get_bin_path("ip") ip_path = module.get_bin_path("ip")
primary_data = subprocess.Popen(
[ip_path, 'addr', 'show', 'primary', device], args = [ip_path, 'addr', 'show', 'primary', device]
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] rc, stdout, stderr = self.module.run_command(args)
secondary_data = subprocess.Popen( primary_data = stdout
[ip_path, 'addr', 'show', 'secondary', device],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] args = [ip_path, 'addr', 'show', 'secondary', device]
rc, stdout, stderr = self.module.run_command(args)
secondary_data = stdout
parse_ip_output(primary_data) parse_ip_output(primary_data)
parse_ip_output(secondary_data, secondary=True) parse_ip_output(secondary_data, secondary=True)
@ -2283,11 +2286,11 @@ def get_file_content(path, default=None):
data = default data = default
return data return data
def ansible_facts(): def ansible_facts(module):
facts = {} facts = {}
facts.update(Facts().populate()) facts.update(Facts().populate())
facts.update(Hardware().populate()) facts.update(Hardware().populate())
facts.update(Network().populate()) facts.update(Network(module).populate())
facts.update(Virtual().populate()) facts.update(Virtual().populate())
return facts return facts
@ -2296,7 +2299,7 @@ def ansible_facts():
def run_setup(module): def run_setup(module):
setup_options = {} setup_options = {}
facts = ansible_facts() facts = ansible_facts(module)
for (k, v) in facts.items(): for (k, v) in facts.items():
setup_options["ansible_%s" % k.replace('-', '_')] = v setup_options["ansible_%s" % k.replace('-', '_')] = v

View file

@ -232,7 +232,6 @@ def main():
_ensure_virtualenv(module) _ensure_virtualenv(module)
os.chdir(app_path)
cmd = "python manage.py %s" % (command, ) cmd = "python manage.py %s" % (command, )
if command in noinput_commands: if command in noinput_commands:
@ -251,7 +250,7 @@ def main():
if module.params[param]: if module.params[param]:
cmd = '%s %s' % (cmd, module.params[param]) cmd = '%s %s' % (cmd, module.params[param])
rc, out, err = module.run_command(cmd) rc, out, err = module.run_command(cmd, cwd=app_path)
if rc != 0: if rc != 0:
if command == 'createcachetable' and 'table' in err and 'already exists' in err: if command == 'createcachetable' and 'table' in err and 'already exists' in err:
out = 'Already exists.' out = 'Already exists.'