Esempio n. 1
0
from zendesk import Zendesk

################################################################
## NEW CONNECTION CLIENT
################################################################
zendesk = Zendesk(
    zendesk_url='https://yourcompany.zendesk.com',
    zendesk_username='******',
    zendesk_password='******',
    use_api_token=True,
    api_version=2
)

# Are you getting an error such as...
# "SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed"?
zendesk = Zendesk('https://yourcompany.zendesk.com', '*****@*****.**', 'passwd',
    client_args={
        "disable_ssl_certificate_validation": True
    }
)


################################################################
## TICKETS
################################################################

# List
zendesk.list_tickets(view_id=1) # Must have a view defined

# Create
new_ticket = {
Esempio n. 2
0
import os
from config import ENV
from salesforce import SalesForce
from zendesk import Zendesk
from migration import MigrationItem
from log_helper import get_logger
import helpers

log = get_logger('Main')

if __name__ == "__main__":
    migration_plan = json.load(open('migration_plan.json', 'r'))
    sf_config = migration_plan['salesforce']
    sf = SalesForce(**sf_config)

    zd_config = migration_plan['zendesk']
    zd = Zendesk(**zd_config)

    for item in migration_plan['migration_items']:
        if item['skip'] == False:
            if item['type'] == 'migration_object':
                migration_item = MigrationItem(sf, zd, mode=ENV, **item)
                if migration_item.skip == False:
                    try:
                        migration_item.migrate()
                    except Exception as err:
                        log.critical(err)
                        raise err
            elif item['type'] == 'script':
                eval(item['script'], {"helpers": helpers, "env": ENV})
Esempio n. 3
0
def get_zd_instance():
    migration_plan = json.load(open('migration_plan.json', 'r'))
    zd_config = migration_plan['zendesk']
    return Zendesk(**zd_config)
    42730237: 'Tickets/LSM',
    42730227: 'Tickets/WSM',
    42771018: 'Tickets/Mobile',
    42730217: 'Tickets/Insights',
    44896573: 'Tickets/Browser',
    42771028: 'Tickets/Platform',
    42730207: 'Tickets/Other'
}

post_url = "https://platform-api.newrelic.com/platform/v1/metrics"

guid = 'com.NewRelic.ZedScraper'
#update bash_profile on server with this info
zendesk = Zendesk(environ['ZENDESK_URL'],
                  environ['ZENDESK_USERNAME'],
                  environ['ZENDESK_APITOKEN'],
                  use_api_token=True,
                  api_version=2,
                  client_args={"disable_ssl_certificate_validation": True})

platform_key = environ['NEW_RELIC_APIKEY']

view_blob = zendesk.count_many_views(ids=view_ids.keys())

counted_views = {}

for view in view_blob['view_counts']:
    metric_name = "Component/test2/%s[Tickets]" % view_ids[view['view_id']]
    total_tickets = view['value']
    data = {
        "agent": {
            "host": "db.zendesk.newrelic_tickets",
Esempio n. 5
0
def main(argv=None):
    import sys, tempfile, argparse

    # Log to stdout
    import logging
    logging.basicConfig()

    # Declare a class for an argparse custom action.
    # Handles converting ascii input from argparse that may contain unicode
    # to a real unicode string.
    class UnicodeStore(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            setattr(namespace, self.dest, values.decode('utf-8'))

    # Options precedence:
    # program state defaults, which are overridden by
    # ~/.zdf2pdf.cfg [zdf2pdf] section options, which are overridden by
    # command line options, which are overridden by
    # -c CONFIG_FILE [zdf2pdf] section options, which are overridden by
    # ~/.zdf2pdf.cfg [RUN_SECTION] section options, which are overridden by
    # -c CONFIG_FILE [RUN_SECTION] section options
    #
    # Program state, with defaults
    #
    state = {
        'verbose': False,
        'json_file': None,
        'categories': None,
        'forums': None,
        'topics': None,
        'run_section': None,
        'list_zdf': 'forums',
        'style_file': None,
        'output_file': 'PCLOADLETTER.pdf',
        'title': None,
        'title_class': None,
        'author': None,
        'date': None,
        'copyright': None,
        'toc': False,
        'toc_class': None,
        'toc_title': 'Table of Contents',
        'pre_width': None,
        'strip_empty': False,
        'header': None,
        'footer': None,
        'category_sections': False,
        'forum_sections': False,
        'topics_heading': None,
        'work_dir': tempfile.gettempdir(),
        'delete': False,
        'url': None,
        'mail': None,
        'password': '******',
        'is_token': False,
    }

    argp = argparse.ArgumentParser(
        description='Make a PDF from Zendesk forums or entries.')
    argp.add_argument('-v',
                      '--verbose',
                      action='store_true',
                      help='Verbose output')

    argp.add_argument('--json-file',
                      action=UnicodeStore,
                      dest='json_file',
                      help='Zendesk entries JSON file to convert to PDF')
    argp.add_argument(
        '--categories',
        action=UnicodeStore,
        dest='categories',
        help='Comma separated Category IDs to download and convert to PDF')
    argp.add_argument(
        '--forums',
        action=UnicodeStore,
        dest='forums',
        help='Comma separated Forum IDs to download and convert to PDF')
    argp.add_argument(
        '--topics',
        action=UnicodeStore,
        dest='topics',
        help='Comma separated Topic (Entry) IDs to download and convert to PDF'
    )
    argp.add_argument('-r',
                      action=UnicodeStore,
                      dest='run_section',
                      help='Run pre-configured section in configuration file')
    argp.add_argument(
        '-l',
        action=UnicodeStore,
        dest='list_zdf',
        help="""List a forum's entries by ID and title.  If no forum ID is
        supplied, list forums by ID and title organized by category""",
        nargs='?',
        const=state['list_zdf'],
        metavar='FORUM_TO_LIST')

    argp.add_argument('-c',
                      action=UnicodeStore,
                      dest='config_file',
                      help='Configuration file (overrides ~/.zdf2pdf.cfg)')
    argp.add_argument('-s',
                      action=UnicodeStore,
                      dest='style_file',
                      help='Style file (CSS) to <link>')
    argp.add_argument('-o',
                      action=UnicodeStore,
                      dest='output_file',
                      help='Output filename (default: PCLOADLETTER.pdf)',
                      default=state['output_file'])

    argp.add_argument('-t',
                      action=UnicodeStore,
                      dest='title',
                      help='Title to be added to the beginning of the PDF')
    argp.add_argument(
        '-a',
        action=UnicodeStore,
        dest='author',
        help='Author line to be added to the beginning of the PDF')
    argp.add_argument('--date',
                      action=UnicodeStore,
                      dest='date',
                      help='Date line to be added to the beginning of the PDF')
    argp.add_argument(
        '--copyright',
        action=UnicodeStore,
        dest='copyright',
        help='Copyright line to be added to the beginning of the PDF')
    argp.add_argument('--title-class',
                      action=UnicodeStore,
                      dest='title_class',
                      help='CSS class to be added to title page div')
    argp.add_argument('--toc',
                      action='store_true',
                      dest='toc',
                      help="Generate a Table of Contents (default: false)")
    argp.add_argument('--toc-title',
                      action=UnicodeStore,
                      dest='toc_title',
                      help="ToC title (default: Table of Contents)")
    argp.add_argument('--toc-class',
                      action=UnicodeStore,
                      dest='toc_class',
                      help='CSS class to be added to ToC div')
    argp.add_argument('--pre-width',
                      action=UnicodeStore,
                      dest='pre_width',
                      help='Width to wrap contents of <pre></pre> tags.')
    argp.add_argument('--strip-empty',
                      action='store_true',
                      dest='strip_empty',
                      help='Strip empty tags. (default: false)')
    argp.add_argument('--header',
                      action=UnicodeStore,
                      dest='header',
                      help='HTML header to add to the PDF (see docs)')
    argp.add_argument('--footer',
                      action=UnicodeStore,
                      dest='footer',
                      help='HTML footer to add to the PDF (see docs)')
    argp.add_argument('--category-sections',
                      action='store_true',
                      dest='category_sections',
                      help='Make categories sections (default: false)')
    argp.add_argument('--forum-sections',
                      action='store_true',
                      dest='category_sections',
                      help='Make categories sections (default: false)')
    argp.add_argument(
        '--topics-heading',
        action=UnicodeStore,
        dest='topics_heading',
        help='Heading to put at start of topics retrieved individually')

    argp.add_argument(
        '-w',
        action=UnicodeStore,
        dest='work_dir',
        help="""Working directory in which to store JSON output and images
        (default: temp dir)""")
    argp.add_argument('-d',
                      '--delete',
                      action='store_true',
                      dest='delete',
                      help="""Delete working directory at program exit
        (default: do not delete)""")

    argp.add_argument('-u',
                      action=UnicodeStore,
                      dest='url',
                      help='URL of Zendesk (e.g. https://example.zendesk.com)')
    argp.add_argument('-m',
                      action=UnicodeStore,
                      dest='mail',
                      help='E-Mail address for Zendesk login')
    argp.add_argument('-p',
                      action=UnicodeStore,
                      dest='password',
                      help='Password for Zendesk login',
                      nargs='?',
                      const=state['password'])
    argp.add_argument(
        '-i',
        '--is-token',
        action='store_true',
        dest='is_token',
        help='Is token? Specify if password supplied a Zendesk token')

    # Set argparse defaults with program defaults.
    # Skip password and list_zdf as they are argparse const, not argparse default
    argp.set_defaults(**dict((k, v) for k, v in state.iteritems()
                             if k != 'password' and k != 'list_zdf'))

    # Read ~/.zdf2pdf.cfg [zdf2pdf] section and update argparse defaults
    try:
        config_state(
            os.path.expanduser('~') + '/.zdf2pdf.cfg', 'zdf2pdf', state)
        # Skip list_zdf because it is not a config file value, not an argparse
        # const value, and we don't want to lose it by overwriting it with None.
        # Password is OK now, because we either have one from the config file or
        # it is still None.
        argp.set_defaults(**dict(
            (k, v) for k, v in state.iteritems() if k != 'list_zdf'))
    except configparser.NoSectionError:
        # -c CONFIG_FILE did not have a [zdf2pdf] section. Skip it.
        pass

    # Parse the command line options
    if argv is None:
        argv = sys.argv
    args = argp.parse_args()

    # Update the program state with command line options
    for k in state.keys():
        state[k] = getattr(args, k)

    # -c CONFIG_FILE given on command line read args.config_file [zdf2pdf], update state
    if args.config_file:
        if state['verbose']:
            print('Reading config file {}'.format(args.config_file))
        try:
            config_state(args.config_file, 'zdf2pdf', state)
        except configparser.NoSectionError:
            # -c CONFIG_FILE did not have a [zdf2pdf] section. Skip it.
            pass

    # -r RUN_SECTION given
    if args.run_section:
        if state['verbose']:
            print('Searching for {} in ~/.zdf2pdf'.format(args.run_section))
        section_found = False
        try:
            config_state(
                os.path.expanduser('~') + '/.zdf2pdf.cfg', args.run_section,
                state)
            section_found = True
            if state['verbose']:
                print('Found {} in ~/.zdf2pdf'.format(args.run_section))
        except configparser.NoSectionError:
            # ~/.zdf2pdf.cfg did not have this section. Hope it's found later.
            pass

        # -c CONFIG_FILE and -r RUN_SECTION given
        if args.config_file:
            if state['verbose']:
                print('Searching for {} in {}'.format(args.run_section,
                                                      args.config_file))
            try:
                config_state(args.config_file, args.run_section, state)
                section_found = True
                if state['verbose']:
                    print('Found {} in {}'.format(args.run_section,
                                                  args.config_file))
            except configparser.NoSectionError:
                # CONFIG_FILE did not have this section.
                pass

        # If the section wasn't found, print an error and exit
        if not section_found:
            print('Error: Run section {} was not found'.format(
                args.run_section))
            return 1

    if state['categories'] or state['topics'] or state['forums'] or state[
            'list_zdf']:
        from zendesk import Zendesk
        if state['url'] and state['mail'] and state['password']:
            if state['verbose']:
                print(
                    'Configuring Zendesk with:\n'
                    'url: {}\n'
                    'mail: {}\n'
                    'password: (hidden)\n'
                    'is_token: {}\n'.format(state['url'], state['mail'],
                                            repr(state['is_token'])))
            zd = Zendesk(state['url'],
                         zendesk_username=state['mail'],
                         zendesk_password=state['password'],
                         use_api_token=state['is_token'])
        else:
            msg = textwrap.dedent("""\
                Error: Need Zendesk config for requested operation. Use -u, -m,
                       -p options or a config file to provide the information.

                Config file (e.g. ~/.zdf2pdf.cfg) should be something like:
                [zdf2pdf]
                url = https://example.zendesk.com
                mail = [email protected]
                password = dneib393fwEF3ifbsEXAMPLEdhb93dw343
                is_token = 1
                """)
            print(msg)
            return 1

    # All config options are in, state is set.
    # Handle any last minute type checking or setting
    if state['pre_width']:
        try:
            state['pre_width'] = int(state['pre_width'])
        except TypeError:
            print('Could not convert pre_width {} to integer'.format(
                repr(state['pre_width'])))
            return 1

    # Log the state
    if state['verbose']:
        print('Running with program state:')
        for k, v in state.iteritems():
            print('{} {}'.format(k, repr(v)))

    if state['list_zdf'] == 'forums':
        # List available zendesk forums with their IDs and titles and exit.
        # Listing is formatted like for following:
        # 12345 Category 1 name
        #     09876 Forum 1 name
        #     54321 Forum 2 name
        # 67890 Category 2 name
        if state['verbose']: print('Listing all forums')
        categories = zd.list_categories()
        for cat in categories['categories']:
            print('{} {}'.format(cat['id'], cat['name']))
            forums = zd.list_category_forums(category_id=cat['id'])['forums']
            for forum in forums:
                print('    {} {}'.format(forum['id'], forum['name']))
        return 0

    elif state['list_zdf']:
        if state['verbose']:
            print('Listing all entries in forum {}'.format(state['list_zdf']))
        # List a zendesk forum's entries with their IDs and titles and exit
        try:
            forum_id = int(state['list_zdf'])
        except ValueError:
            print('Error: Could not convert to integer: {}'.format(
                state['list_zdf']))
            return 1

        entries = zd.list_topics(forum_id=state['list_zdf'])
        for entry in entries['topics']:
            print('{} {}'.format(entry['id'], entry['title']))
        return 0

    # Use an entries file on disk
    if state['json_file']:
        if state['verbose']:
            print('Reading entries from {}'.format(state['json_file']))
        # Get the entries off disk
        with open(state['json_file'], 'r') as infile:
            entries = json.loads(infile.read())
    else:
        entries = []

    # Get the entries from one or more zendesk categories
    if state['categories']:

        try:
            cat_ids = [int(i) for i in state['categories'].split(',')]
        except ValueError:
            print('Error: Could not convert to integers: {}'.format(
                state['forums']))
            return 1

        for cat_id in cat_ids:
            if state['verbose']:
                print('Obtaining entries from category {}'.format(cat_id))

            cat_entries = []
            forums = zd.list_category_forums(category_id=cat_id)['forums']
            for forum in forums:
                if state['verbose']:
                    print('Obtaining entries from forum {}'.format(
                        forum['id']))

                # topics = [{entry}, {entry}, ..., {entry}]
                topics = zd.list_topics(forum_id=forum['id'])['topics']

                if state['forum_sections']:
                    cat_entries.append({
                        'section': forum['name'],
                        'id': forum['id'],
                        'body': forum['description'],
                        'topics': topics
                    })
                    # result:
                    # cat_entries = [
                    #                 <previous forums,>
                    #                 {
                    #                   'section':'FORUM TITLE',
                    #                   'topics':
                    #                     [
                    #                       {entry},
                    #                       ...
                    #                       {entry}
                    #                     ]
                    #                 }
                    #               ]
                else:
                    cat_entries += topics
                    # result:
                    # cat_entries = [
                    #                 {entry},
                    #                 ...
                    #                 {entry}
                    #               ]

            if state['category_sections']:
                cat = zd.show_category(category_id=cat_id)
                entries.append({
                    'section': cat['name'],
                    'id': cat_id,
                    'body': cat['description'],
                    'topics': cat_entries
                })
                #od[zd.show_category(category_id=cat_id)['name']] =
                #entries.append([zd.show_category(category_id=cat_id)['name']] =
                # result if forum sections:
                # entries = [
                #             <previous categories,>
                #             {
                #               'section': 'CATEGORY TITLE',
                #               'id': 'CATEGORY ID',
                #               'body': 'CATEGORY DESCRIPTION',
                #               'topics':
                #                 [
                #                   {
                #                     'section':'FORUM TITLE',
                #                     'topics':
                #                       [
                #                         {entry},
                #                         ...
                #                         {entry}
                #                       ]
                #                   }
                #                 ]
                #             }
                #           ]
                #
                # result if not forum sections:
                # entries = [
                #             <previous categories,>
                #             {
                #               'section':'CATEGORY TITLE',
                #               'topics':
                #                 [
                #                   {entry},
                #                   ...
                #                   {entry}
                #                 ]
                #             }
                #           ]
            else:
                entries += cat_entries
                # result: whatever cat_entries was (forums as sections or not)
                #         is concatenated onto the end of entries

    # Get the entries from one or more zendesk forums
    if state['forums']:
        try:
            forum_ids = [int(i) for i in state['forums'].split(',')]
            for forum_id in forum_ids:
                if state['verbose']:
                    print('Obtaining entries from forum {}'.format(forum_id))
                topics = zd.list_topics(forum_id=forum_id)['topics']
                # see above for description of what entries looks like
                if state['forum_sections']:
                    forum = zd.show_forum(forum_id=forum_id)['forum']
                    entries.append({
                        'section': forum['name'],
                        'id': forum['id'],
                        'body': forum['description'],
                        'topics': topics
                    })
                else:
                    entries += topics

        except ValueError:
            print('Error: Could not convert to integers: {}'.format(
                state['forums']))
            return 1

    # Get individual entries from zendesk
    if state['topics']:
        topic_ids = state['topics'].replace(' ', '')
        topics = zd.show_multiple_topics(topic_ids)['topics']
        if state['entries_heading']:
            entries.append({
                'section': state['entries_heading'],
                'topics': topics
            })
        else:
            entries += topics

    if len(entries) == 0:
        # Didn't get entries from any inputs.
        print("Error: Did not receive any entries.")
        return 1

    zdf2pdf(entries, state)

    if state['delete']:
        shutil.rmtree(state['work_dir'])

    return 0
Esempio n. 6
0
def main():
    arguments = docopt(__doc__)

    logger.setLevel(arguments['--level'])
    logger.debug(arguments)

    global cfg
    global run_open
    global open_cmd
    global zendesk

    # read in YAML configuration file
    if "~" in arguments['--config']:
        pattern = re.compile('~')
        arguments['--config'] = pattern.sub(os.path.expanduser("~"), arguments['--config'])
    if not os.path.exists(arguments['--config']):
        logger.error("Specified configuration file does not exist!")
        exit(1)
    with open(arguments['--config'], 'r') as ymlfile:
        cfg = yaml.load(ymlfile)

    # determine if run_open is defined and enabled
    try:
        run_open = cfg['downloader']['run_open']
        if str(run_open).lower() == "true" or run_open == 1:
            run_open = True
        else:
            run_open = False
    except:
        run_open = False
    # determine if open_command is defined
    try:
        open_cmd = cfg['downloader']['open_command']
    except:
        if run_open:
            logger.warning("'run_open' is set, but 'open_command' doesn't exist - disabling auto open. Please configure 'open_cmd' in .zendesk.yml.")
            run_open = False

    # check directory for downloads, expand '~' and append '/' if necessary
    if "~" in cfg['downloader']['directory']:
        pattern = re.compile('~')
        cfg['downloader']['directory'] = pattern.sub(os.path.expanduser("~"), cfg['downloader']['directory'])
    if not cfg['downloader']['directory'].endswith('/'):
        cfg['downloader']['directory'] += '/'
    logger.debug("download directory: {}".format(cfg['downloader']['directory']))

    options = {}
    if 'extensions' in cfg['downloader']:
        options['extensions'] = cfg['downloader']['extensions']
    if 'exclude' in cfg['downloader']:
        options['exclude'] = cfg['downloader']['exclude']
    if 'rm_after_extract' in cfg['downloader']:
        options['rm_after_extract'] = cfg['downloader']['rm_after_extract']

    zendesk = Zendesk(cfg['credentials']['username'], cfg['credentials']['password'], cfg['credentials']['url'], options=options)

    if '{0}'.format(arguments['--case']) == 'None':
        logger.info("No case specified, downloading attachments for all cases with updates in the last {0} hours".format(arguments['--recent']))
        start_time = datetime.datetime.now() - datetime.timedelta(hours=int(arguments['--recent']))
        updated_tickets =  zendesk.getUpdatedTickets(start_time)
        logger.debug(updated_tickets)
        if not "error" in updated_tickets:
            for ticket in updated_tickets['ids']:
                processTicket(ticket)
        else:
            logger.error(updated_tickets['error'])
    else:
        ticket = arguments['--case']
        processTicket(ticket)
Esempio n. 7
0
from zendesk import Zendesk

################################################################
## NEW CONNECTION CLIENT
################################################################
zendesk = Zendesk('https://yourcompany.zendesk.com', '*****@*****.**', 'passwd')

# Are you getting an error such as...
# "SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed"?
zendesk = Zendesk('https://yourcompany.zendesk.com', '*****@*****.**', 'passwd',
    client_args={
        "disable_ssl_certificate_validation": True
    }
)


################################################################
## TICKETS
################################################################

# List
zendesk.list_tickets(view_id=1) # Must have a view defined

# Create
new_ticket = {
    'ticket': { _
        'requester_name': 'Howard Schultz',
        'requester_email': '*****@*****.**',
        'subject':'My Starbucks coffee is cold!',
        'description': 'please reheat my coffee',
        'set_tags': 'coffee drinks',
Esempio n. 8
0
import re
from zendesk import Zendesk


def get_id_from_url(url):
    match = re.match(r".*/(?P<identifier>\d+)\.xml", url)
    if match and match.group('identifier'):
        return match.group('identifier')


################################################################
## NEW CONNECTION CLIENT
################################################################
zendesk = Zendesk('https://yourcompany.zendesk.com', '*****@*****.**',
                  'passwd')

################################################################
## TICKETS
################################################################

# List
zendesk.list_tickets(view_id=1)  # Must have a view defined

# Create
new_ticket = {
    'ticket': {
        'requester-name': 'Howard Schultz',
        'requester-email': '*****@*****.**',
        'subject': 'My Starbucks coffee is cold!',
        'description': 'please reheat my coffee',
        'set-tags': 'coffee drinks',
Esempio n. 9
0
    def __init__(self, settings):

        # Set up a set of globals to pass to every template
        self.gs_globals = {}

        # GENOMICS STATUS MAJOR VERSION NUMBER
        # Bump this with any change that requires an update to documentation
        self.gs_globals['gs_version'] = '1.0';

        # Get the latest git commit hash
        # This acts as a minor version number for small updates
        # It also forces javascript / CSS updates and solves caching problems
        try:
            self.gs_globals['git_commit'] = subprocess.check_output(['git', 'rev-parse', '--short=7', 'HEAD']).strip()
            self.gs_globals['git_commit_full'] = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
        except:
            self.gs_globals['git_commit'] = 'unknown'
            self.gs_globals['git_commit_full'] = 'unknown'

        handlers = [
            ("/", MainHandler),
            ("/login", LoginHandler),
            ("/logout", LogoutHandler),
            ("/unauthorized", UnAuthorizedHandler),
            ("/api/v1", DataHandler),
            ("/api/v1/applications", ApplicationsDataHandler),
            ("/api/v1/application/([^/]*)$", ApplicationDataHandler),
            ("/api/v1/bioinfo_analysis", BioinfoAnalysisHandler),
            ("/api/v1/bioinfo_analysis/([^/]*)$", BioinfoAnalysisHandler),
            ("/api/v1/expected", BarcodeVsExpectedDataHandler),
            tornado.web.URLSpec("/api/v1/caliper_image/(?P<project>[^/]+)/(?P<sample>[^/]+)/(?P<step>[^/]+)", CaliperImageHandler, name="CaliperImageHandler"),
            ("/api/v1/charon_summary/([^/]*)$",CharonProjectHandler ),
            ("/api/v1/delivered_monthly", DeliveredMonthlyDataHandler),
            ("/api/v1/delivered_monthly.png", DeliveredMonthlyPlotHandler),
            ("/api/v1/delivered_quarterly", DeliveredQuarterlyDataHandler),
            ("/api/v1/delivered_quarterly.png", DeliveredQuarterlyPlotHandler),
            ("/api/v1/flowcells", FlowcellsDataHandler),
            ("/api/v1/flowcell_count/", FlowcellCountApiHandler),
            ("/api/v1/flowcell_info2/([^/]*)$", FlowcellsInfoDataHandler),
            ("/api/v1/flowcell_info/([^/]*)$", OldFlowcellsInfoDataHandler),
            ("/api/v1/flowcell_qc/([^/]*)$", FlowcellQCHandler),
            ("/api/v1/flowcell_demultiplex/([^/]*)$",
                FlowcellDemultiplexHandler),
            ("/api/v1/flowcell_q30/([^/]*)$", FlowcellQ30Handler),
            # ("/api/v1/flowcells/([^/]*)$", FlowcellDataHandler),
            ("/api/v1/flowcell_notes/([^/]*)$", FlowcellNotesDataHandler),
            ("/api/v1/flowcell_links/([^/]*)$", FlowcellLinksDataHandler),
            ("/api/v1/flowcell_search/([^/]*)$", FlowcellSearchHandler),
            ("/api/v1/flowcell_yield/([^/]*)$", DataFlowcellYieldHandler),
            ("/api/v1/generate_workset", GenerateWorksetHandler),
            ("/api/v1/instrument_cluster_density",
                InstrumentClusterDensityDataHandler),
            ("/api/v1/instrument_cluster_density.png",
                InstrumentClusterDensityPlotHandler),
            ("/api/v1/instrument_error_rates", InstrumentErrorrateDataHandler),
            ("/api/v1/instrument_error_rates.png",
                InstrumentErrorratePlotHandler),
            ("/api/v1/instrument_logs", DataInstrumentLogsHandler),
            ("/api/v1/instrument_logs/([^/]*)$", DataInstrumentLogsHandler),
            ("/api/v1/instrument_names",InstrumentNamesHandler ),
            ("/api/v1/instrument_unmatched", InstrumentUnmatchedDataHandler),
            ("/api/v1/instrument_unmatched.png", InstrumentUnmatchedPlotHandler),
            ("/api/v1/instrument_yield", InstrumentYieldDataHandler),
            ("/api/v1/instrument_yield.png", InstrumentYieldPlotHandler),
            ("/api/v1/internal_costs/([^/]*)", ProjectInternalCostsHandler),
            ("/api/v1/last_updated", UpdatedDocumentsDatahandler),
            ("/api/v1/last_psul", LastPSULRunHandler),
            ("/api/v1/load_workset_samples", WorksetSampleLoadHandler),
            ("/api/v1/plot/q30.png", Q30PlotHandler),
            ("/api/v1/plot/samples_per_lane.png",
                SamplesPerLanePlotHandler),
            ("/api/v1/plot/reads_per_lane.png", ReadsPerLanePlotHandler),
            ("/api/v1/plot/clusters_per_lane.png", ClustersPerLanePlotHandler),
            ("/api/v1/plot/barcodes_vs_expected([^/]*)$", BarcodeVsExpectedPlotHandler),
            ("/api/v1/samples_per_lane", SamplesPerLaneDataHandler),
            ("/api/v1/produced_monthly", ProducedMonthlyDataHandler),
            ("/api/v1/produced_monthly.png", ProducedMonthlyPlotHandler),
            ("/api/v1/produced_quarterly", ProducedQuarterlyDataHandler),
            ("/api/v1/produced_quarterly.png", ProducedQuarterlyPlotHandler),
            ("/api/v1/projects", ProjectsDataHandler),
            ("/api/v1/project/([^/]*)$", ProjectSamplesDataHandler),
            ("/api/v1/project/([^/]*)/tickets", ProjectTicketsDataHandler),
            ("/api/v1/projects_fields", ProjectsFieldsDataHandler),
            ("/api/v1/project_summary/([^/]*)$", ProjectDataHandler),
            ("/api/v1/project_summary_update/([^/]*)/([^/]*)$", ProjectSummaryUpdateHandler),
            ("/api/v1/project_search/([^/]*)$", ProjectsSearchHandler),
            ("/api/v1/presets", PresetsHandler),
            ("/api/v1/qc/([^/]*)$", SampleQCDataHandler),
            ("/api/v1/projectqc/([^/]*)$", ProjectQCDataHandler),
            ("/api/v1/reads_vs_quality", ReadsVsQDataHandler),
            ("/api/v1/rna_report/([^/]*$)", ProjectRNAMetaDataHandler),
            ("/api/v1/running_notes/([^/]*)$", RunningNotesDataHandler),
            ("/api/v1/links/([^/]*)$", LinksDataHandler),
            ("/api/v1/sample_info/([^/]*)$", SampleInfoDataHandler),
            ("/api/v1/sample_readcount/(\w+)?", SampleReadCountDataHandler),
            ("/api/v1/sample_run_counts/(\w+)?",
                SampleRunReadCountDataHandler),
            ("/api/v1/sample_alignment/([^/]*)$",
                SampleQCAlignmentDataHandler),
            ("/api/v1/sample_coverage/([^/]*)$", SampleQCCoverageDataHandler),
            ("/api/v1/sample_summary/([^/]*)$", SampleQCSummaryDataHandler),
            ("/api/v1/sample_insert_sizes/([^/]*)$",
                SampleQCInsertSizesDataHandler),
            ("/api/v1/samples/start/([^/]*)$", PagedQCDataHandler),
            ("/api/v1/samples/([^/]*)$", SampleRunDataHandler),
            ("/api/v1/stats",StatsAggregationHandler),
            ("/api/v1/stats/application_open_projects",ApplicationOpenProjectsHandler),
            ("/api/v1/stats/application_open_samples",ApplicationOpenSamplesHandler),
            ("/api/v1/stats/week_instr_yield",WeekInstrumentTypeYieldHandler),
            ("/api/v1/stats/year_application",YearApplicationsProjectHandler),
            ("/api/v1/stats/year_application_samples",YearApplicationsSamplesHandler),
            ("/api/v1/stats/year_affiliation_projects",YearAffiliationProjectsHandler),
            ("/api/v1/stats/year_deliverytime_projects",YearDeliverytimeProjectsHandler),
            ("/api/v1/stats/year_deliverytime_application",YearDeliverytimeApplicationHandler),
            ("/api/v1/deliveries/set_bioinfo_responsible$", DeliveriesPageHandler),
            ("/api/v1/suggestions", SuggestionBoxDataHandler),
            ("/api/v1/test/(\w+)?", TestDataHandler),
            ("/api/v1/phix_err_rate", PhixErrorRateDataHandler),
            ("/api/v1/worksets", WorksetsDataHandler),
            ("/api/v1/workset/([^/]*)$", WorksetDataHandler),
            ("/api/v1/workset_search/([^/]*)$", WorksetSearchHandler),
            ("/api/v1/workset_notes/([^/]*)$", WorksetNotesDataHandler),
            ("/api/v1/workset_links/([^/]*)$", WorksetLinksHandler),
            ("/api/v1/ws_pl_to_lims", WorksetPlacementSavingHandler),
            ("/applications", ApplicationsHandler),
            ("/application/([^/]*)$", ApplicationHandler),
            ("/barcode_vs_expected", ExpectedHandler),
            ("/bioinfo/(P[^/]*)$", BioinfoAnalysisHandler),
            ("/deliveries", DeliveriesPageHandler),
            ("/clusters_per_lane", ClustersPerLaneHandler),
            ("/flowcells", FlowcellsHandler),
            ("/flowcells/([^/]*)$", FlowcellHandler),
            ("/flowcells_plot", FlowcellPlotHandler),
            ("/flowcell_count_plot", FlowcellCountPlotHandler),
            ("/instrument_logs",InstrumentLogsHandler),
            ("/instrument_logs/([^/]*)$", InstrumentLogsHandler),
            ("/multiqc_report/([^/]*)$", MultiQCReportHandler),
            ("/nas_quotas", NASQuotasHandler),
            ("/q30", Q30Handler),
            ("/qc/([^/]*)$", SampleQCSummaryHandler),
            (r"/qc_reports/(.*)", SafeStaticFileHandler, {"path": 'qc_reports'}),
            ("/quotas", QuotasHandler),
            ("/phix_err_rate", PhixErrorRateHandler),
            ("/production", ProductionHandler),
            ("/production/cronjobs", ProductionCronjobsHandler),
            ("/project/([^/]*)$", ProjectSamplesHandler),
            ("/project/(P[^/]*)/([^/]*)$", ProjectSamplesHandler),
            ("/project_summary/([^/]*)$", ProjectSummaryHandler),
            ("/projects/([^/]*)$", ProjectsHandler),
            ("/proj_meta", ProjMetaCompareHandler),
            ("/reads_total/([^/]*)$", ReadsTotalHandler),
            ("/reads_vs_qv", ReadsVsQvhandler),
            ("/reads_per_lane", ReadsPerLaneHandler),
            ("/rec_ctrl_view/([^/]*)$", RecCtrlDataHandler),
            ("/samples_per_lane", SamplesPerLaneHandler),
            ("/samples/([^/]*)$", SampleRunHandler),
            ("/sequencing", SequencingStatsHandler),
            ("/suggestion_box", SuggestionBoxHandler),
            ("/worksets", WorksetsHandler),
            ("/workset/([^/]*)$", WorksetHandler),
            ("/workset_placement",WorksetPlacementHandler),
            (r'.*', BaseHandler)
        ]

        self.declared_handlers = handlers

        # Load templates
        self.loader = template.Loader("design")

        # Global connection to the database
        couch = Server(settings.get("couch_server", None))
        if couch:
            self.analysis_db= couch["analysis"]
            self.application_categories_db = couch["application_categories"]
            self.bioinfo_db = couch["bioinfo_analysis"]
            self.cronjobs_db = couch["cronjobs"]
            self.flowcells_db = couch["flowcells"]
            self.gs_users_db = couch["gs_users"]
            self.instruments_db= couch["instruments"]
            self.instrument_logs_db = couch["instrument_logs"]
            self.projects_db = couch["projects"]
            self.samples_db = couch["samples"]
            self.server_status_db = couch['server_status']
            self.suggestions_db = couch["suggestion_box"]
            self.worksets_db = couch["worksets"]
            self.x_flowcells_db = couch["x_flowcells"]
        else:
            print settings.get("couch_server", None)
            raise IOError("Cannot connect to couchdb");

        # Load columns and presets from genstat-defaults user in StatusDB
        genstat_id = ''
        for u in self.gs_users_db.view('authorized/users'):
            if u.get('key') == 'genstat-defaults':
                genstat_id = u.get('value')

        # It's important to check that this user exists!
        if not genstat_id:
            raise RuntimeError("genstat-defaults user not found on {}, please " \
                               "make sure that the user is abailable with the " \
                               "corresponding defaults information.".format(settings.get("couch_server", None)))

        # We need to get this database as OrderedDict, so the pv_columns doesn't
        # mess up
        user = settings.get("username", None)
        password = settings.get("password", None)
        headers = {"Accept": "application/json",
                   "Authorization": "Basic " + "{}:{}".format(user, password).encode('base64')[:-1]}
        decoder = json.JSONDecoder(object_pairs_hook=OrderedDict)
        user_url = "{}/gs_users/{}".format(settings.get("couch_server"), genstat_id)
        json_user = requests.get(user_url, headers=headers).content.rstrip()

        self.genstat_defaults = decoder.decode(json_user)

        # Load private instrument listing
        self.instrument_list = settings.get("instruments")

        # If settings states  mode, no authentication is used
        self.test_mode = settings["Testing mode"]

        # google oauth key
        self.oauth_key = settings["google_oauth"]["key"]

        # ZenDesk
        self.zendesk_url = settings["zendesk"]["url"]
        self.zendesk_user = settings["zendesk"]["username"]
        self.zendesk_token = settings["zendesk"]["token"]
        self.zendesk = Zendesk(self.zendesk_url, use_api_token=True, zendesk_username=self.zendesk_user,
                                zendesk_password=self.zendesk_token, api_version=2)

        # Trello
        self.trello_api_key = settings['trello']['api_key']
        self.trello_api_secret = settings['trello']['api_secret']
        self.trello_token = settings['trello']['token']

        # Load password seed
        self.password_seed = settings.get("password_seed")

        # load logins for the genologics sftp
        self.genologics_login=settings['sftp']['login']
        self.genologics_pw=settings['sftp']['password']

        # Location of the psul log
        self.psul_log=settings.get("psul_log")


        # index page - to display quotas of uppmax projects
    	self.uppmax_projects = settings.get('uppmax_projects')
        # to display instruments in the server status
        self.server_status = settings.get('server_status')

        # project summary - multiqc tab
        self.multiqc_path = settings.get('multiqc_path')

        # Setup the Tornado Application
        cookie_secret = base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)
        settings["debug"]= True
        settings["static_path"]= "static"
        settings["cookie_secret"]= cookie_secret
        settings["login_url"]= "/login"


        if options['develop']:
            tornado.autoreload.watch("design/application.html")
            tornado.autoreload.watch("design/applications.html")
            tornado.autoreload.watch("design/barcode_vs_expected.html")
            tornado.autoreload.watch("design/base.html")
            tornado.autoreload.watch("design/bioinfo_tab.html")
            tornado.autoreload.watch("design/bioinfo_tab/run_lane_sample_view.html")
            tornado.autoreload.watch("design/bioinfo_tab/sample_run_lane_view.html")
            tornado.autoreload.watch("design/clusters_per_lane.html")
            tornado.autoreload.watch("design/cronjobs.html")
            tornado.autoreload.watch("design/deliveries.html")
            tornado.autoreload.watch("design/error_page.html")
            tornado.autoreload.watch("design/flowcell.html")
            tornado.autoreload.watch("design/flowcell_error.html")
            tornado.autoreload.watch("design/flowcell_samples.html")
            tornado.autoreload.watch("design/flowcells.html")
            tornado.autoreload.watch("design/index.html")
            tornado.autoreload.watch("design/instrument_logs.html")
            tornado.autoreload.watch("design/link_tab.html")
            tornado.autoreload.watch("design/nas_quotas.html")
            tornado.autoreload.watch("design/phix_err_rate.html")
            tornado.autoreload.watch("design/production.html")
            tornado.autoreload.watch("design/proj_meta_compare.html")
            tornado.autoreload.watch("design/project_samples.html")
            tornado.autoreload.watch("design/project_summary.html")
            tornado.autoreload.watch("design/projects.html")
            tornado.autoreload.watch("design/q30.html")
            tornado.autoreload.watch("design/reads_per_lane.html")
            tornado.autoreload.watch("design/reads_total.html")
            tornado.autoreload.watch("design/reads_vs_qv.html")
            tornado.autoreload.watch("design/rec_ctrl_view.html")
            tornado.autoreload.watch("design/running_notes_help.html")
            tornado.autoreload.watch("design/running_notes_tab.html")
            tornado.autoreload.watch("design/samples_per_lane.html")
            tornado.autoreload.watch("design/sequencing_stats.html")
            tornado.autoreload.watch("design/suggestion_box.html")
            tornado.autoreload.watch("design/unauthorized.html")
            tornado.autoreload.watch("design/uppmax_quotas.html")
            tornado.autoreload.watch("design/workset_placement.html")
            tornado.autoreload.watch("design/workset_samples.html")
            tornado.autoreload.watch("design/worksets.html")
            tornado.autoreload.watch("design/yield_plot.html")

        tornado.web.Application.__init__(self, handlers, **settings)
Esempio n. 10
0
def config(argv=None):
    import os, sys, argparse

    # Declare a class for an argparse custom action.
    # Handles converting ascii input from argparse that may contain unicode
    # to a real unicode string.
    class UnicodeStore(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            setattr(namespace, self.dest, values.decode('utf-8'))

    # Options precedence:
    # program state defaults, which are overridden by
    # ~/.zd.cfg [zdgrab] section options, which are overridden by
    # command line options, which are overridden by
    # -c CONFIG_FILE [zdgrab] section options, which are overridden by
    # ~/.zd.cfg [RUN_SECTION] section options, which are overridden by
    # -c CONFIG_FILE [RUN_SECTION] section options
    #
    # Program state, with defaults
    #
    state = {
        'verbose': False,
        'tickets': None,
        'work_dir': os.path.join(os.path.expanduser('~'), 'zdgrab'),
        'agent': 'me',
        'url': None,
        'mail': None,
        'password': '******',
        'is_token': False,
    }

    argp = argparse.ArgumentParser(
        description='Download attachments from Zendesk tickets.')
    argp.add_argument('-v',
                      '--verbose',
                      action='store_true',
                      help='Verbose output')

    argp.add_argument(
        '-t',
        action=UnicodeStore,
        dest='tickets',
        help='Ticket(s) to grab attachments (default: all of your open tickets)'
    )

    argp.add_argument('-c',
                      action=UnicodeStore,
                      dest='config_file',
                      help='Configuration file (overrides ~/.zd.cfg)')

    argp.add_argument('-w',
                      action=UnicodeStore,
                      dest='work_dir',
                      help="""Working directory in which to store attachments.
        (default: ~/zdgrab/)""")

    argp.add_argument('-a',
                      action=UnicodeStore,
                      dest='agent',
                      help='Agent whose open tickets to search (default: me)')

    argp.add_argument('-u',
                      action=UnicodeStore,
                      dest='url',
                      help='URL of Zendesk (e.g. https://example.zendesk.com)')
    argp.add_argument('-m',
                      action=UnicodeStore,
                      dest='mail',
                      help='E-Mail address for Zendesk login')
    argp.add_argument('-p',
                      action=UnicodeStore,
                      dest='password',
                      help='Password for Zendesk login',
                      nargs='?',
                      const=state['password'])
    argp.add_argument(
        '-i',
        '--is-token',
        action='store_true',
        dest='is_token',
        help='Is token? Specify if password supplied a Zendesk token')

    # Set argparse defaults with program defaults.
    # Skip password as it is argparse const, not argparse default
    argp.set_defaults(**dict(
        (k, v) for k, v in state.iteritems() if k != 'password'))

    # Read ~/.zd.cfg [zdgrab] section and update argparse defaults
    try:
        config_state(os.path.join(os.path.expanduser('~'), '.zd.cfg'), 'zd',
                     state)
        # Password is OK now, because we either have one from the config file or
        # it is still None.
        argp.set_defaults(**dict((k, v) for k, v in state.iteritems()))
    except configparser.NoSectionError:
        # -c CONFIG_FILE did not have a [zdgrab] section. Skip it.
        pass

    # Parse the command line options
    if argv is None:
        argv = sys.argv
    args = argp.parse_args()

    # Update the program state with command line options
    for k in state.keys():
        state[k] = getattr(args, k)

    # -c CONFIG_FILE given on command line read args.config_file [zdgrab], update state
    if args.config_file:
        if state['verbose']:
            print('Reading config file {}'.format(args.config_file))
        try:
            config_state(args.config_file, 'zd', state)
        except configparser.NoSectionError:
            # -c CONFIG_FILE did not have a [zdgrab] section. Skip it.
            pass

    from zendesk import Zendesk
    if state['url'] and state['mail'] and state['password']:
        if state['verbose']:
            print(
                'Configuring Zendesk with:\n'
                '  url: {}\n'
                '  mail: {}\n'
                '  is_token: {}\n'
                '  password: (hidden)\n'.format(state['url'], state['mail'],
                                                repr(state['is_token'])))
        zd = Zendesk(state['url'],
                     zendesk_username=state['mail'],
                     zendesk_password=state['password'],
                     use_api_token=state['is_token'],
                     api_version=2)
    else:
        msg = textwrap.dedent("""\
            Error: Need Zendesk config to continue. Use -u, -m, -p options
            or a config file to provide the information.

            Config file (e.g. ~/.zd.cfg) should be something like:
            [zd]
            url = https://example.zendesk.com
            mail = [email protected]
            password = dneib393fwEF3ifbsEXAMPLEdhb93dw343
            is_token = 1
            agent = [email protected]
            """)
        print(msg)
        return 1

    # Log the state
    if state['verbose']:
        print('Running with program state:')
        # Let's go around our ass to get to our elbow to hide the password here.
        for (k, v) in [(k, v) for k, v in state.iteritems()
                       if k != 'password']:
            print('  {}: {}'.format(k, repr(v)))
        print('  password: (hidden)\n')

    # tickets=None means default to getting all of the attachments for this
    # user's open tickets. If tickets is given, try to split it into ints
    if state['tickets']:
        # User gave a list of tickets
        try:
            state['tickets'] = [int(i) for i in state['tickets'].split(',')]
        except ValueError:
            print('Error: Could not convert to integers: {}'.format(
                state['tickets']))
            return 1

    return zd, state