Exemplo n.º 1
0
def push_event_hook():
    push_event = request.json
    app.logger.debug(push_event)
    user_name = push_event['user_name']
    repo_name = push_event['repository']['name']
    repo_url = push_event['repository']['url']
    repo_homepage = push_event['repository']['homepage']
    refspec = push_event['ref']
    app.logger.debug('Received push event by %s in branch %s on repository %s',
                     user_name, refspec, repo_url)

    for commit in push_event['commits']:
        app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'],
                         commit['author']['name'], commit['author']['email'],
                         commit['url'])
        commit_time = dateutil.parser.parse(commit['timestamp'])
        issues = re.findall(app.config['REGEX'], commit['message'],
                            re.MULTILINE)
        if not issues:
            app.logger.debug(
                '''Didn't find any referenced issues in commit %s''',
                commit['id'])
        else:
            app.logger.debug('Found %d referenced issues in commit %s',
                             len(issues), commit['id'])
            yt = Connection(app.config['YOUTRACK_URL'],
                            app.config['YOUTRACK_USERNAME'],
                            app.config['YOUTRACK_PASSWORD'])

            user_login = get_user_login(yt, commit['author']['email'])
            if user_login is None:
                app.logger.warn(
                    "Couldn't find user with email address %s. Using default user.",
                    commit['author']['email'])
                default_user = yt.getUser(app.config['DEFAULT_USER'])
                user_login = default_user['login']

            for issue_id in issues:
                app.logger.debug('Processing reference to issue %s', issue_id)
                try:
                    yt.getIssue(issue_id)
                    comment_string = 'Commit [%(url)s %(id)s] on branch %(refspec)s in [%(repo_homepage)s %(repo_name)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % {
                        'url': commit['url'],
                        'id': commit['id'],
                        'author': commit['author']['name'],
                        'date': str(commit_time),
                        'message': commit['message'],
                        'repo_homepage': repo_homepage,
                        'repo_name': repo_name,
                        'refspec': refspec
                    }
                    app.logger.debug(comment_string)
                    yt.executeCommand(issueId=issue_id,
                                      command='comment',
                                      comment=comment_string.encode('utf-8'),
                                      run_as=user_login.encode('utf-8'))
                except YouTrackException:
                    app.logger.warn("Couldn't find issue %s", issue_id)
    return Response('Push event processed. Thanks!', mimetype='text/plain')
Exemplo n.º 2
0
def push_event_hook(room=None):
    push_event = request.json
    app.logger.debug(push_event)
    app.logger.debug("slack_room:%s" % room)

    # process mergerequest
    if 'object_kind' in push_event and push_event['object_kind'] == 'merge_request':
        obj = push_event['object_attributes']
        user = push_event['user']
        slack = Slacker(app.config['SLACK_TOKEN'])
        url = "%s/%s/%s/merge_requests/%d" % (app.config['GITLAB_HOME'], obj['target']['namespace'], obj['target']['name'], obj['iid'])
        print url
        event = "Pull Request(%s): %s - %s\n%s" % (obj['state'], url, obj['title'], obj['description'])
        slack.chat.post_message('#%s' % room, event, username=user['username'], icon_url=user['avatar_url'])
        return Response('Push event processed. Thanks!', mimetype='text/plain')

    user_name = push_event['user_name']
    repo_name = push_event['repository']['name']
    repo_url = push_event['repository']['url']
    repo_homepage = push_event['repository']['homepage']
    refspec = push_event['ref']
    app.logger.debug('Received push event by %s in branch %s on repository %s', user_name, refspec, repo_url)

    for commit in push_event['commits']:
        app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'], commit['author']['name'], commit['author']['email'], commit['url'])
        commit_time = dateutil.parser.parse(commit['timestamp'])
        issues = re.findall(app.config['REGEX'], commit['message'], re.MULTILINE)
        if not issues:
            app.logger.debug('''Didn't find any referenced issues in commit %s''', commit['id'])
        else:
            app.logger.debug('Found %d referenced issues in commit %s', len(issues), commit['id'])
            yt = Connection(app.config['YOUTRACK_URL'], app.config['YOUTRACK_USERNAME'], app.config['YOUTRACK_PASSWORD'])

            user_login = get_user_login(yt, commit['author']['email'])
            if user_login is None:
                app.logger.warn("Couldn't find user with email address %s. Using default user.", commit['author']['email'])
                default_user = yt.getUser(app.config['DEFAULT_USER'])
                user_login = default_user['login']

            for issue_id in issues:
                app.logger.debug('Processing reference to issue %s', issue_id)
                try:
                    yt.getIssue(issue_id)
                    comment_string = 'Commit [%(url)s %(id)s] on branch %(refspec)s in [%(repo_homepage)s %(repo_name)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % {'url': commit['url'], 'id': commit['id'], 'author': commit['author']['name'], 'date': str(commit_time), 'message': commit['message'], 'repo_homepage': repo_homepage, 'repo_name': repo_name, 'refspec': refspec}
                    app.logger.debug(comment_string)
                    yt.executeCommand(issueId=issue_id, command='comment', comment=comment_string.encode('utf-8'),
                                      run_as=user_login.encode('utf-8'))
                except YouTrackException:
                    app.logger.warn("Couldn't find issue %s", issue_id)
    return Response('Push event processed. Thanks!', mimetype='text/plain')
class ConnectionTest(unittest.TestCase):
    def setUp(self):
        #self.con = Connection('http://teamsys.intellij.net', 'resttest', 'resttest')
        self.con = Connection("http://localhost:8081", "root", "root")

    def test_getProject(self):
        p = self.con.getProject('SB')
        self.assertEqual(p.id, 'SB')
        self.assertEqual(p.name, 'Sandbox')

    def test_getSubsystems(self):
        subsystems = self.con.getSubsystems('SB')
        default = [s for s in subsystems if s.isDefault][0]
        self.assertTrue(default is not None)

    def test_getIssue(self):
        i = self.con.getIssue('SB-1')
        self.assertEqual(i.id, 'SB-1')
        self.assertEqual(i.numberInProject, '1')
        self.assertEqual(i.projectShortName, 'SB')

    def test_createIssue(self):
        i = self.con.createIssue('SB', 'resttest', 'Test issue',
                                 'Test description', '2', 'Bug', 'First',
                                 'Open', '', '', '')
        self.assertEqual(i.projectShortName, 'SB')
        self.assertEqual(i.priority, '2')
        self.assertEqual(i.type, 'Bug')
        self.assertEqual(i.subsystem, 'First')

    def test_createIssueAttachment(self):
        i = self.con.createIssue('SB', 'resttest', 'For attachmkents test',
                                 'Test description', '2', 'Bug', 'First',
                                 'Open', '', '', '')
        fname = 'connection_test.py'
        content = open(fname)
        self.con.createAttachment(i.id, fname, content)
        self.assertEqual(fname, self.con.getAttachments(i.id)[0].name)

    def test_createAndDeleteSubsystem(self):
        name = 'Test Subsystem [' + str(random.random()) + "]"
        self.con.createSubsystemDetailed('SB', name, False, 'resttest')
        s = self.con.getSubsystem('SB', name)
        self.assertEqual(s.name, name)
        self.assertEqual(s.isDefault, 'false')
        #todo: uncomment when fix deployed to teamsys
        #self.assertEqual(s.defaultAssignee, 'resttest')
        self.con.deleteSubsystem('SB', name)

    def test_importIssues(self):
        issues = self.con.getIssues("A", "", 0, 10)
        for issue in issues:
            if hasattr(issue, "Assignee"):
                issue["assigneeName"] = issue["Assignee"]
                del issue.Assignee
        self.con.importIssues("B", "assignees", issues)
Exemplo n.º 4
0
def recibir_horas(bot, update, user_data):
    try:
        duracion = int(update.message.text)
        logger.info(duracion)
    except ValueError:
        logger.error("No entiendo el número!")
        update.message.reply_text("No entiendo el número!")
        return RECIBIR

    work_item = {
        'duration': duracion,
        'date': str(datetime.now()),
        'worktype': user_data['tipo_nom'],
        'description': 'bot :)'
    }
    work_item = dotdict(work_item)
    logger.info(work_item)

    try:
        connection = Connection(user_data['host']['host'],
                                user_data['host']['username'],
                                user_data['host']['pass'])
        connection.createWorkItem(user_data['issue'], work_item)
        logger.info('Guardar tiempo {} {}'.format(user_data['issue'],
                                                  duracion))

        issue = connection.getIssue(user_data['issue'])

        keyboard = []
        if user_data['tipo_tarea'] == '#Unresolved':
            keyboard.append([
                InlineKeyboardButton('Marcar como cerrada',
                                     callback_data='issue_estado_cerrar')
            ])
        else:
            keyboard.append([
                InlineKeyboardButton('Marcar como en progreso',
                                     callback_data='issue_estado_en_progreso')
            ])
        keyboard.append([
            InlineKeyboardButton('Dejar como {}'.format(issue['State']),
                                 callback_data='terminar')
        ])
        reply_markup = InlineKeyboardMarkup(keyboard,
                                            resize_keyboard=True,
                                            one_time_keyboard=True)
        update.message.reply_text("Gracias amego! Y ahora?",
                                  reply_markup=reply_markup)
        return CONFIRMAR

    except Exception as e:
        logger.error(e)
        update.message.reply_text("No eh!")

    return ConversationHandler.END
    def __init__(self, host, user, password, api_key):
        connection = Connection(url=host, api_key=api_key)

        # get one issue
        issue = connection.getIssue('PI-1000')

        # get first 10 issues in project JT for query 'for: me #unresolved'
        issues = connection.getIssues(
            'pi', '#Resolved Fixed in build: {Next Build}', 0, 10)
        for issue in issues:
            print(issue)
class ConnectionTest(unittest.TestCase):

    def setUp(self):
        #self.con = Connection('http://teamsys.intellij.net', 'resttest', 'resttest')
        self.con = Connection("http://localhost:8081", "root", "root")
    def test_getProject(self):
        p = self.con.getProject('SB')
        self.assertEqual(p.id, 'SB')
        self.assertEqual(p.name, 'Sandbox')

    def test_getSubsystems(self):
        subsystems = self.con.getSubsystems('SB')
        default = [s for s in subsystems if s.isDefault][0]
        self.assertTrue(default is not None)        

    def test_getIssue(self):
        i = self.con.getIssue('SB-1')
        self.assertEqual(i.id, 'SB-1')
        self.assertEqual(i.numberInProject, '1')
        self.assertEqual(i.projectShortName, 'SB')

    def test_createIssue(self):
        i = self.con.createIssue('SB', 'resttest', 'Test issue', 'Test description', '2', 'Bug', 'First', 'Open', '', '', '')
        self.assertEqual(i.projectShortName, 'SB')
        self.assertEqual(i.priority, '2')
        self.assertEqual(i.type, 'Bug')
        self.assertEqual(i.subsystem, 'First')

    def test_createIssueAttachment(self):
        i = self.con.createIssue('SB', 'resttest', 'For attachmkents test', 'Test description', '2', 'Bug', 'First', 'Open', '', '', '')
        fname = 'connection_test.py'
        content = open(fname)
        self.con.createAttachment(i.id, fname, content)
        self.assertEqual(fname, self.con.getAttachments(i.id)[0].name)

    def test_createAndDeleteSubsystem(self):
        name = 'Test Subsystem [' + str(random.random()) + "]"
        self.con.createSubsystemDetailed('SB', name, False, 'resttest')
        s = self.con.getSubsystem('SB', name)
        self.assertEqual(s.name, name)
        self.assertEqual(s.isDefault, 'false')
        #todo: uncomment when fix deployed to teamsys
        #self.assertEqual(s.defaultAssignee, 'resttest')
        self.con.deleteSubsystem('SB', name)

    def test_importIssues(self):
        issues = self.con.getIssues("A", "", 0, 10)
        for issue in issues:
            if hasattr(issue, "Assignee"):
                issue["assigneeName"] = issue["Assignee"]
                del issue.Assignee
        self.con.importIssues("B", "assignees", issues)
Exemplo n.º 7
0
def push_event_hook():
    push_event = request.json
    app.logger.debug(push_event)
    user_name = push_event['user_name']
    repo_name = push_event['repository']['name']
    repo_url = push_event['repository']['url']
    repo_homepage = push_event['repository']['homepage']
    refspec = push_event['ref']
    app.logger.debug('Received push event by %s in branch %s on repository %s', user_name, refspec, repo_url)

    for commit in push_event['commits']:
        app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'], commit['author']['name'], commit['author']['email'], commit['url'])
        commit_time = dateutil.parser.parse(commit['timestamp'])
        issues = re.findall(app.config['REGEX'], commit['message'], re.MULTILINE)
        if not issues:
            app.logger.debug('''Didn't find any referenced issues in commit %s''', commit['id'])
        else:
            app.logger.debug('Found %d referenced issues in commit %s', len(issues), commit['id'])
            yt = Connection(app.config['YOUTRACK_URL'], app.config['YOUTRACK_USERNAME'], app.config['YOUTRACK_PASSWORD'])

            user_login = get_user_login(yt, commit['author']['email'])
            if user_login is None:
                app.logger.warn("Couldn't find user with email address %s. Using default user.", commit['author']['email'])
                default_user = yt.getUser(app.config['DEFAULT_USER'])
                user_login = default_user['login']

            for issue_id in issues:
                app.logger.debug('Processing reference to issue %s', issue_id)
                try:
                    yt.getIssue(issue_id)
                    comment_string = 'Commit [%(url)s %(id)s] on branch %(refspec)s in [%(repo_homepage)s %(repo_name)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % {'url': commit['url'], 'id': commit['id'], 'author': commit['author']['name'], 'date': str(commit_time), 'message': commit['message'], 'repo_homepage': repo_homepage, 'repo_name': repo_name, 'refspec': refspec}
                    app.logger.debug(comment_string)
                    yt.executeCommand(issueId=issue_id, command='comment', comment=comment_string.encode('utf-8'),
                                      run_as=user_login.encode('utf-8'))
                except YouTrackException:
                    app.logger.warn("Couldn't find issue %s", issue_id)
    return Response('Push event processed. Thanks!', mimetype='text/plain')
Exemplo n.º 8
0
class YtClient(object):

    def __init__(self, server, username, password):
        self.logger = LoggerFactory.getLogger("com.xebialabs.yourtrack.Server")
        if server is None:
            sys.exit("No server provided.")
        if username is not None:
            youtrackUsername = username
        else:
            youtrackUsername = server['username']
        if password is not None:
            youtrackPassword = password
        else:
            youtrackPassword = server['password']

        if server['token'] is not None:
            # authentication request with permanent token
            self.youtrack = YouTrack(server['url'], token=server['token'])
        else:
            # authentication with username and password
            self.youtrack = YouTrack(server['url'], login=youtrackUsername, password=youtrackPassword)

    def getIssue(self, issueId):
        return self.youtrack.getIssue(issueId)

    def getAllIssues(self, query, withFields):
        self.logger.debug("getAllIssues")
        self.logger.debug("Query = %s" % query)
        self.logger.debug("Fields = %s" % withFields)
        return self.youtrack.getAllIssues(filter=query, withFields=withFields)

    def updateIssuesByQuery(self, query, fieldsToUpdate, comment):
        command = ""
        for key in fieldsToUpdate:
            command += key + " " + fieldsToUpdate[key]
        foundIssues = self.youtrack.getAllIssues(filter=query, withFields=[])
        for issue in foundIssues:
            self.youtrack.executeCommand(issue['id'], command, comment)

    def getIssuesByQuery(self, query, fieldList=[]):
        self.logger.debug("getIssuesByQuery")
        return self.youtrack.getAllIssues(filter=query, withFields=[])
Exemplo n.º 9
0
def receive_hook():
    payload = request.json
    user_name = payload['user_name']
    repo_url = payload['repository']['url']
    app.logger.debug('Received payload for a push by %s on repository %s', user_name, repo_url)

    for commit in payload['commits']:
        app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'], commit['author']['name'], commit['author']['email'], commit['url'])
        commit_time = dateutil.parser.parse(commit['timestamp'])
        refs = re.findall(app.config['REGEX'], commit['message'], re.MULTILINE)
        if not refs:
            app.logger.info('''Didn't find any referenced issues in commit %s''', commit['id'])
        else:
            app.logger.info('Found %d referenced issues in commit %s', len(refs), commit['id'])

            yt = Connection(app.config['YOUTRACK_URL'], app.config['YOUTRACK_USERNAME'], app.config['YOUTRACK_PASSWORD'])

            user = app.config['DEFAULT_USER']
            users = yt.getUsers({ 'q': commit['author']['email'] })
            if not users:
                app.logger.warn('''Couldn't find user with email address %s. Using default user.''', commit['author']['email'])
            elif len(users) > 1:
                app.logger.warn('''Found more than one user with email address %s. Using default user.''', commit['author']['email'])
            else:
                user = users[0]['login']

            for ref in refs:
                app.logger.info('Processing reference to issue %s', ref)
                try:
                    issue = yt.getIssue(ref)
                    comment_string = 'Commit [%(url)s %(id)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % {'url': commit['url'], 'id': commit['id'], 'author': commit['author']['name'], 'date': str(commit_time), 'message': commit['message']}
                    app.logger.debug(comment_string)
                    yt.executeCommand(issueId=ref, command='comment', comment=comment_string, run_as=user)
                except YouTrackException:
                    app.logger.warn('''Couldn't find issue %s''', ref)
    return Response('Payload processed. Thanks!', mimetype='text/plain')
Exemplo n.º 10
0
from youtrack.connection import Connection as YouTrack

from config.settings import YOUTRACK_TOKEN

yt = YouTrack('https://jingyi.myjetbrains.com/youtrack', token=YOUTRACK_TOKEN)

issue = yt.getIssue('FEJIS-4')

print(issue)
print(issue)
Exemplo n.º 11
0
        redmine_users = get_redmine_users()
        redmine_trackers = get_redmine_trackers()
        redmine_statuses = get_redmine_statuses()
        redmine_priorities = get_redmine_priorities()
        redmine_versions = get_redmine_project_versions()
        redmine_custom_fields = get_redmine_custom_fields()
    except Exception as e:
        print e
        sys.exit(0)

    issues_dict = {}

    print "==========Copying from YouTrack to Redmine=========="
    for issue in issues_list:
        issue_id = issue.id
        youtrack_issue = youtrack.getIssue(id=issue_id)
        print "Processing " + youtrack_issue.id + " " + youtrack_issue.summary
        redmine_issue = redmine.issue.new()
        redmine_issue.project_id = redmine.project.get(REDMINE_PROJECT).id
        set_assignee()
        sey_subject()
        set_type()
        set_status()
        set_estimation()
        set_storypoints()
        set_planfixdate()
        set_affected_versions()
        set_description()
        add_attachments()
        redmine_issue.save()
        add_comments()
    try :
        source = Connection(source_url, source_login, source_password)
        print "Connected to source url [%s]" % source_url
    except Exception, ex :
        print "Failed to connect to source url [%s] with login/password [%s/%s]" % (source_url, source_login, source_password)
        raise ex

    try :
        target.getProject(target_project_id)
    except Exception, ex:
        print "Can't connect to target project [%s]" % target_project_id
        raise ex

    #twin issues
    try :
        source_issue = source.getIssue(source_issue_id)
    except Exception, ex :
        print "Failed to get issue [%s]" % source_issue_id
        raise ex

    target_issue = Issue()

    #import users if needed
    name_fields = ["reporeterName", "assigneeName", "updaterName"]
    for field in name_fields :
        if (field in source_issue) :
            check_user(source_issue[field], source, target)

    target_issue.numberInProject = str(get_new_issue_id(target_project_id, target))

    #check subsystem
Exemplo n.º 13
0
        redmine_users = get_redmine_users()
        redmine_trackers = get_redmine_trackers()
        redmine_statuses = get_redmine_statuses()
        redmine_priorities = get_redmine_priorities()
        redmine_versions = get_redmine_project_versions()
        redmine_custom_fields = get_redmine_custom_fields()
    except Exception as e:
        print e
        sys.exit(0)

    issues_dict = {}

    print "==========Copying from YouTrack to Redmine=========="
    for issue in issues_list:
        issue_id = issue.id
        youtrack_issue = youtrack.getIssue(id=issue_id)
        print "Processing " + youtrack_issue.id + " " + youtrack_issue.summary
        redmine_issue = redmine.issue.new()
        redmine_issue.project_id = redmine.project.get(REDMINE_PROJECT).id
        set_assignee()
        sey_subject()
        set_type()
        set_status()
        set_estimation()
        set_storypoints()
        set_planfixdate()
        set_affected_versions()
        set_description()
        add_attachments()
        redmine_issue.save()
        add_comments()
Exemplo n.º 14
0
def issues(request):
    yt = YouTrack(settings.YOUTRACK_BASE_URL, token=settings.YOUTRACK_TOKEN)
    issue = yt.getIssue("2-119920")
    return Response(issue.to_dict())
def do_move(source_url, source_login, source_password,
            target_url, target_login, target_password, source_issue_id, target):
    print("source_url       : " + source_url)
    print("source_login     : "******"source_password  : "******"target_url       : " + target_url)
    print("target_login     : "******"target_password  : "******"source_id        : " + source_issue_id)

    if target.find('-') > -1:
        print("target_id        : " + target)
        target_project_id, target_issue_number = target.split('-')
    else:
        print("target_project_id: " + target)
        target_project_id = target
        target_issue_number = None

    # connecting
    try:
        target = Connection(target_url, target_login, target_password)
        print("Connected to target url [%s]" % target_url)
    except Exception as ex:
        print("Failed to connect to target url [%s] with login/password [%s/%s]"
              % (target_url, target_login, target_password))
        raise ex

    try:
        source = Connection(source_url, source_login, source_password)
        print("Connected to source url [%s]" % source_url)
    except Exception as ex:
        print("Failed to connect to source url [%s] with login/password [%s/%s]"
              % (source_url, source_login, source_password))
        raise ex

    try:
        target.getProject(target_project_id)
    except Exception as ex:
        print("Can't connect to target project [%s]" % target_project_id)
        raise ex

    # twin issues
    try:
        source_issue = source.getIssue(source_issue_id)
    except Exception as ex:
        print("Failed to get issue [%s]" % source_issue_id)
        raise ex

    target_issue = Issue()

    # import users if needed
    name_fields = ["reporterName", "assigneeName", "updaterName"]
    for field in name_fields:
        if field in source_issue:
            check_user(source_issue[field], source, target)

    if not target_issue_number:
        target_issue_number = str(get_new_issue_id(target_project_id, target))
    target_issue.numberInProject = target_issue_number

    # check subsystem
    target_subsystem = None
    try:
        target.getSubsystem(target_project_id, source_issue.subsystem)
        target_subsystem = source_issue.subsystem
    except (YouTrackException, AttributeError):
        pass
    target_issue.subsystem = target_subsystem
    for field in PREDEFINED_FIELDS:
        if field in source_issue:
            target_issue[field] = source_issue[field]

    if "Type" in source_issue:
        target_issue.type = source_issue["Type"]
    elif "type" in source_issue:
        target_issue.type = source_issue["type"]
    else:
        target_issue.type = "Bug"

    # convert custom field
    target_cfs = target.getProjectCustomFields(target_project_id)
    for cf in target_cfs:
        cf_name = cf.name
        if cf_name in source_issue:
            target_issue[cf_name] = source_issue[cf_name]

    # comments
    target_issue.comments = source_issue.getComments()
    for comment in target_issue.comments:
        check_user(comment.author, source, target)

    # import issue
    print(target.importIssues(
        target_project_id,
        "",
        [target_issue]))

    # attachments
    for attachment in source_issue.getAttachments():
        check_user(attachment.authorLogin, source, target)
        attachment.url = attachment.url.replace(source_url, "")
        target.createAttachmentFromAttachment(
            "%s-%s" % (target_project_id, target_issue.numberInProject),
            attachment)

    # work items
    if get_time_tracking_state(
            source, target, source_issue_id.split('-')[0],
            target_project_id):
        workitems = source.getWorkItems(source_issue_id)
        if workitems:
            existing_workitems = dict()
            target_workitems = target.getWorkItems(
                target_project_id + '-' + target_issue_number)
            if target_workitems:
                for w in target_workitems:
                    _id = '%s\n%s\n%s' % (w.date, w.authorLogin, w.duration)
                    if hasattr(w, 'description'):
                        _id += '\n%s' % w.description
                    existing_workitems[_id] = w
            new_workitems = []
            for w in workitems:
                _id = '%s\n%s\n%s' % (w.date, w.authorLogin, w.duration)
                if hasattr(w, 'description'):
                    _id += '\n%s' % w.description
                if _id not in existing_workitems:
                    new_workitems.append(w)
            if new_workitems:
                print("Process workitems for issue [ " + source_issue_id + "]")
                try:
                    for w in new_workitems:
                        check_user(w.authorLogin, source, target)
                    target.importWorkItems(
                        target_project_id + '-' + target_issue_number,
                        new_workitems)
                except YouTrackException as e:
                    print("Failed to import workitems: " + str(e))

    # links
    link_importer = LinkImporter(target)
    links2import = source_issue.getLinks()
    link_importer.collectLinks(links2import)
    link_importer.addAvailableIssue(source_issue)
    for l in links2import:
        link_importer.addAvailableIssue(source.getIssue(l.source))
        link_importer.addAvailableIssue(source.getIssue(l.target))
    link_importer.importCollectedLinks()
def Main(sendTo, subject, yamlMessage):
    """
    Workflow Zabbix-YouTrack
    :param sendTo: URL to Youtrack (ex. https://youtrack.example.com)
    :param subject: subject from Zabbix Action
    :param yamlMessage: message from Zabbix Action
    :return:
    """

    # ----- Use below example yamlMessage to debug -----
#     yamlMessage = """Name: 'Test Zabbix-YT workflow, ignore it'
# Text: 'Agent ping (server:agent.ping()): DOWN (1) '
# Hostname: 'server.exmpale.ru'
# Status: "OK"
# Severity: "High"
# EventID: "96976"
# TriggerID: "123456789012" """

    messages = yaml.load(yamlMessage)

    # ----- START Issue parameters -----
    # Correspondence between the YouTrackPriority and ZabbixSeverity
    # Critical >= High
    # Normal < High

    ytPriority = 'Normal'
    if messages['Severity'] == 'Disaster' or messages['Severity'] == 'High':
        ytPriority = 'Critical'

    ytName = "{} ZabbixTriggerID::{}".format(messages['Name'], messages['TriggerID'])
    # ----- END Issue parameters -----

    # ----- START Youtrack Issue description -----
    # Search link to other issue
    searchString = "Hostname: '{}'".format(messages['Hostname'])
    linkToHostIssue = "{youtrack}/issues/{projectname}?q={query}".format(
        youtrack=sendTo,
        projectname=YT_PROJECT_NAME,
        query=urllib.parse.quote(searchString, safe='')
    )

    issueDescription = """
{ytName}
-----
{yamlMessage}
-----
- [https://zabbix.example.com/zabbix.php?action=dashboard.view Zabbix Dashboard]
- Show [{linkToHostIssue} all issue for *this host*]
""".format(
        ytName=ytName,
        yamlMessage=yamlMessage,
        linkToHostIssue=linkToHostIssue, )

    # ----- END Youtrack Issue description -----

    # ----- START Youtrack current week -----

    # Create connect to Youtrack API
    connection = Connection(sendTo, YT_USER, YT_PASSWORD)

    # Get current week in YT format (Sprint planned)
    version = connection.getAllBundles('version')

    for fixVersion in version[0].values:
        if fixVersion['archived'] == False and fixVersion['released'] == False:
            fixVersionWeek = fixVersion['name']
            break
    # ----- END Youtrack current week -----

    # ----- START Youtrack get or create issue -----
    # Get issue if exist
    # Search for TriggerID
    createNewIssue = False

    logger.debug("Get issue with text '{}'".format(messages['TriggerID']))
    issue = connection.getIssues(YT_PROJECT_NAME,
                                 "ZabbixTriggerID::{}".format(messages['TriggerID']),
                                 0,
                                 1)


    if len(issue) == 0:
        createNewIssue = True

    else:
        # if issue contains TriggerID in summary, then it's good issue
        # else create new issue, this is bad issue, not from Zabbix
        if "ZabbixTriggerID::{}".format(messages['TriggerID']) in issue[0]['summary']:
            issueId = issue[0]['id']
            issue = connection.getIssue(issueId)
        else:
            createNewIssue = True

    # Create new issue
    if createNewIssue:
        logger.debug("Create new issue because it is not exist")
        issue = connection.createIssue(YT_PROJECT_NAME,
                                       'Unassigned',
                                       ytName,
                                       issueDescription,
                                       priority=ytPriority,
                                       subsystem=YT_SUBSYSTEM,
                                       type=YT_TYPE,
                                       )
        time.sleep(3)

        # Parse ID for new issue
        result = re.search(r'(CM-\d*)', issue[0]['location'])
        issueId = result.group(0)
        issue = connection.getIssue(issueId)

    logger.debug("Issue have id={}".format(issueId))

    # Set issue service
    ExecAndLog(connection, issueId, "Service {}".format(YT_SERVICE))

    # Update priority
    ExecAndLog(connection, issueId, "Priority {}".format(ytPriority))

    # ----- END Youtrack get or create issue -----

    # ----- START PROBLEM block ------
    if messages['Status'] == "PROBLEM":

        # Issue exist and NOT Hold on, Unnassigned and Estimated time set
        if issue['State'] != 'Hold on':

            # Estimated time
            ExecAndLog(connection, issueId, "Estimated time {}".format(YT_TIME))

            # Update fix version
            ExecAndLog(connection=connection, issueId=issueId, command="Sprint planned {}".format(fixVersionWeek))

        # Reopen if Fixed or Verified or Canceled
        if issue['State'] == 'Fixed' or issue['State'] == 'Verified' or issue['State'] == 'Canceled':
            # Reopen Issue
            ExecAndLog(connection, issueId, "State reopen")

            # Assignee issue
            ExecAndLog(connection, issueId, command="Assignee Unassigned")

        # Update summary and description for issue
        logger.debug("Run command in {issueId}: {command}".format(issueId=issueId,
                                                                  command="""Update summary and description with connection.updateIssue method"""
                                                                  ))
        connection.updateIssue(issueId=issueId, summary=ytName, description=issueDescription)

        # Add comment
        logger.debug("Run command in {issueId}: {command}".format(issueId=issueId,
                                                                  command="""Now is PROBLEM {}""".format(
                                                                      messages['Text'])
                                                                  ))
        connection.executeCommand(issueId=issueId,
                                  command="",
                                  comment=YT_COMMENT.format(
                                      status=messages['Status'],
                                      text=messages['Text'])
                                  )

        # Send ID to Zabbix:
        logger.debug("ZABBIX-API: Send Youtrack ID to {}".format(messages['EventID']))
        Zbx.event.acknowledge(eventids=messages['EventID'], message="Create Youtrack task")
        Zbx.event.acknowledge(eventids=messages['EventID'],
                              message="https://youtrack.example.com/issue/{}".format(issueId))
    # ----- End PROBLEM block ------


    # ----- Start OK block -----
    if messages['Status'] == "OK":

        if issue['State'] == 'Hold on' or issue['State'] == 'Registered':
            # Cancel if not in work
            ExecAndLog(connection, issueId, command="State Cancel")

            # Assignee issue
            ExecAndLog(connection, issueId, command="Assignee {}".format(YT_ASSIGNEE))

        if issue['State'] == 'Fixed':
            # Verify if Fixed
            ExecAndLog(connection, issueId, command="State verify")

        logger.debug("Run command in {issueId}: {command}".format(issueId=issueId,
                                                                  command="""Now is OK {}""".format(messages['Text'])
                                                                  ))
        connection.executeCommand(issueId=issueId,
                                  command="",
                                  comment=YT_COMMENT.format(
                                      status=messages['Status'],
                                      text=messages['Text'])
                                  )
                    for comment in issue.getComments():
                        if not hasattr(comment, "text") or (len(comment.text.strip()) == 0):
                            setattr(comment, 'text', 'no text')

                user_importer.importUsersRecursively(users)

                print "Create issues [" + str(len(issues)) + "]"
                if params.get('create_new_issues'):
                    last_created_issue_number = create_issues(target, issues, last_created_issue_number)
                else:
                    print target.importIssues(projectId, project.name + ' Assignees', issues)
                link_importer.addAvailableIssues(issues)

                for issue in issues:
                    try:
                        target_issue = target.getIssue(issue.id)
                    except youtrack.YouTrackException, e:
                        print "Cannot get target issue"
                        print e
                        continue

                    if params.get('add_new_comments'):
                        target_comments = dict()
                        max_id = 0
                        for c in target_issue.getComments():
                            target_comments[c.created] = c
                            if max_id < c.created:
                                max_id = c.created
                        for c in issue.getComments():
                            if c.created > max_id or c.created not in target_comments:
                                group = None
Exemplo n.º 18
0
def do_move(source_url, source_login, source_password,
            target_url, target_login, target_password, source_issue_id, target):
    print("source_url       : " + source_url)
    print("source_login     : "******"source_password  : "******"target_url       : " + target_url)
    print("target_login     : "******"target_password  : "******"source_id        : " + source_issue_id)

    if target.find('-') > -1:
        print("target_id        : " + target)
        target_project_id, target_issue_number = target.split('-')
    else:
        print("target_project_id: " + target)
        target_project_id = target
        target_issue_number = None

    # connecting
    try:
        target = Connection(target_url, target_login, target_password)
        print("Connected to target url [%s]" % target_url)
    except Exception as ex:
        print("Failed to connect to target url [%s] with login/password [%s/%s]"
              % (target_url, target_login, target_password))
        raise ex

    try:
        source = Connection(source_url, source_login, source_password)
        print("Connected to source url [%s]" % source_url)
    except Exception as ex:
        print("Failed to connect to source url [%s] with login/password [%s/%s]"
              % (source_url, source_login, source_password))
        raise ex

    try:
        target.getProject(target_project_id)
    except Exception as ex:
        print("Can't connect to target project [%s]" % target_project_id)
        raise ex

    # twin issues
    try:
        source_issue = source.getIssue(source_issue_id)
    except Exception as ex:
        print("Failed to get issue [%s]" % source_issue_id)
        raise ex

    target_issue = Issue()

    # import users if needed
    name_fields = ["reporterName", "assigneeName", "updaterName"]
    for field in name_fields:
        if field in source_issue:
            check_user(source_issue[field], source, target)

    if not target_issue_number:
        target_issue_number = str(get_new_issue_id(target_project_id, target))
    target_issue.numberInProject = target_issue_number

    # check subsystem
    target_subsystem = None
    try:
        target.getSubsystem(target_project_id, source_issue.subsystem)
        target_subsystem = source_issue.subsystem
    except (YouTrackException, AttributeError):
        pass
    target_issue.subsystem = target_subsystem
    for field in PREDEFINED_FIELDS:
        if field in source_issue:
            target_issue[field] = source_issue[field]

    if "Type" in source_issue:
        target_issue.type = source_issue["Type"]
    elif "type" in source_issue:
        target_issue.type = source_issue["type"]
    else:
        target_issue.type = "Bug"

    # convert custom field
    target_cfs = target.getProjectCustomFields(target_project_id)
    for cf in target_cfs:
        cf_name = cf.name
        if cf_name in source_issue:
            target_issue[cf_name] = source_issue[cf_name]

    # comments
    target_issue.comments = source_issue.getComments()
    for comment in target_issue.comments:
        check_user(comment.author, source, target)

    # attachments
    print(target.importIssues(
        target_project_id,
        target.getProjectAssigneeGroups(target_project_id)[0].name,
        [target_issue]))
    for attachment in source_issue.getAttachments():
        check_user(attachment.authorLogin, source, target)
        target.createAttachmentFromAttachment(
            "%s-%s" % (target_project_id, target_issue.numberInProject),
            attachment)
                user_importer.importUsersRecursively(users)

                print "Create issues [" + str(len(issues)) + "]"
                if params.get('create_new_issues'):
                    last_created_issue_number = create_issues(
                        target, issues, last_created_issue_number)
                else:
                    print target.importIssues(projectId,
                                              project.name + ' Assignees',
                                              issues)
                link_importer.addAvailableIssues(issues)

                for issue in issues:
                    try:
                        target_issue = target.getIssue(issue.id)
                    except youtrack.YouTrackException, e:
                        print "Cannot get target issue"
                        print e
                        continue

                    if params.get('sync_tags') and issue.tags:
                        try:
                            for tag in issue.tags:
                                tag = re.sub(r'[,&<>]', '_', tag)
                                try:
                                    target.executeCommand(
                                        issue.id,
                                        'tag ' + tag,
                                        disable_notifications=True)
                                except youtrack.YouTrackException:
def youtrack2youtrack(source_url, source_login, source_password, target_url, target_login, target_password,
                      project_ids, query='', source_token=None, target_token=None, params=None):
    if not len(project_ids):
        print("You should sign at least one project to import")
        return
    if params is None:
        params = {}

    source = Connection(source_url, source_login, source_password) if (source_token is None) else Connection(source_url,
                                                                                                             token=source_token)
    target = Connection(target_url, target_login, target_password) if (target_token is None) else Connection(target_url,
                                                                                                             token=target_token)
    # , proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888)

    print("Import issue link types")
    for ilt in source.getIssueLinkTypes():
        try:
            print(target.createIssueLinkType(ilt))
        except youtrack.YouTrackException as e:
            print(e.message)

    user_importer = UserImporter(source, target, caching_users=params.get('enable_user_caching', True))
    link_importer = LinkImporter(target)

    # create all projects with minimum info and project lead set
    created_projects = []
    for project_id in project_ids:
        created = create_project_stub(source, target, project_id, user_importer)
        created_projects.append(created)

    # save created project ids to create correct group roles afterwards
    user_importer.addCreatedProjects([project.id for project in created_projects])
    # import project leads with group they are included and roles assigned to these groups
    user_importer.importUsersRecursively([target.getUser(project.lead) for project in created_projects])
    # afterwards in a script any user import imply recursive import

    cf_names_to_import = set([])  # names of cf prototypes that should be imported
    for project_id in project_ids:
        cf_names_to_import.update([pcf.name.capitalize() for pcf in source.getProjectCustomFields(project_id)])

    target_cf_names = [pcf.name.capitalize() for pcf in target.getCustomFields()]

    period_cf_names = []

    for cf_name in cf_names_to_import:
        source_cf = source.getCustomField(cf_name)
        if source_cf.type.lower() == 'period':
            period_cf_names.append(source_cf.name.lower())

        print("Processing custom field '%s'" % utf8encode(cf_name))
        if cf_name in target_cf_names:
            target_cf = target.getCustomField(cf_name)
            if not (target_cf.type == source_cf.type):
                print("In your target and source YT instances you have field with name [ %s ]" % utf8encode(cf_name))
                print("They have different types. Source field type [ %s ]. Target field type [ %s ]" %
                      (source_cf.type, target_cf.type))
                print("exiting...")
                exit()
        else:
            if hasattr(source_cf, "defaultBundle"):
                create_bundle_from_bundle(source, target, source_cf.defaultBundle, source_cf.type, user_importer)
            target.createCustomField(source_cf)

    failed_commands = []

    for projectId in project_ids:
        source = Connection(source_url, source_login, source_password) if (source_token is None) else Connection(
            source_url, token=source_token)
        target = Connection(target_url, target_login, target_password) if (target_token is None) else Connection(
            target_url, token=target_token)
        # , proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888)
        # reset connections to avoid disconnections
        user_importer.resetConnections(source, target)
        link_importer.resetConnections(target)

        # copy project, subsystems, versions
        project = source.getProject(projectId)

        link_importer.addAvailableIssuesFrom(projectId)
        project_custom_fields = source.getProjectCustomFields(projectId)
        # create bundles and additional values
        for pcf_ref in project_custom_fields:
            pcf = source.getProjectCustomField(projectId, pcf_ref.name)
            if hasattr(pcf, "bundle"):
                try:
                    create_bundle_from_bundle(source, target, pcf.bundle, source.getCustomField(pcf.name).type,
                                              user_importer)
                except youtrack.YouTrackException as e:
                    if e.response.status != 409:
                        raise e
                    else:
                        print(e)

        target_project_fields = [pcf.name.lower() for pcf in target.getProjectCustomFields(projectId)]
        for field in project_custom_fields:
            if field.name.lower() in target_project_fields:
                if hasattr(field, 'bundle'):
                    if field.bundle != target.getProjectCustomField(projectId, field.name).bundle:
                        target.deleteProjectCustomField(projectId, field.name)
                        create_project_custom_field(target, field, projectId)
            else:
                try:
                    create_project_custom_field(target, field, projectId)
                except youtrack.YouTrackException as e:
                    if e.response.status != 409:
                        raise e
                    else:
                        print(e)

        # copy issues
        start = 0
        max = 20

        sync_workitems = enable_time_tracking(source, target, projectId)
        tt_settings = target.getProjectTimeTrackingSettings(projectId)

        print("Import issues")
        last_created_issue_number = 0

        while True:
            try:
                print("Get issues from " + str(start) + " to " + str(start + max))
                issues = source.getIssues(projectId, query, start, max)

                if len(issues) <= 0:
                    break

                if convert_period_values and period_cf_names:
                    for issue in issues:
                        for pname in period_cf_names:
                            for fname in issue.__dict__:
                                if fname.lower() != pname:
                                    continue
                                issue[fname] = period_to_minutes(issue[fname])

                users = set([])

                for issue in issues:
                    print("Collect users for issue [%s]" % issue.id)

                    users.add(issue.getReporter())
                    if issue.hasAssignee():
                        if isinstance(issue.Assignee, (list, tuple)):
                            users.update(issue.getAssignee())
                        else:
                            users.add(issue.getAssignee())
                    # TODO: http://youtrack.jetbrains.net/issue/JT-6100
                    users.add(issue.getUpdater())
                    if issue.hasVoters():
                        users.update(issue.getVoters())
                    for comment in issue.getComments():
                        users.add(comment.getAuthor())

                    print("Collect links for issue [%s]" % issue.id)
                    link_importer.collectLinks(issue.getLinks(True))
                    # links.extend(issue.getLinks(True))

                    # fix problem with comment.text
                    for comment in issue.getComments():
                        if not hasattr(comment, "text") or (len(comment.text.strip()) == 0):
                            setattr(comment, 'text', 'no text')

                user_importer.importUsersRecursively(users)

                print("Create issues [" + str(len(issues)) + "]")
                if params.get('create_new_issues'):
                    create_issues(target, issues, last_created_issue_number)
                else:
                    print(target.importIssues(projectId, project.name + ' Assignees', issues))
                link_importer.addAvailableIssues(issues)

                for issue in issues:
                    try:
                        target_issue = target.getIssue(issue.id)
                    except youtrack.YouTrackException as e:
                        print("Cannot get target issue")
                        print(e)
                        continue

                    if params.get('sync_tags') and issue.tags:
                        try:
                            for tag in issue.tags:
                                tag = re.sub(r'[,&<>]', '_', tag)
                                try:
                                    target.executeCommand(issue.id, 'tag ' + tag, disable_notifications=True)
                                except youtrack.YouTrackException:
                                    tag = re.sub(r'[\s-]', '_', tag)
                                    target.executeCommand(issue.id, 'tag ' + tag, disable_notifications=True)
                        except youtrack.YouTrackException as e:
                            print("Cannot sync tags for issue " + issue.id)
                            print(e)

                    if params.get('add_new_comments'):
                        target_comments = dict()
                        max_id = 0
                        for c in target_issue.getComments():
                            target_comments[c.created] = c
                            if max_id < c.created:
                                max_id = c.created
                        for c in issue.getComments():
                            if c.created > max_id or c.created not in target_comments:
                                group = None
                                if hasattr(c, 'permittedGroup'):
                                    group = c.permittedGroup
                                try:
                                    target.executeCommand(issue.id, 'comment', c.text, group, c.author,
                                                          disable_notifications=True)
                                except youtrack.YouTrackException as e:
                                    print('Cannot add comment to issue')
                                    print(e)

                    if params.get('sync_custom_fields'):
                        skip_fields = []
                        if tt_settings and tt_settings.Enabled and tt_settings.TimeSpentField:
                            skip_fields.append(tt_settings.TimeSpentField)
                        skip_fields = [name.lower() for name in skip_fields]
                        for pcf in [pcf for pcf in project_custom_fields if pcf.name.lower() not in skip_fields]:
                            target_cf_value = None
                            if pcf.name in target_issue:
                                target_cf_value = target_issue[pcf.name]
                                if isinstance(target_cf_value, (list, tuple)):
                                    target_cf_value = set(target_cf_value)
                                elif target_cf_value == target.getProjectCustomField(projectId, pcf.name).emptyText:
                                    target_cf_value = None
                            source_cf_value = None
                            if pcf.name in issue:
                                source_cf_value = issue[pcf.name]
                                if isinstance(source_cf_value, (list, tuple)):
                                    source_cf_value = set(source_cf_value)
                                elif source_cf_value == source.getProjectCustomField(projectId, pcf.name).emptyText:
                                    source_cf_value = None
                            if source_cf_value == target_cf_value:
                                continue
                            if isinstance(source_cf_value, set) or isinstance(target_cf_value, set):
                                if source_cf_value is None:
                                    source_cf_value = set([])
                                elif not isinstance(source_cf_value, set):
                                    source_cf_value = set([source_cf_value])
                                if target_cf_value is None:
                                    target_cf_value = set([])
                                elif not isinstance(target_cf_value, set):
                                    target_cf_value = set([target_cf_value])
                                for v in target_cf_value:
                                    if v not in source_cf_value:
                                        target.executeCommand(issue.id, 'remove %s %s' % (pcf.name, v),
                                                              disable_notifications=True)
                                for v in source_cf_value:
                                    if v not in target_cf_value:
                                        target.executeCommand(issue.id, 'add %s %s' % (pcf.name, v),
                                                              disable_notifications=True)
                            else:
                                if source_cf_value is None:
                                    source_cf_value = target.getProjectCustomField(projectId, pcf.name).emptyText
                                if pcf.type.lower() == 'date':
                                    m = re.match(r'(\d{10})(?:\d{3})?', str(source_cf_value))
                                    if m:
                                        source_cf_value = datetime.datetime.fromtimestamp(
                                            int(m.group(1))).strftime('%Y-%m-%d')
                                elif pcf.type.lower() == 'period':
                                    source_cf_value = '%sm' % source_cf_value
                                command = '%s %s' % (pcf.name, source_cf_value)
                                try:
                                    target.executeCommand(issue.id, command, disable_notifications=True)
                                except youtrack.YouTrackException as e:
                                    if e.response.status == 412 and e.response.reason.find('Precondition Failed') > -1:
                                        print('WARN: Some workflow blocks following command: %s' % command)
                                        failed_commands.append((issue.id, command))

                    if sync_workitems:
                        workitems = source.getWorkItems(issue.id)
                        if workitems:
                            existing_workitems = dict()
                            target_workitems = target.getWorkItems(issue.id)
                            if target_workitems:
                                for w in target_workitems:
                                    _id = '%s\n%s\n%s' % (w.date, w.authorLogin, w.duration)
                                    if hasattr(w, 'description'):
                                        _id += '\n%s' % w.description
                                    existing_workitems[_id] = w
                            new_workitems = []
                            for w in workitems:
                                _id = '%s\n%s\n%s' % (w.date, w.authorLogin, w.duration)
                                if hasattr(w, 'description'):
                                    _id += '\n%s' % w.description
                                if _id not in existing_workitems:
                                    new_workitems.append(w)
                            if new_workitems:
                                print("Process workitems for issue [ " + issue.id + "]")
                                try:
                                    user_importer.importUsersRecursively(
                                        [source.getUser(w.authorLogin)
                                         for w in new_workitems])
                                    target.importWorkItems(issue.id, new_workitems)
                                except youtrack.YouTrackException as e:
                                    if e.response.status == 404:
                                        print("WARN: Target YouTrack doesn't support workitems importing.")
                                        print("WARN: Workitems won't be imported.")
                                        sync_workitems = False
                                    else:
                                        print("ERROR: Skipping workitems because of error:" + str(e))

                    print("Process attachments for issue [%s]" % issue.id)
                    existing_attachments = dict()
                    try:
                        for a in target.getAttachments(issue.id):
                            existing_attachments[a.name + '\n' + a.created] = a
                    except youtrack.YouTrackException as e:
                        if e.response.status == 404:
                            print("Skip importing attachments because issue %s doesn't exist" % issue.id)
                            continue
                        raise e

                    attachments = []

                    users = set([])
                    for a in issue.getAttachments():
                        if a.name + '\n' + a.created in existing_attachments and not params.get('replace_attachments'):
                            a.name = utf8encode(a.name)
                            try:
                                print("Skip attachment '%s' (created: %s) because it's already exists"
                                      % (utf8encode(a.name), utf8encode(a.created)))
                            except Exception:
                                pass
                            continue
                        attachments.append(a)
                        author = a.getAuthor()
                        if author is not None:
                            users.add(author)
                    user_importer.importUsersRecursively(users)

                    for a in attachments:
                        print("Transfer attachment of " + utf8encode(issue.id) + ": " + utf8encode(a.name))
                        # TODO: add authorLogin to workaround http://youtrack.jetbrains.net/issue/JT-6082
                        # a.authorLogin = target_login
                        try:
                            target.createAttachmentFromAttachment(issue.id, a)
                        except BaseException as e:
                            print("Cant import attachment [ %s ]" % utf8encode(a.name))
                            print(repr(e))
                            continue
                        if params.get('replace_attachments'):
                            try:
                                old_attachment = existing_attachments.get(a.name + '\n' + a.created)
                                if old_attachment:
                                    print('Deleting old attachment')
                                    target.deleteAttachment(issue.id, old_attachment.id)
                            except BaseException as e:
                                print("Cannot delete attachment '%s' from issue %s" % (
                                utf8encode(a.name), utf8encode(issue.id)))
                                print(e)

            except Exception as e:
                print('Cant process issues from ' + str(start) + ' to ' + str(start + max))
                traceback.print_exc()
                raise e

            start += max

    print("Import issue links")
    link_importer.importCollectedLinks()

    print("Trying to execute failed commands once again")
    for issue_id, command in failed_commands:
        try:
            print('Executing command on issue %s: %s' % (issue_id, command))
            target.executeCommand(issue_id, command, disable_notifications=True)
        except youtrack.YouTrackException as e:
            print('Failed to execute command for issue #%s: %s' % (issue_id, command))
            print(e)
Exemplo n.º 21
0
def Main(sendTo, subject, yamlMessage):
    """
    Workflow Zabbix-YouTrack
    :param sendTo: URL to Youtrack (ex. https://youtrack.example.com)
    :param subject: subject from Zabbix Action
    :param yamlMessage: message from Zabbix Action
    :return:
    """

    # ----- Use below example yamlMessage to debug -----
    #     yamlMessage = """Name: 'Test Zabbix-YT workflow, ignore it'
    # Text: 'Agent ping (server:agent.ping()): DOWN (1) '
    # Hostname: 'server.exmpale.ru'
    # Status: "OK"
    # Severity: "High"
    # EventID: "96976"
    # TriggerID: "123456789012" """

    messages = yaml.load(yamlMessage)

    # ----- START Issue parameters -----
    # Correspondence between the YouTrackPriority and ZabbixSeverity
    # Critical >= High
    # Normal < High

    ytPriority = 'Normal'
    if messages['Severity'] == 'Disaster' or messages['Severity'] == 'High':
        ytPriority = 'Critical'

    ytName = "{} ZabbixTriggerID::{}".format(messages['Name'],
                                             messages['TriggerID'])
    # ----- END Issue parameters -----

    # ----- START Youtrack Issue description -----
    # Search link to other issue
    searchString = "Hostname: '{}'".format(messages['Hostname'])
    linkToHostIssue = "{youtrack}/issues/{projectname}?q={query}".format(
        youtrack=sendTo,
        projectname=YT_PROJECT_NAME,
        query=urllib.parse.quote(searchString, safe=''))

    issueDescription = """
{ytName}
-----
{yamlMessage}
-----
- [https://zabbix.example.com/zabbix.php?action=dashboard.view Zabbix Dashboard]
- Show [{linkToHostIssue} all issue for *this host*]
""".format(
        ytName=ytName,
        yamlMessage=yamlMessage,
        linkToHostIssue=linkToHostIssue,
    )

    # ----- END Youtrack Issue description -----

    # ----- START Youtrack current week -----

    # Create connect to Youtrack API
    connection = Connection(sendTo, YT_USER, YT_PASSWORD)

    # Get current week in YT format (Sprint planned)
    version = connection.getAllBundles('version')

    for fixVersion in version[0].values:
        if fixVersion['archived'] == False and fixVersion['released'] == False:
            fixVersionWeek = fixVersion['name']
            break
    # ----- END Youtrack current week -----

    # ----- START Youtrack get or create issue -----
    # Get issue if exist
    # Search for TriggerID
    createNewIssue = False

    logger.debug("Get issue with text '{}'".format(messages['TriggerID']))
    issue = connection.getIssues(
        YT_PROJECT_NAME, "ZabbixTriggerID::{}".format(messages['TriggerID']),
        0, 1)

    if len(issue) == 0:
        createNewIssue = True

    else:
        # if issue contains TriggerID in summary, then it's good issue
        # else create new issue, this is bad issue, not from Zabbix
        if "ZabbixTriggerID::{}".format(
                messages['TriggerID']) in issue[0]['summary']:
            issueId = issue[0]['id']
            issue = connection.getIssue(issueId)
        else:
            createNewIssue = True

    # Create new issue
    if createNewIssue:
        logger.debug("Create new issue because it is not exist")
        issue = connection.createIssue(
            YT_PROJECT_NAME,
            'Unassigned',
            ytName,
            issueDescription,
            priority=ytPriority,
            subsystem=YT_SUBSYSTEM,
            type=YT_TYPE,
        )
        time.sleep(3)

        # Parse ID for new issue
        result = re.search(r'(CM-\d*)', issue[0]['location'])
        issueId = result.group(0)
        issue = connection.getIssue(issueId)

    logger.debug("Issue have id={}".format(issueId))

    # Set issue service
    ExecAndLog(connection, issueId, "Service {}".format(YT_SERVICE))

    # Update priority
    ExecAndLog(connection, issueId, "Priority {}".format(ytPriority))

    # ----- END Youtrack get or create issue -----

    # ----- START PROBLEM block ------
    if messages['Status'] == "PROBLEM":

        # Issue exist and NOT Hold on, Unnassigned and Estimated time set
        if issue['State'] != 'Hold on':

            # Estimated time
            ExecAndLog(connection, issueId,
                       "Estimated time {}".format(YT_TIME))

            # Update fix version
            ExecAndLog(connection=connection,
                       issueId=issueId,
                       command="Sprint planned {}".format(fixVersionWeek))

        # Reopen if Fixed or Verified or Canceled
        if issue['State'] == 'Fixed' or issue['State'] == 'Verified' or issue[
                'State'] == 'Canceled':
            # Reopen Issue
            ExecAndLog(connection, issueId, "State reopen")

            # Assignee issue
            ExecAndLog(connection, issueId, command="Assignee Unassigned")

        # Update summary and description for issue
        logger.debug("Run command in {issueId}: {command}".format(
            issueId=issueId,
            command=
            """Update summary and description with connection.updateIssue method"""
        ))
        connection.updateIssue(issueId=issueId,
                               summary=ytName,
                               description=issueDescription)

        # Add comment
        logger.debug("Run command in {issueId}: {command}".format(
            issueId=issueId,
            command="""Now is PROBLEM {}""".format(messages['Text'])))
        connection.executeCommand(issueId=issueId,
                                  command="",
                                  comment=YT_COMMENT.format(
                                      status=messages['Status'],
                                      text=messages['Text']))

        # Send ID to Zabbix:
        logger.debug("ZABBIX-API: Send Youtrack ID to {}".format(
            messages['EventID']))
        Zbx.event.acknowledge(eventids=messages['EventID'],
                              message="Create Youtrack task")
        Zbx.event.acknowledge(
            eventids=messages['EventID'],
            message="https://youtrack.example.com/issue/{}".format(issueId))
    # ----- End PROBLEM block ------

    # ----- Start OK block -----
    if messages['Status'] == "OK":

        if issue['State'] == 'Hold on' or issue['State'] == 'Registered':
            # Cancel if not in work
            ExecAndLog(connection, issueId, command="State Cancel")

            # Assignee issue
            ExecAndLog(connection,
                       issueId,
                       command="Assignee {}".format(YT_ASSIGNEE))

        if issue['State'] == 'Fixed':
            # Verify if Fixed
            ExecAndLog(connection, issueId, command="State verify")

        logger.debug("Run command in {issueId}: {command}".format(
            issueId=issueId,
            command="""Now is OK {}""".format(messages['Text'])))
        connection.executeCommand(issueId=issueId,
                                  command="",
                                  comment=YT_COMMENT.format(
                                      status=messages['Status'],
                                      text=messages['Text']))