diff --git a/docsite/latest/rst/gettingstarted.rst b/docsite/latest/rst/gettingstarted.rst index 34241673c93..f4f0d47f405 100644 --- a/docsite/latest/rst/gettingstarted.rst +++ b/docsite/latest/rst/gettingstarted.rst @@ -310,7 +310,7 @@ If you would like to access sudo mode, there are also flags to do that: # as bruce, sudoing to batman $ ansible all -m ping -u bruce --sudo --sudo-user batman -(The sudo implementation is changeable in ansbile's configuration file if you happen to want to use a sudo +(The sudo implementation is changeable in ansible's configuration file if you happen to want to use a sudo replacement. Flags passed dot sudo can also be set.) Now run a live command on all of your nodes: diff --git a/docsite/latest/rst/playbooks2.rst b/docsite/latest/rst/playbooks2.rst index 362e6b20587..ccbc07f3dc9 100644 --- a/docsite/latest/rst/playbooks2.rst +++ b/docsite/latest/rst/playbooks2.rst @@ -186,6 +186,15 @@ in a push-script:: There are full examples of both of these items in the github examples/playbooks directory. +If you have a variable that changes infrequently, it might make sense to +provide a default value that can be overriden. This can be accomplished using +the default argument:: + + vars_prompt: + - name: "release_version" + prompt: "Product release version" + default: "1.0" + An alternative form of vars_prompt allows for hiding input from the user, and may later support some other options, but otherwise works equivalently:: @@ -290,7 +299,7 @@ decide to do something conditionally based on success or failure:: - action: command /bin/something when: result|failed - action: command /bin/something_else - when: result|sucess + when: result|success As a reminder, to see what derived variables are available, you can do:: diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py index 1f2b7dcba79..b82a1f605f3 100644 --- a/lib/ansible/runner/__init__.py +++ b/lib/ansible/runner/__init__.py @@ -381,6 +381,7 @@ class Runner(object): inject = utils.combine_vars(inject, host_variables) inject = utils.combine_vars(inject, self.module_vars) inject = utils.combine_vars(inject, self.setup_cache[host]) + inject.setdefault('ansible_ssh_user', self.remote_user) inject['hostvars'] = HostVars(self.setup_cache, self.inventory) inject['group_names'] = host_variables.get('group_names', []) inject['groups'] = self.inventory.groups_list() diff --git a/library/cloud/ec2 b/library/cloud/ec2 index e8d6b73ea62..4916594d5f5 100644 --- a/library/cloud/ec2 +++ b/library/cloud/ec2 @@ -142,6 +142,13 @@ options: required: false default: null aliases: [] + placement_group: + version_added: "1.3" + description: + - placement group for the instance when using EC2 Clustered Compute + required: false + default: null + aliases: [] vpc_subnet_id: version_added: "1.1" description: @@ -223,6 +230,7 @@ def main(): ec2_url = dict(aliases=['EC2_URL']), ec2_secret_key = dict(aliases=['EC2_SECRET_KEY'], no_log=True), ec2_access_key = dict(aliases=['EC2_ACCESS_KEY']), + placement_group = dict(), user_data = dict(), instance_tags = dict(), vpc_subnet_id = dict(), @@ -247,6 +255,7 @@ def main(): ec2_url = module.params.get('ec2_url') ec2_secret_key = module.params.get('ec2_secret_key') ec2_access_key = module.params.get('ec2_access_key') + placement_group = module.params.get('placement_group') user_data = module.params.get('user_data') instance_tags = module.params.get('instance_tags') vpc_subnet_id = module.params.get('vpc_subnet_id') @@ -310,7 +319,6 @@ def main(): count_remaining = count_remaining - len(running_instances) # Both min_count and max_count equal count parameter. This means the launch request is explicit (we want count, or fail) in how many instances we want. - if count_remaining > 0: try: @@ -320,7 +328,8 @@ def main(): 'min_count': count_remaining, 'max_count': count_remaining, 'monitoring_enabled': monitoring, - 'placement': zone, + 'placement': zone, + 'placement_group': placement_group, 'instance_type': instance_type, 'kernel_id': kernel, 'ramdisk_id': ramdisk, diff --git a/library/cloud/quantum_router_interface b/library/cloud/quantum_router_interface index dfc01e2928e..f85ac1a311b 100644 --- a/library/cloud/quantum_router_interface +++ b/library/cloud/quantum_router_interface @@ -239,7 +239,7 @@ def main(): if module.params['state'] == 'absent': port_id = _get_port_id(quantum, module, router_id, subnet_id) if not port_id: - module.exit_json(changed = False, result = "Sucess") + module.exit_json(changed = False, result = "Success") _remove_interface_router(quantum, module, router_id, subnet_id) module.exit_json(changed=True, result="Deleted") diff --git a/library/network/get_url b/library/network/get_url index 7cc1c5227ec..53b07261479 100644 --- a/library/network/get_url +++ b/library/network/get_url @@ -89,7 +89,6 @@ author: Jan-Piet Mens ''' EXAMPLES=''' -<<<<<<< HEAD - name: download foo.conf get_url: url=http://example.com/path/file.conf dest=/etc/foo.conf mode=0440 diff --git a/library/notification/mail b/library/notification/mail index b3d9dc794fe..76d39cc6b27 100644 --- a/library/notification/mail +++ b/library/notification/mail @@ -103,7 +103,7 @@ options: EXAMPLES = ''' # Example playbook sending mail to root -- local_action: mail msg='System ${ansible_hostname} has been sucessfully provisioned.' +- local_action: mail msg='System ${ansible_hostname} has been successfully provisioned.' # Send e-mail to a bunch of users, attaching files - local_action: mail diff --git a/library/packaging/apt b/library/packaging/apt index dd2fed9e465..d0e86e80827 100644 --- a/library/packaging/apt +++ b/library/packaging/apt @@ -31,7 +31,7 @@ options: pkg: description: - A package name or package specifier with version, like C(foo) or C(foo=1.0) - required: true + required: false default: null state: description: diff --git a/library/system/service b/library/system/service index 3970144e917..bb5b903b6f5 100644 --- a/library/system/service +++ b/library/system/service @@ -54,6 +54,12 @@ options: - Whether the service should start on boot. At least one of state and enabled are required. + runlevel: + required: false + description: + - The runlevel that this service belongs to. Needed by OpenRC system + (e.g. Gentoo), and default to "default" if not set. + arguments: description: - Additional arguments provided on the command line @@ -85,6 +91,7 @@ EXAMPLES = ''' import platform import os +import re import tempfile import shlex import select @@ -115,8 +122,10 @@ class Service(object): self.state = module.params['state'] self.pattern = module.params['pattern'] self.enable = module.params['enabled'] + self.runlevel = module.params['runlevel'] self.changed = False self.running = None + self.crashed = None self.action = None self.svc_cmd = None self.svc_initscript = None @@ -360,7 +369,7 @@ class LinuxService(Service): def get_service_tools(self): paths = [ '/sbin', '/usr/sbin', '/bin', '/usr/bin' ] - binaries = [ 'service', 'chkconfig', 'update-rc.d', 'initctl', 'systemctl', 'start', 'stop', 'restart' ] + binaries = [ 'service', 'chkconfig', 'update-rc.d', 'rc-service', 'rc-update', 'initctl', 'systemctl', 'start', 'stop', 'restart' ] initpaths = [ '/etc/init.d' ] location = dict() @@ -379,6 +388,11 @@ class LinuxService(Service): elif location.get('update-rc.d', None) and os.path.exists("/etc/init.d/%s" % self.name): # service is managed by with SysV init scripts, but with update-rc.d self.enable_cmd = location['update-rc.d'] + elif location.get('rc-service', None) and not location.get('systemctl', None): + # service is managed by OpenRC + self.svc_cmd = location['rc-service'] + self.enable_cmd = location['rc-update'] + return elif location.get('systemctl', None): # verify service is managed by systemd @@ -435,6 +449,11 @@ class LinuxService(Service): elif initctl_status_stdout.find("start/running") != -1: self.running = True + if self.svc_cmd.endswith("rc-service") and self.running is None: + openrc_rc, openrc_status_stdout, openrc_status_stderr = self.execute_command("%s %s status" % (self.svc_cmd, self.name)) + self.running = "started" in openrc_status_stdout + self.crashed = "crashed" in openrc_status_stderr + # if the job status is still not known check it by response code # For reference, see: # http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html @@ -509,19 +528,44 @@ class LinuxService(Service): elif not self.enable: return - # we change argument depending on real binary used - # update-rc.d wants enable/disable while - # chkconfig wants on/off - # also, systemctl needs the argument order reversed + if self.enable_cmd.endswith("rc-update"): + (rc, out, err) = self.execute_command("%s show" % self.enable_cmd) + for line in out.splitlines(): + service_name, runlevels = line.split('|') + service_name = service_name.strip() + if service_name != self.name: + continue + runlevels = re.split(r'\s+', runlevels) + # service already enabled for the runlevel + if self.enable and self.runlevel in runlevels: + return + # service already disabled for the runlevel + elif not self.enable and self.runlevel not in runlevels: + return + break + else: + # service already disabled altogether + if not self.enable: + return + + # we change argument depending on real binary used: + # - update-rc.d and systemctl wants enable/disable + # - chkconfig wants on/off + # - rc-update wants add/delete + # also, rc-update and systemctl needs the argument order reversed if self.enable: on_off = "on" enable_disable = "enable" + add_delete = "add" else: on_off = "off" enable_disable = "disable" + add_delete = "delete" if self.enable_cmd.endswith("update-rc.d"): args = (self.enable_cmd, self.name, enable_disable) + elif self.enable_cmd.endswith("rc-update"): + args = (self.enable_cmd, add_delete, self.name + " " + self.runlevel) elif self.enable_cmd.endswith("systemctl"): args = (self.enable_cmd, enable_disable, self.name + ".service") else: @@ -542,7 +586,7 @@ class LinuxService(Service): arguments = self.arguments if self.svc_cmd: if not self.svc_cmd.endswith("systemctl"): - # SysV take the form + # SysV and OpenRC take the form svc_cmd = "%s %s" % (self.svc_cmd, self.name) else: # systemd commands take the form @@ -552,15 +596,23 @@ class LinuxService(Service): # upstart svc_cmd = "%s" % self.svc_initscript + # In OpenRC, if a service crashed, we need to reset its status to + # stopped with the zap command, before we can start it back. + if self.svc_cmd.endswith('rc-service') and self.action == 'start' and self.crashed: + self.execute_command("%s zap" % svc_cmd, daemonize=True) + if self.action is not "restart": if svc_cmd != '': - # upstart or systemd + # upstart or systemd or OpenRC rc_state, stdout, stderr = self.execute_command("%s %s %s" % (svc_cmd, self.action, arguments), daemonize=True) else: # SysV rc_state, stdout, stderr = self.execute_command("%s %s %s" % (self.action, self.name, arguments), daemonize=True) + elif self.svc_cmd.endswith('rc-service'): + # All services in OpenRC support restart. + rc_state, stdout, stderr = self.execute_command("%s %s %s" % (svc_cmd, self.action, arguments), daemonize=True) else: - # not all services support restart. Do it the hard way. + # In other systems, not all services support restart. Do it the hard way. if svc_cmd != '': # upstart or systemd rc1, stdout1, stderr1 = self.execute_command("%s %s %s" % (svc_cmd, 'stop', arguments), daemonize=True) @@ -938,6 +990,7 @@ def main(): state = dict(choices=['running', 'started', 'stopped', 'restarted', 'reloaded']), pattern = dict(required=False, default=None), enabled = dict(choices=BOOLEANS, type='bool'), + runlevel = dict(required=False, default='default'), arguments = dict(aliases=['args'], default=''), ), supports_check_mode=True diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index 9f1b439dcd4..3346b4940bf 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -41,7 +41,7 @@ package() { python2 setup.py install -O1 --root="$pkgdir" - install -D examples/ansible.cfg "$pkgdir/etc/ansible/ansbile.cfg" + install -D examples/ansible.cfg "$pkgdir/etc/ansible/ansible.cfg" install -D README.md "$pkgdir/usr/share/doc/ansible/README.md" install -D COPYING "$pkgdir/usr/share/doc/ansible/COPYING"