If you are running any kind of environment with greater than 10 servers, than you need a CMDB (Configuration Management DataBase). CMDB’s are the brain of your fleet & it’s environment. You can store anything in a CMDB, but commonly the metadata in CMDB’s consists of any of the following physical & digital asset inventory, […]
Continue ReadingCategory: How To’s
Python & The Jira Rest API
Recently, while having to work a lot more in Jira than normal I got annoyed with the Jira Web GUI. So I wrote a script to do simple management of our jira issues. Here is the basic usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
(env) ➜ jira git:(master) ✗ ./jira-ctl.py usage: jira-ctl.py [-h] [-lp] [-li LIST_PROJECT_ISSUES] [-ua UPDATE_ASSIGNEE] [-ud UPDATE_DATE] [-usts UPDATE_STATUS] [-usum UPDATE_SUMMARY] optional arguments: -h, --help show this help message and exit -lp, --list-projects List all projects -li LIST_PROJECT_ISSUES, --list-issues LIST_PROJECT_ISSUES List Issues for a specific project -ua UPDATE_ASSIGNEE, --update-assignee UPDATE_ASSIGNEE Update an issues assignee format: <issue number>,<first_last> -ud UPDATE_DATE, --update-date UPDATE_DATE Update an issues due date format: <issue number >,<yyyy-mm-dd> -usts UPDATE_STATUS, --update-status UPDATE_STATUS Update an issues status format: <issue number>,'<Open|In Progress|Resolved>' -usum UPDATE_SUMMARY, --update-summary UPDATE_SUMMARY Update an issues summary format: <issue number>,'<summary>' (env) ➜ jira git:(master) ✗ |
Here is the code…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
from jira.client import JIRA import os, sys import prettytable import argparse parser = argparse.ArgumentParser() parser.add_argument('-lp', '--list-projects', action="store_true", dest="list_projects", required=False, help="List all projects") parser.add_argument('-li', '--list-issues', action="store", dest="list_project_issues", required=False, help="List Issues for a specific project") parser.add_argument('-ua', '--update-assignee', action="store", dest="update_assignee", required=False, help="Update an issues assignee format: <issue number>,<first_last>") parser.add_argument('-ud', '--update-date', action="store", dest="update_date", required=False, help="Update an issues due date format: <issue number>,<yyyy-mm-dd>") parser.add_argument('-usts', '--update-status', action="store", dest="update_status", required=False, help="Update an issues status format: <issue number>,'<Open|In Progress|Resolved>'") parser.add_argument('-usum', '--update-summary', action="store", dest="update_summary", required=False, help="Update an issues summary format: <issue number>,'<summary>'") args = parser.parse_args() def get_pass(): if os.environ.get('JIRA_PASS') == None: print "you must first export your JIRA_PASS in the shell by running: source getpass.sh" print 'or "export JIRA_PASS=<jira_password>' sys.exit() jira_password = str(os.environ['JIRA_PASS']) return jira_password def connect_jira(jira_server, jira_user, jira_password): ''' Connect to JIRA. Return None on error ''' try: #print "Connecting to JIRA: %s" % jira_server jira_options = {'server': jira_server} jira = JIRA(options=jira_options, # Note the tuple basic_auth=(jira_user, jira_password)) return jira except Exception,e: print "Failed to connect to JIRA: %s" % e return None def list_projects(): projects = jira.projects() header = ["Projects"] table = prettytable.PrettyTable(header) for project in projects: row = [str(project)] table.add_row(row) print table def list_project_issues(project): query = 'project = %s and status != Resolved order by due asc' % (project) #query = 'project = %s and status != Resolved order by due desc' % (project) #query = 'project = %s order by due desc' % (project) issues = jira.search_issues(query, maxResults=100) if issues: header = ["Ticket", "Summary", "Assignee", "Status", "Due Date"] table = prettytable.PrettyTable(header) for issue in issues: summary = issue.fields.summary st = str(issue.fields.status) dd = issue.fields.duedate assignee = issue.fields.assignee row = [issue, summary, assignee, st, dd] table.add_row(row) print table def update_issue_assignee(issue_number, assignee): issue = jira.issue(issue_number) issue.update(assignee=assignee) print "updated %s with new Assignee: %s" % (issue_number, assignee) def update_issue_duedate(issue_number, dd): issue = jira.issue(issue_number) issue.update(duedate=dd) print "updated %s with new Due Date: %s" % (issue_number, dd) def update_issue_summary(issue_number, summary): issue = jira.issue(issue_number) issue.update(summary=summary) print "updated %s with new Summary: %s" % (issue_number, summary) def update_issue_status(issue_number, status): # To figure out transitions view the following URL # https://jira.yourcompany.com/rest/api/2/issue/XXXXXX-22/transitions?expand=transitions.fields transitions = { 'Resolved': 11, 'Open': 41, 'In Progress': 21, 'Testing': 71, 'Transition': 81, 'Closed': 91, } issue = jira.issue(issue_number) jira.transition_issue(issue, transitions[status]) print "updated %s with new Status: %s" % (issue_number, status) if __name__ == "__main__": if not args: parser.print_help() else: jira_user = '<your_login>' jira_password = get_pass() jira_server = 'https://jira.yourcompany.com' jira = connect_jira(jira_server, jira_user, jira_password) if args.list_projects: list_projects() elif args.list_project_issues: project = args.list_project_issues list_project_issues(project) elif args.update_assignee: (issue_number, assignee) = args.update_assignee.split(',') update_issue_assignee(issue_number, assignee) elif args.update_date: (issue_number, dd) = args.update_date.split(',') update_issue_duedate(issue_number, dd) elif args.update_status: (issue_number, status) = args.update_status.split(',') update_issue_status(issue_number, status) elif args.update_summary: (issue_number, summary) = args.update_summary.split(',') update_issue_summary(issue_number, summary) else: parser.print_help() |
Later, I found out that there is a Jira command line […]
Continue ReadingHow To: Maximize Availability Effeciently Using AWS Availability Zones
For the TL;DR version, skip straight to the Cassandra Examples Intro & Background During my years at PayPal I was fortunate enough to be a part of a pioneering architecture & engineering team that designed & delivered a new paradigm for how we deployed & operated applications using a model that included 5 Availability Zones per […]
Continue ReadingConsul for Service Discovery
Why Service Discovery ? Service Discovery effectively replaces the process of having to manually assign or automate your own DNS entries for nodes on your network. Service Discovery aims to move even further away from treating VM’s like pets to cattle, by getting rid of the age old practice of Hostname & FQDN having contextual value. […]
Continue ReadingHow To: curl the Openstack API’s (v3 Keystone Auth)
While Openstack provides a python client(s) for interactions….
1 2 3 4 5 6 7 8 |
[root@diamond ~]# source keystonerc_tuxninja [root@diamond ~(keystone_tuxninja)]# openstack server list +--------------------------------------+-------+--------+----------------------------------------+ | ID | Name | Status | Networks | +--------------------------------------+-------+--------+----------------------------------------+ | e5b35d6a-a9ba-4714-a9e1-6361706bd047 | spin1 | ACTIVE | private_tuxlabs=10.0.0.8, 192.168.1.52 | +--------------------------------------+-------+--------+----------------------------------------+ [root@diamond ~(keystone_tuxninja)]# |
I frequently, finding myself needing to get data out of it without the pain of awk/sed’ing out the ASCII art. Thus to quickly access the raw data, we can directly query the API’s using curl & parsing JSON instead, which is much better 🙂 Authentication Before […]
Continue Reading