mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Added search function to jira module and bugfixes (#22)
* Added search function to jira module * Added jira Operations in update function * Fixed Whitepsaces * Fixed Author header * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: John R Barker <john@johnrbarker.com> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: John R Barker <john@johnrbarker.com> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: John R Barker <john@johnrbarker.com> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: John R Barker <john@johnrbarker.com> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: John R Barker <john@johnrbarker.com> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: John R Barker <john@johnrbarker.com> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> * Added changelog framgents and update with review comments * Resolved https://github.com/ansible-collections/community.general/issues/109 * Added example for Transsition with comments * Fixed Whitespaces * Fixed whitepsaces again * Update changelogs/fragments/22-jira.yaml Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> * Added changes from Andersson007 * Update changelogs/fragments/22-jira.yaml Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> * Updated Changelog framgnets as per reviews * Update changelogs/fragments/22-jira.yaml Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> * Added max results per review request, which supports limiting number of resuted searches from the Jira API. * Removed whitespace * Removed version_added per request * Update plugins/modules/web_infrastructure/jira.py Co-Authored-By: Andrew Klychkov <aaklychkov@mail.ru> Co-authored-by: Per Abildgaard Toft <pto@netic.dk> Co-authored-by: John R Barker <john@johnrbarker.com> Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
This commit is contained in:
parent
1625429f74
commit
9d1880f29e
2 changed files with 106 additions and 9 deletions
8
changelogs/fragments/22-jira.yaml
Normal file
8
changelogs/fragments/22-jira.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- jira - added search function with support for Jira JQL (https://github.com/ansible-collections/community.general/pull/22).
|
||||||
|
- jira - added update function which can update Jira Selects etc (https://github.com/ansible-collections/community.general/pull/22).
|
||||||
|
|
||||||
|
bugfixes:
|
||||||
|
- jira - printing full error message from jira server (https://github.com/ansible-collections/community.general/pull/22).
|
||||||
|
- jira - transition issue not working (https://github.com/ansible-collections/community.general/issues/109).
|
|
@ -4,6 +4,8 @@
|
||||||
# (c) 2014, Steve Smith <ssmith@atlassian.com>
|
# (c) 2014, Steve Smith <ssmith@atlassian.com>
|
||||||
# Atlassian open-source approval reference OSR-76.
|
# Atlassian open-source approval reference OSR-76.
|
||||||
#
|
#
|
||||||
|
# (c) 2020, Per Abildgaard Toft <per@minfejl.dk> Search and update function
|
||||||
|
#
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
@ -15,7 +17,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
'supported_by': 'community'}
|
'supported_by': 'community'}
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = """
|
||||||
module: jira
|
module: jira
|
||||||
short_description: create and modify issues in a JIRA instance
|
short_description: create and modify issues in a JIRA instance
|
||||||
description:
|
description:
|
||||||
|
@ -30,7 +32,7 @@ options:
|
||||||
operation:
|
operation:
|
||||||
required: true
|
required: true
|
||||||
aliases: [ command ]
|
aliases: [ command ]
|
||||||
choices: [ create, comment, edit, fetch, transition , link ]
|
choices: [ comment, create, edit, fetch, link, search, transition, update ]
|
||||||
description:
|
description:
|
||||||
- The operation to perform.
|
- The operation to perform.
|
||||||
|
|
||||||
|
@ -106,6 +108,19 @@ options:
|
||||||
(possibly after merging with other required data, as when passed to create). See examples for more information,
|
(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.
|
and the JIRA REST API for the structure required for various fields.
|
||||||
|
|
||||||
|
jql:
|
||||||
|
required: false
|
||||||
|
description:
|
||||||
|
- Query JIRA in JQL Syntax, e.g. 'CMDB Hostname'='test.example.com'.
|
||||||
|
type: str
|
||||||
|
|
||||||
|
maxresults:
|
||||||
|
required: false
|
||||||
|
description:
|
||||||
|
- Limit the result of I(operation=search). If no value is specified, the default jira limit will be used.
|
||||||
|
- Used when I(operation=search) only, ignored otherwise.
|
||||||
|
type: int
|
||||||
|
|
||||||
timeout:
|
timeout:
|
||||||
required: false
|
required: false
|
||||||
description:
|
description:
|
||||||
|
@ -122,8 +137,10 @@ options:
|
||||||
notes:
|
notes:
|
||||||
- "Currently this only works with basic-auth."
|
- "Currently this only works with basic-auth."
|
||||||
|
|
||||||
author: "Steve Smith (@tarka)"
|
author:
|
||||||
'''
|
- "Steve Smith (@tarka)"
|
||||||
|
- "Per Abildgaard Toft (@pertoft)"
|
||||||
|
"""
|
||||||
|
|
||||||
EXAMPLES = """
|
EXAMPLES = """
|
||||||
# Create a new issue and add a comment to it:
|
# Create a new issue and add a comment to it:
|
||||||
|
@ -137,6 +154,10 @@ EXAMPLES = """
|
||||||
summary: Example Issue
|
summary: Example Issue
|
||||||
description: Created using Ansible
|
description: Created using Ansible
|
||||||
issuetype: Task
|
issuetype: Task
|
||||||
|
args:
|
||||||
|
fields:
|
||||||
|
customfield_13225: "test"
|
||||||
|
customfield_12931: '{"value": "Test"}'
|
||||||
register: issue
|
register: issue
|
||||||
|
|
||||||
- name: Comment on issue
|
- name: Comment on issue
|
||||||
|
@ -185,6 +206,22 @@ EXAMPLES = """
|
||||||
- autocreated
|
- autocreated
|
||||||
- ansible
|
- ansible
|
||||||
|
|
||||||
|
# Updating a field using operations: add, set & remove
|
||||||
|
- name: Change the value of a Select dropdown
|
||||||
|
jira:
|
||||||
|
uri: '{{ server }}'
|
||||||
|
username: '{{ user }}'
|
||||||
|
password: '{{ pass }}'
|
||||||
|
issue: '{{ issue.meta.key }}'
|
||||||
|
operation: update
|
||||||
|
args:
|
||||||
|
fields:
|
||||||
|
customfield_12931: [ {'set': {'value': 'Virtual'}} ]
|
||||||
|
customfield_13820: [ {'set': {'value':'Manually'}} ]
|
||||||
|
register: cmdb_issue
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
|
||||||
# Retrieve metadata for an issue and use it to create an account
|
# Retrieve metadata for an issue and use it to create an account
|
||||||
- name: Get an issue
|
- name: Get an issue
|
||||||
jira:
|
jira:
|
||||||
|
@ -196,6 +233,22 @@ EXAMPLES = """
|
||||||
issue: ANS-63
|
issue: ANS-63
|
||||||
register: issue
|
register: issue
|
||||||
|
|
||||||
|
# Search for an issue
|
||||||
|
# You can limit the search for specific fields by adding optional args. Note! It must be a dict, hence, lastViewed: null
|
||||||
|
- name: Search for an issue
|
||||||
|
jira:
|
||||||
|
uri: '{{ server }}'
|
||||||
|
username: '{{ user }}'
|
||||||
|
password: '{{ pass }}'
|
||||||
|
project: ANS
|
||||||
|
operation: search
|
||||||
|
maxresults: 10
|
||||||
|
jql: project=cmdb AND cf[13225]="test"
|
||||||
|
args:
|
||||||
|
fields:
|
||||||
|
lastViewed: null
|
||||||
|
register: issue
|
||||||
|
|
||||||
- name: Create a unix account for the reporter
|
- name: Create a unix account for the reporter
|
||||||
become: true
|
become: true
|
||||||
user:
|
user:
|
||||||
|
@ -223,11 +276,17 @@ EXAMPLES = """
|
||||||
issue: '{{ issue.meta.key }}'
|
issue: '{{ issue.meta.key }}'
|
||||||
operation: transition
|
operation: transition
|
||||||
status: Done
|
status: Done
|
||||||
|
args:
|
||||||
|
fields:
|
||||||
|
customfield_14321: [ {'set': {'value': 'Value of Select' }} ]
|
||||||
|
comment: [ { 'add': { 'body' : 'Test' } }]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
|
import urllib
|
||||||
from ansible.module_utils._text import to_text, to_bytes
|
from ansible.module_utils._text import to_text, to_bytes
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
@ -246,13 +305,17 @@ def request(url, user, passwd, timeout, data=None, method=None):
|
||||||
# inject the basic-auth header up-front to ensure that JIRA treats
|
# inject the basic-auth header up-front to ensure that JIRA treats
|
||||||
# the requests as authorized for this user.
|
# the requests as authorized for this user.
|
||||||
auth = to_text(base64.b64encode(to_bytes('{0}:{1}'.format(user, passwd), errors='surrogate_or_strict')))
|
auth = to_text(base64.b64encode(to_bytes('{0}:{1}'.format(user, passwd), errors='surrogate_or_strict')))
|
||||||
|
|
||||||
response, info = fetch_url(module, url, data=data, method=method, timeout=timeout,
|
response, info = fetch_url(module, url, data=data, method=method, timeout=timeout,
|
||||||
headers={'Content-Type': 'application/json',
|
headers={'Content-Type': 'application/json',
|
||||||
'Authorization': "Basic %s" % auth})
|
'Authorization': "Basic %s" % auth})
|
||||||
|
|
||||||
if info['status'] not in (200, 201, 204):
|
if info['status'] not in (200, 201, 204):
|
||||||
module.fail_json(msg=info['msg'])
|
error = json.loads(info['body'])
|
||||||
|
if error:
|
||||||
|
module.fail_json(msg=error['errorMessages'])
|
||||||
|
else:
|
||||||
|
# Fallback print body, if it cant be decoded
|
||||||
|
module.fail_json(msg=info['body'])
|
||||||
|
|
||||||
body = response.read()
|
body = response.read()
|
||||||
|
|
||||||
|
@ -320,12 +383,34 @@ def edit(restbase, user, passwd, params):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def update(restbase, user, passwd, params):
|
||||||
|
data = {
|
||||||
|
"update": params['fields'],
|
||||||
|
}
|
||||||
|
url = restbase + '/issue/' + params['issue']
|
||||||
|
|
||||||
|
ret = put(url, user, passwd, params['timeout'], data)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def fetch(restbase, user, passwd, params):
|
def fetch(restbase, user, passwd, params):
|
||||||
url = restbase + '/issue/' + params['issue']
|
url = restbase + '/issue/' + params['issue']
|
||||||
ret = get(url, user, passwd, params['timeout'])
|
ret = get(url, user, passwd, params['timeout'])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def search(restbase, user, passwd, params):
|
||||||
|
url = restbase + '/search?jql=' + urllib.request.pathname2url(params['jql'])
|
||||||
|
if params['fields']:
|
||||||
|
fields = params['fields'].keys()
|
||||||
|
url = url + '&fields=' + '&fields='.join([urllib.request.pathname2url(f) for f in fields])
|
||||||
|
if params['maxresults']:
|
||||||
|
url = url + '&maxResults=' + str(params['maxresults'])
|
||||||
|
ret = get(url, user, passwd, params['timeout'])
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def transition(restbase, user, passwd, params):
|
def transition(restbase, user, passwd, params):
|
||||||
# Find the transition id
|
# Find the transition id
|
||||||
turl = restbase + '/issue/' + params['issue'] + "/transitions"
|
turl = restbase + '/issue/' + params['issue'] + "/transitions"
|
||||||
|
@ -344,7 +429,7 @@ def transition(restbase, user, passwd, params):
|
||||||
# Perform it
|
# Perform it
|
||||||
url = restbase + '/issue/' + params['issue'] + "/transitions"
|
url = restbase + '/issue/' + params['issue'] + "/transitions"
|
||||||
data = {'transition': {"id": tid},
|
data = {'transition': {"id": tid},
|
||||||
'fields': params['fields']}
|
'update': params['fields']}
|
||||||
|
|
||||||
ret = post(url, user, passwd, params['timeout'], data)
|
ret = post(url, user, passwd, params['timeout'], data)
|
||||||
|
|
||||||
|
@ -369,9 +454,11 @@ def link(restbase, user, passwd, params):
|
||||||
OP_REQUIRED = dict(create=['project', 'issuetype', 'summary'],
|
OP_REQUIRED = dict(create=['project', 'issuetype', 'summary'],
|
||||||
comment=['issue', 'comment'],
|
comment=['issue', 'comment'],
|
||||||
edit=[],
|
edit=[],
|
||||||
|
update=[],
|
||||||
fetch=['issue'],
|
fetch=['issue'],
|
||||||
transition=['status'],
|
transition=['status'],
|
||||||
link=['linktype', 'inwardissue', 'outwardissue'])
|
link=['linktype', 'inwardissue', 'outwardissue'],
|
||||||
|
search=['jql'])
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -380,7 +467,7 @@ def main():
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
uri=dict(required=True),
|
uri=dict(required=True),
|
||||||
operation=dict(choices=['create', 'comment', 'edit', 'fetch', 'transition', 'link'],
|
operation=dict(choices=['create', 'comment', 'edit', 'update', 'fetch', 'transition', 'link', 'search'],
|
||||||
aliases=['command'], required=True),
|
aliases=['command'], required=True),
|
||||||
username=dict(required=True),
|
username=dict(required=True),
|
||||||
password=dict(required=True, no_log=True),
|
password=dict(required=True, no_log=True),
|
||||||
|
@ -396,6 +483,8 @@ def main():
|
||||||
linktype=dict(),
|
linktype=dict(),
|
||||||
inwardissue=dict(),
|
inwardissue=dict(),
|
||||||
outwardissue=dict(),
|
outwardissue=dict(),
|
||||||
|
jql=dict(),
|
||||||
|
maxresults=dict(type='int'),
|
||||||
timeout=dict(type='float', default=10),
|
timeout=dict(type='float', default=10),
|
||||||
validate_certs=dict(default=True, type='bool'),
|
validate_certs=dict(default=True, type='bool'),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue