summaryrefslogtreecommitdiff
path: root/web_infrastructure
diff options
context:
space:
mode:
authorMichael DeHaan <michael.dehaan@gmail.com>2014-09-26 10:14:28 -0400
committerMichael DeHaan <michael.dehaan@gmail.com>2014-09-26 10:14:28 -0400
commit50f105578a07361e60f95a63da6acb5660765871 (patch)
treefd3d7c7f34b2cc149d1c0984aa0f61a249a67553 /web_infrastructure
parent38a8bad1c03aa562a92bfb3c0fa54b0ccffbaaf2 (diff)
downloadansible-modules-extras-50f105578a07361e60f95a63da6acb5660765871.tar.gz
Restructuring.
Diffstat (limited to 'web_infrastructure')
-rwxr-xr-xweb_infrastructure/ejabberd_user214
-rw-r--r--web_infrastructure/jboss140
-rw-r--r--web_infrastructure/jira347
3 files changed, 701 insertions, 0 deletions
diff --git a/web_infrastructure/ejabberd_user b/web_infrastructure/ejabberd_user
new file mode 100755
index 00000000..d8b03846
--- /dev/null
+++ b/web_infrastructure/ejabberd_user
@@ -0,0 +1,214 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2013, Peter Sprygada <sprygada@gmail.com>
+#
+# This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>.
+#
+DOCUMENTATION = '''
+---
+module: ejabberd_user
+version_added: "1.5"
+author: Peter Sprygada
+short_description: Manages users for ejabberd servers
+requirements:
+ - ejabberd with mod_admin_extra
+description:
+ - This module provides user management for ejabberd servers
+options:
+ username:
+ description:
+ - the name of the user to manage
+ required: true
+ host:
+ description:
+ - the ejabberd host associated with this username
+ required: true
+ password:
+ description:
+ - the password to assign to the username
+ required: false
+ logging:
+ description:
+ - enables or disables the local syslog facility for this module
+ required: false
+ default: false
+ choices: [ 'true', 'false', 'yes', 'no' ]
+ state:
+ description:
+ - describe the desired state of the user to be managed
+ required: false
+ default: 'present'
+ choices: [ 'present', 'absent' ]
+notes:
+ - Password parameter is required for state == present only
+ - Passwords must be stored in clear text for this release
+ - The ejabberd configuration file must include mod_admin_extra as a module.
+'''
+EXAMPLES = '''
+Example playbook entries using the ejabberd_user module to manage users state.
+
+ tasks:
+
+ - name: create a user if it does not exists
+ action: ejabberd_user username=test host=server password=password
+
+ - name: delete a user if it exists
+ action: ejabberd_user username=test host=server state=absent
+'''
+import syslog
+
+class EjabberdUserException(Exception):
+ """ Base exeption for EjabberdUser class object """
+ pass
+
+class EjabberdUser(object):
+ """ This object represents a user resource for an ejabberd server. The
+ object manages user creation and deletion using ejabberdctl. The following
+ commands are currently supported:
+ * ejabberdctl register
+ * ejabberdctl deregister
+ """
+
+ def __init__(self, module):
+ self.module = module
+ self.logging = module.params.get('logging')
+ self.state = module.params.get('state')
+ self.host = module.params.get('host')
+ self.user = module.params.get('username')
+ self.pwd = module.params.get('password')
+
+ @property
+ def changed(self):
+ """ This method will check the current user and see if the password has
+ changed. It will return True if the user does not match the supplied
+ credentials and False if it does not
+ """
+ try:
+ options = [self.user, self.host, self.pwd]
+ (rc, out, err) = self.run_command('check_password', options)
+ except EjabberdUserException, e:
+ (rc, out, err) = (1, None, "required attribute(s) missing")
+ return rc
+
+ @property
+ def exists(self):
+ """ This method will check to see if the supplied username exists for
+ host specified. If the user exists True is returned, otherwise False
+ is returned
+ """
+ try:
+ options = [self.user, self.host]
+ (rc, out, err) = self.run_command('check_account', options)
+ except EjabberdUserException, e:
+ (rc, out, err) = (1, None, "required attribute(s) missing")
+ return True if rc == 0 else False
+
+ def log(self, entry):
+ """ This method will log information to the local syslog facility """
+ if self.logging:
+ syslog.openlog('ansible-%s' % os.path.basename(__file__))
+ syslog.syslog(syslog.LOG_NOTICE, entry)
+
+ def run_command(self, cmd, options):
+ """ This method will run the any command specified and return the
+ returns using the Ansible common module
+ """
+ if not all(options):
+ raise EjabberdUserException
+
+ cmd = 'ejabberdctl %s ' % cmd
+ cmd += " ".join(options)
+ self.log('command: %s' % cmd)
+ return self.module.run_command(cmd.split())
+
+ def update(self):
+ """ The update method will update the credentials for the user provided
+ """
+ try:
+ options = [self.user, self.host, self.pwd]
+ (rc, out, err) = self.run_command('change_password', options)
+ except EjabberdUserException, e:
+ (rc, out, err) = (1, None, "required attribute(s) missing")
+ return (rc, out, err)
+
+ def create(self):
+ """ The create method will create a new user on the host with the
+ password provided
+ """
+ try:
+ options = [self.user, self.host, self.pwd]
+ (rc, out, err) = self.run_command('register', options)
+ except EjabberdUserException, e:
+ (rc, out, err) = (1, None, "required attribute(s) missing")
+ return (rc, out, err)
+
+ def delete(self):
+ """ The delete method will delete the user from the host
+ """
+ try:
+ options = [self.user, self.host]
+ (rc, out, err) = self.run_command('unregister', options)
+ except EjabberdUserException, e:
+ (rc, out, err) = (1, None, "required attribute(s) missing")
+ return (rc, out, err)
+
+def main():
+ module = AnsibleModule(
+ argument_spec = dict(
+ host=dict(default=None, type='str'),
+ username=dict(default=None, type='str'),
+ password=dict(default=None, type='str'),
+ state=dict(default='present', choices=['present', 'absent']),
+ logging=dict(default=False, type='bool')
+ ),
+ supports_check_mode = True
+ )
+
+ obj = EjabberdUser(module)
+
+ rc = None
+ result = dict()
+
+ if obj.state == 'absent':
+ if obj.exists:
+ if module.check_mode:
+ module.exit_json(changed=True)
+ (rc, out, err) = obj.delete()
+ if rc != 0:
+ module.fail_json(msg=err, rc=rc)
+
+ elif obj.state == 'present':
+ if not obj.exists:
+ if module.check_mode:
+ module.exit_json(changed=True)
+ (rc, out, err) = obj.create()
+ elif obj.changed:
+ if module.check_mode:
+ module.exit_json(changed=True)
+ (rc, out, err) = obj.update()
+ if rc is not None and rc != 0:
+ module.fail_json(msg=err, rc=rc)
+
+ if rc is None:
+ result['changed'] = False
+ else:
+ result['changed'] = True
+
+ module.exit_json(**result)
+
+
+# import module snippets
+from ansible.module_utils.basic import *
+main()
diff --git a/web_infrastructure/jboss b/web_infrastructure/jboss
new file mode 100644
index 00000000..94782356
--- /dev/null
+++ b/web_infrastructure/jboss
@@ -0,0 +1,140 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2013, Jeroen Hoekx <jeroen.hoekx@dsquare.be>
+#
+# 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/>.
+
+DOCUMENTATION = """
+module: jboss
+version_added: "1.4"
+short_description: deploy applications to JBoss
+description:
+ - Deploy applications to JBoss standalone using the filesystem
+options:
+ deployment:
+ required: true
+ description:
+ - The name of the deployment
+ src:
+ required: false
+ description:
+ - The remote path of the application ear or war to deploy
+ deploy_path:
+ required: false
+ default: /var/lib/jbossas/standalone/deployments
+ description:
+ - The location in the filesystem where the deployment scanner listens
+ state:
+ required: false
+ choices: [ present, absent ]
+ default: "present"
+ description:
+ - Whether the application should be deployed or undeployed
+notes:
+ - "The JBoss standalone deployment-scanner has to be enabled in standalone.xml"
+ - "Ensure no identically named application is deployed through the JBoss CLI"
+author: Jeroen Hoekx
+"""
+
+EXAMPLES = """
+# Deploy a hello world application
+- jboss: src=/tmp/hello-1.0-SNAPSHOT.war deployment=hello.war state=present
+# Update the hello world application
+- jboss: src=/tmp/hello-1.1-SNAPSHOT.war deployment=hello.war state=present
+# Undeploy the hello world application
+- jboss: deployment=hello.war state=absent
+"""
+
+import os
+import shutil
+import time
+
+def is_deployed(deploy_path, deployment):
+ return os.path.exists(os.path.join(deploy_path, "%s.deployed"%(deployment)))
+
+def is_undeployed(deploy_path, deployment):
+ return os.path.exists(os.path.join(deploy_path, "%s.undeployed"%(deployment)))
+
+def is_failed(deploy_path, deployment):
+ return os.path.exists(os.path.join(deploy_path, "%s.failed"%(deployment)))
+
+def main():
+ module = AnsibleModule(
+ argument_spec = dict(
+ src=dict(),
+ deployment=dict(required=True),
+ deploy_path=dict(default='/var/lib/jbossas/standalone/deployments'),
+ state=dict(choices=['absent', 'present'], default='present'),
+ ),
+ )
+
+ changed = False
+
+ src = module.params['src']
+ deployment = module.params['deployment']
+ deploy_path = module.params['deploy_path']
+ state = module.params['state']
+
+ if state == 'present' and not src:
+ module.fail_json(msg="Argument 'src' required.")
+
+ if not os.path.exists(deploy_path):
+ module.fail_json(msg="deploy_path does not exist.")
+
+ deployed = is_deployed(deploy_path, deployment)
+
+ if state == 'present' and not deployed:
+ if not os.path.exists(src):
+ module.fail_json(msg='Source file %s does not exist.'%(src))
+ if is_failed(deploy_path, deployment):
+ ### Clean up old failed deployment
+ os.remove(os.path.join(deploy_path, "%s.failed"%(deployment)))
+
+ shutil.copyfile(src, os.path.join(deploy_path, deployment))
+ while not deployed:
+ deployed = is_deployed(deploy_path, deployment)
+ if is_failed(deploy_path, deployment):
+ module.fail_json(msg='Deploying %s failed.'%(deployment))
+ time.sleep(1)
+ changed = True
+
+ if state == 'present' and deployed:
+ if module.md5(src) != module.md5(os.path.join(deploy_path, deployment)):
+ os.remove(os.path.join(deploy_path, "%s.deployed"%(deployment)))
+ shutil.copyfile(src, os.path.join(deploy_path, deployment))
+ deployed = False
+ while not deployed:
+ deployed = is_deployed(deploy_path, deployment)
+ if is_failed(deploy_path, deployment):
+ module.fail_json(msg='Deploying %s failed.'%(deployment))
+ time.sleep(1)
+ changed = True
+
+ if state == 'absent' and deployed:
+ os.remove(os.path.join(deploy_path, "%s.deployed"%(deployment)))
+ while deployed:
+ deployed = not is_undeployed(deploy_path, deployment)
+ if is_failed(deploy_path, deployment):
+ module.fail_json(msg='Undeploying %s failed.'%(deployment))
+ time.sleep(1)
+ changed = True
+
+ module.exit_json(changed=changed)
+
+# import module snippets
+from ansible.module_utils.basic import *
+main()
diff --git a/web_infrastructure/jira b/web_infrastructure/jira
new file mode 100644
index 00000000..950fc3db
--- /dev/null
+++ b/web_infrastructure/jira
@@ -0,0 +1,347 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2014, Steve Smith <ssmith@atlassian.com>
+# Atlassian open-source approval reference OSR-76.
+#
+# 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/>.
+#
+
+DOCUMENTATION = """
+module: jira
+version_added: "1.6"
+short_description: create and modify issues in a JIRA instance
+description:
+ - Create and modify issues in a JIRA instance.
+
+options:
+ uri:
+ required: true
+ description:
+ - Base URI for the JIRA instance
+
+ operation:
+ required: true
+ aliases: [ command ]
+ choices: [ create, comment, edit, fetch, transition ]
+ description:
+ - The operation to perform.
+
+ username:
+ required: true
+ description:
+ - The username to log-in with.
+
+ password:
+ required: true
+ description:
+ - The password to log-in with.
+
+ project:
+ aliases: [ prj ]
+ required: false
+ description:
+ - The project for this operation. Required for issue creation.
+
+ summary:
+ required: false
+ description:
+ - The issue summary, where appropriate.
+
+ description:
+ required: false
+ description:
+ - The issue description, where appropriate.
+
+ issuetype:
+ required: false
+ description:
+ - The issue type, for issue creation.
+
+ issue:
+ required: false
+ description:
+ - An existing issue key to operate on.
+
+ comment:
+ required: false
+ description:
+ - The comment text to add.
+
+ status:
+ required: false
+ description:
+ - The desired status; only relevant for the transition operation.
+
+ assignee:
+ required: false
+ description:
+ - Sets the assignee on create or transition operations. Note not all transitions will allow this.
+
+ fields:
+ required: false
+ description:
+ - This is a free-form data structure that can contain arbitrary data. This is passed directly to the JIRA REST API (possibly after merging with other required data, as when passed to create). See examples for more information, and the JIRA REST API for the structure required for various fields.
+
+notes:
+ - "Currently this only works with basic-auth."
+
+author: Steve Smith
+"""
+
+EXAMPLES = """
+# Create a new issue and add a comment to it:
+- name: Create an issue
+ jira: uri={{server}} username={{user}} password={{pass}}
+ project=ANS operation=create
+ summary="Example Issue" description="Created using Ansible" issuetype=Task
+ register: issue
+
+- name: Comment on issue
+ jira: uri={{server}} username={{user}} password={{pass}}
+ issue={{issue.meta.key}} operation=comment
+ comment="A comment added by Ansible"
+
+# Assign an existing issue using edit
+- name: Assign an issue using free-form fields
+ jira: uri={{server}} username={{user}} password={{pass}}
+ issue={{issue.meta.key}} operation=edit
+ assignee=ssmith
+
+# Create an issue with an existing assignee
+- name: Create an assigned issue
+ jira: uri={{server}} username={{user}} password={{pass}}
+ project=ANS operation=create
+ summary="Assigned issue" description="Created and assigned using Ansible"
+ issuetype=Task assignee=ssmith
+
+# Edit an issue using free-form fields
+- name: Set the labels on an issue using free-form fields
+ jira: uri={{server}} username={{user}} password={{pass}}
+ issue={{issue.meta.key}} operation=edit
+ args: { fields: {labels: ["autocreated", "ansible"]}}
+
+- name: Set the labels on an issue, YAML version
+ jira: uri={{server}} username={{user}} password={{pass}}
+ issue={{issue.meta.key}} operation=edit
+ args:
+ fields:
+ labels:
+ - "autocreated"
+ - "ansible"
+ - "yaml"
+
+# Retrieve metadata for an issue and use it to create an account
+- name: Get an issue
+ jira: uri={{server}} username={{user}} password={{pass}}
+ project=ANS operation=fetch issue="ANS-63"
+ register: issue
+
+- name: Create a unix account for the reporter
+ sudo: true
+ user: name="{{issue.meta.fields.creator.name}}" comment="{{issue.meta.fields.creator.displayName}}"
+
+# Transition an issue by target status
+- name: Close the issue
+ jira: uri={{server}} username={{user}} password={{pass}}
+ issue={{issue.meta.key}} operation=transition status="Done"
+"""
+
+import json
+import base64
+
+def request(url, user, passwd, data=None, method=None):
+ if data:
+ data = json.dumps(data)
+
+ # NOTE: fetch_url uses a password manager, which follows the
+ # standard request-then-challenge basic-auth semantics. However as
+ # JIRA allows some unauthorised operations it doesn't necessarily
+ # send the challenge, so the request occurs as the anonymous user,
+ # resulting in unexpected results. To work around this we manually
+ # inject the basic-auth header up-front to ensure that JIRA treats
+ # the requests as authorized for this user.
+ auth = base64.encodestring('%s:%s' % (user, passwd)).replace('\n', '')
+ response, info = fetch_url(module, url, data=data, method=method,
+ headers={'Content-Type':'application/json',
+ 'Authorization':"Basic %s" % auth})
+
+ if info['status'] not in (200, 204):
+ module.fail_json(msg=info['msg'])
+
+ body = response.read()
+
+ if body:
+ return json.loads(body)
+ else:
+ return {}
+
+def post(url, user, passwd, data):
+ return request(url, user, passwd, data=data, method='POST')
+
+def put(url, user, passwd, data):
+ return request(url, user, passwd, data=data, method='PUT')
+
+def get(url, user, passwd):
+ return request(url, user, passwd)
+
+
+def create(restbase, user, passwd, params):
+ createfields = {
+ 'project': { 'key': params['project'] },
+ 'summary': params['summary'],
+ 'description': params['description'],
+ 'issuetype': { 'name': params['issuetype'] }}
+
+ # Merge in any additional or overridden fields
+ if params['fields']:
+ createfields.update(params['fields'])
+
+ data = {'fields': createfields}
+
+ url = restbase + '/issue/'
+
+ ret = post(url, user, passwd, data)
+
+ return ret
+
+
+def comment(restbase, user, passwd, params):
+ data = {
+ 'body': params['comment']
+ }
+
+ url = restbase + '/issue/' + params['issue'] + '/comment'
+
+ ret = post(url, user, passwd, data)
+
+ return ret
+
+
+def edit(restbase, user, passwd, params):
+ data = {
+ 'fields': params['fields']
+ }
+
+ url = restbase + '/issue/' + params['issue']
+
+ ret = put(url, user, passwd, data)
+
+ return ret
+
+
+def fetch(restbase, user, passwd, params):
+ url = restbase + '/issue/' + params['issue']
+ ret = get(url, user, passwd)
+ return ret
+
+
+def transition(restbase, user, passwd, params):
+ # Find the transition id
+ turl = restbase + '/issue/' + params['issue'] + "/transitions"
+ tmeta = get(turl, user, passwd)
+
+ target = params['status']
+ tid = None
+ for t in tmeta['transitions']:
+ if t['name'] == target:
+ tid = t['id']
+ break
+
+ if not tid:
+ raise ValueError("Failed find valid transition for '%s'" % target)
+
+ # Perform it
+ url = restbase + '/issue/' + params['issue'] + "/transitions"
+ data = { 'transition': { "id" : tid },
+ 'fields': params['fields']}
+
+ ret = post(url, user, passwd, data)
+
+ return ret
+
+
+# Some parameters are required depending on the operation:
+OP_REQUIRED = dict(create=['project', 'issuetype', 'summary', 'description'],
+ comment=['issue', 'comment'],
+ edit=[],
+ fetch=['issue'],
+ transition=['status'])
+
+def main():
+
+ global module
+ module = AnsibleModule(
+ argument_spec=dict(
+ uri=dict(required=True),
+ operation=dict(choices=['create', 'comment', 'edit', 'fetch', 'transition'],
+ aliases=['command'], required=True),
+ username=dict(required=True),
+ password=dict(required=True),
+ project=dict(),
+ summary=dict(),
+ description=dict(),
+ issuetype=dict(),
+ issue=dict(aliases=['ticket']),
+ comment=dict(),
+ status=dict(),
+ assignee=dict(),
+ fields=dict(default={})
+ ),
+ supports_check_mode=False
+ )
+
+ op = module.params['operation']
+
+ # Check we have the necessary per-operation parameters
+ missing = []
+ for parm in OP_REQUIRED[op]:
+ if not module.params[parm]:
+ missing.append(parm)
+ if missing:
+ module.fail_json(msg="Operation %s require the following missing parameters: %s" % (op, ",".join(missing)))
+
+ # Handle rest of parameters
+ uri = module.params['uri']
+ user = module.params['username']
+ passwd = module.params['password']
+ if module.params['assignee']:
+ module.params['fields']['assignee'] = { 'name': module.params['assignee'] }
+
+ if not uri.endswith('/'):
+ uri = uri+'/'
+ restbase = uri + 'rest/api/2'
+
+ # Dispatch
+ try:
+
+ # Lookup the corresponding method for this operation. This is
+ # safe as the AnsibleModule should remove any unknown operations.
+ thismod = sys.modules[__name__]
+ method = getattr(thismod, op)
+
+ ret = method(restbase, user, passwd, module.params)
+
+ except Exception as e:
+ return module.fail_json(msg=e.message)
+
+
+ module.exit_json(changed=True, meta=ret)
+
+
+from ansible.module_utils.basic import *
+from ansible.module_utils.urls import *
+main()