summaryrefslogtreecommitdiff
path: root/web_infrastructure
diff options
context:
space:
mode:
Diffstat (limited to 'web_infrastructure')
-rw-r--r--web_infrastructure/apache2_module.py15
-rw-r--r--web_infrastructure/django_manage.py8
-rw-r--r--web_infrastructure/htpasswd.py56
-rw-r--r--web_infrastructure/supervisorctl.py25
4 files changed, 84 insertions, 20 deletions
diff --git a/web_infrastructure/apache2_module.py b/web_infrastructure/apache2_module.py
index 39351482..cb43ba9b 100644
--- a/web_infrastructure/apache2_module.py
+++ b/web_infrastructure/apache2_module.py
@@ -20,6 +20,7 @@ DOCUMENTATION = '''
---
module: apache2_module
version_added: 1.6
+author: "Christian Berendt (@berendt)"
short_description: enables/disables a module of the Apache2 webserver
description:
- Enables or disables a specified module of the Apache2 webserver.
@@ -34,6 +35,7 @@ options:
choices: ['present', 'absent']
default: present
+requirements: ["a2enmod","a2dismod"]
'''
EXAMPLES = '''
@@ -49,9 +51,12 @@ import re
def _disable_module(module):
name = module.params['name']
a2dismod_binary = module.get_bin_path("a2dismod")
+ if a2dismod_binary is None:
+ module.fail_json(msg="a2dismod not found. Perhaps this system does not use a2dismod to manage apache")
+
result, stdout, stderr = module.run_command("%s %s" % (a2dismod_binary, name))
- if re.match(r'.*' + name + r' already disabled.*', stdout, re.S):
+ if re.match(r'.*\b' + name + r' already disabled', stdout, re.S):
module.exit_json(changed = False, result = "Success")
elif result != 0:
module.fail_json(msg="Failed to disable module %s: %s" % (name, stdout))
@@ -61,9 +66,12 @@ def _disable_module(module):
def _enable_module(module):
name = module.params['name']
a2enmod_binary = module.get_bin_path("a2enmod")
+ if a2enmod_binary is None:
+ module.fail_json(msg="a2enmod not found. Perhaps this system does not use a2enmod to manage apache")
+
result, stdout, stderr = module.run_command("%s %s" % (a2enmod_binary, name))
- if re.match(r'.*' + name + r' already enabled.*', stdout, re.S):
+ if re.match(r'.*\b' + name + r' already enabled', stdout, re.S):
module.exit_json(changed = False, result = "Success")
elif result != 0:
module.fail_json(msg="Failed to enable module %s: %s" % (name, stdout))
@@ -86,4 +94,5 @@ def main():
# import module snippets
from ansible.module_utils.basic import *
-main()
+if __name__ == '__main__':
+ main()
diff --git a/web_infrastructure/django_manage.py b/web_infrastructure/django_manage.py
index d71001fd..17b0534d 100644
--- a/web_infrastructure/django_manage.py
+++ b/web_infrastructure/django_manage.py
@@ -93,7 +93,7 @@ notes:
- To be able to use the migrate command, you must have south installed and added as an app in your settings
- To be able to use the collectstatic command, you must have enabled staticfiles in your settings
requirements: [ "virtualenv", "django" ]
-author: Scott Anderson
+author: "Scott Anderson (@tastychutney)"
'''
EXAMPLES = """
@@ -222,7 +222,7 @@ def main():
)
command = module.params['command']
- app_path = module.params['app_path']
+ app_path = os.path.expanduser(module.params['app_path'])
virtualenv = module.params['virtualenv']
for param in specific_params:
@@ -236,8 +236,6 @@ def main():
if not module.params[param]:
module.fail_json(msg='%s param is required for command=%s' % (param, command))
- venv = module.params['virtualenv']
-
_ensure_virtualenv(module)
cmd = "python manage.py %s" % (command, )
@@ -258,7 +256,7 @@ def main():
if module.params[param]:
cmd = '%s %s' % (cmd, module.params[param])
- rc, out, err = module.run_command(cmd, cwd=app_path)
+ rc, out, err = module.run_command(cmd, cwd=os.path.expanduser(app_path))
if rc != 0:
if command == 'createcachetable' and 'table' in err and 'already exists' in err:
out = 'Already exists.'
diff --git a/web_infrastructure/htpasswd.py b/web_infrastructure/htpasswd.py
index 4a72ea37..e567a776 100644
--- a/web_infrastructure/htpasswd.py
+++ b/web_infrastructure/htpasswd.py
@@ -46,7 +46,10 @@ options:
choices: ["apr_md5_crypt", "des_crypt", "ldap_sha1", "plaintext"]
default: "apr_md5_crypt"
description:
- - Encryption scheme to be used.
+ - Encryption scheme to be used. As well as the four choices listed
+ here, you can also use any other hash supported by passlib, such as
+ md5_crypt and sha256_crypt, which are linux passwd hashes. If you
+ do so the password file will not be compatible with Apache or Nginx
state:
required: false
choices: [ present, absent ]
@@ -66,7 +69,7 @@ notes:
- "On Debian, Ubuntu, or Fedora: install I(python-passlib)."
- "On RHEL or CentOS: Enable EPEL, then install I(python-passlib)."
requires: [ passlib>=1.6 ]
-author: Lorin Hochstein
+author: "Lorin Hochstein (@lorin)"
"""
EXAMPLES = """
@@ -74,20 +77,25 @@ EXAMPLES = """
- htpasswd: path=/etc/nginx/passwdfile name=janedoe password=9s36?;fyNp owner=root group=www-data mode=0640
# Remove a user from a password file
- htpasswd: path=/etc/apache2/passwdfile name=foobar state=absent
+# Add a user to a password file suitable for use by libpam-pwdfile
+- htpasswd: path=/etc/mail/passwords name=alex password=oedu2eGh crypt_scheme=md5_crypt
"""
import os
+import tempfile
from distutils.version import StrictVersion
try:
- from passlib.apache import HtpasswdFile
+ from passlib.apache import HtpasswdFile, htpasswd_context
+ from passlib.context import CryptContext
import passlib
except ImportError:
passlib_installed = False
else:
passlib_installed = True
+apache_hashes = ["apr_md5_crypt", "des_crypt", "ldap_sha1", "plaintext"]
def create_missing_directories(dest):
destpath = os.path.dirname(dest)
@@ -99,6 +107,10 @@ def present(dest, username, password, crypt_scheme, create, check_mode):
""" Ensures user is present
Returns (msg, changed) """
+ if crypt_scheme in apache_hashes:
+ context = htpasswd_context
+ else:
+ context = CryptContext(schemes = [ crypt_scheme ] + apache_hashes)
if not os.path.exists(dest):
if not create:
raise ValueError('Destination %s does not exist' % dest)
@@ -106,9 +118,9 @@ def present(dest, username, password, crypt_scheme, create, check_mode):
return ("Create %s" % dest, True)
create_missing_directories(dest)
if StrictVersion(passlib.__version__) >= StrictVersion('1.6'):
- ht = HtpasswdFile(dest, new=True, default_scheme=crypt_scheme)
+ ht = HtpasswdFile(dest, new=True, default_scheme=crypt_scheme, context=context)
else:
- ht = HtpasswdFile(dest, autoload=False, default=crypt_scheme)
+ ht = HtpasswdFile(dest, autoload=False, default=crypt_scheme, context=context)
if getattr(ht, 'set_password', None):
ht.set_password(username, password)
else:
@@ -117,9 +129,9 @@ def present(dest, username, password, crypt_scheme, create, check_mode):
return ("Created %s and added %s" % (dest, username), True)
else:
if StrictVersion(passlib.__version__) >= StrictVersion('1.6'):
- ht = HtpasswdFile(dest, new=False, default_scheme=crypt_scheme)
+ ht = HtpasswdFile(dest, new=False, default_scheme=crypt_scheme, context=context)
else:
- ht = HtpasswdFile(dest, default=crypt_scheme)
+ ht = HtpasswdFile(dest, default=crypt_scheme, context=context)
found = None
if getattr(ht, 'check_password', None):
@@ -198,6 +210,36 @@ def main():
if not passlib_installed:
module.fail_json(msg="This module requires the passlib Python library")
+ # Check file for blank lines in effort to avoid "need more than 1 value to unpack" error.
+ try:
+ f = open(path, "r")
+ except IOError:
+ # No preexisting file to remove blank lines from
+ f = None
+ else:
+ try:
+ lines = f.readlines()
+ finally:
+ f.close()
+
+ # If the file gets edited, it returns true, so only edit the file if it has blank lines
+ strip = False
+ for line in lines:
+ if not line.strip():
+ strip = True
+ break
+
+ if strip:
+ # If check mode, create a temporary file
+ if check_mode:
+ temp = tempfile.NamedTemporaryFile()
+ path = temp.name
+ f = open(path, "w")
+ try:
+ [ f.write(line) for line in lines if line.strip() ]
+ finally:
+ f.close()
+
try:
if state == 'present':
(msg, changed) = present(path, username, password, crypt_scheme, create, check_mode)
diff --git a/web_infrastructure/supervisorctl.py b/web_infrastructure/supervisorctl.py
index f75992b9..28f341d8 100644
--- a/web_infrastructure/supervisorctl.py
+++ b/web_infrastructure/supervisorctl.py
@@ -64,7 +64,7 @@ options:
- The desired state of program/group.
required: true
default: null
- choices: [ "present", "started", "stopped", "restarted" ]
+ choices: [ "present", "started", "stopped", "restarted", "absent" ]
supervisorctl_path:
description:
- path to supervisorctl executable
@@ -75,7 +75,9 @@ notes:
- When C(state) = I(present), the module will call C(supervisorctl reread) then C(supervisorctl add) if the program/group does not exist.
- When C(state) = I(restarted), the module will call C(supervisorctl update) then call C(supervisorctl restart).
requirements: [ "supervisorctl" ]
-author: Matt Wright, Aaron Wang <inetfuture@gmail.com>
+author:
+ - "Matt Wright (@mattupstate)"
+ - "Aaron Wang (@inetfuture) <inetfuture@gmail.com>"
'''
EXAMPLES = '''
@@ -101,7 +103,7 @@ def main():
username=dict(required=False),
password=dict(required=False),
supervisorctl_path=dict(required=False),
- state=dict(required=True, choices=['present', 'started', 'restarted', 'stopped'])
+ state=dict(required=True, choices=['present', 'started', 'restarted', 'stopped', 'absent'])
)
module = AnsibleModule(argument_spec=arg_spec, supports_check_mode=True)
@@ -183,19 +185,32 @@ def main():
if module.check_mode:
module.exit_json(changed=True)
for process_name in to_take_action_on:
- rc, out, err = run_supervisorctl(action, process_name)
+ rc, out, err = run_supervisorctl(action, process_name, check_rc=True)
if '%s: %s' % (process_name, expected_result) not in out:
module.fail_json(msg=out)
module.exit_json(changed=True, name=name, state=state, affected=to_take_action_on)
if state == 'restarted':
- rc, out, err = run_supervisorctl('update')
+ rc, out, err = run_supervisorctl('update', check_rc=True)
processes = get_matched_processes()
take_action_on_processes(processes, lambda s: True, 'restart', 'started')
processes = get_matched_processes()
+ if state == 'absent':
+ if len(processes) == 0:
+ module.exit_json(changed=False, name=name, state=state)
+
+ if module.check_mode:
+ module.exit_json(changed=True)
+ run_supervisorctl('reread', check_rc=True)
+ rc, out, err = run_supervisorctl('remove', name)
+ if '%s: removed process group' % name in out:
+ module.exit_json(changed=True, name=name, state=state)
+ else:
+ module.fail_json(msg=out, name=name, state=state)
+
if state == 'present':
if len(processes) > 0:
module.exit_json(changed=False, name=name, state=state)