Example #1
0
	def __init__(self):
		self.zabbix_conf = '/etc/zabbix/zabbix_server.conf'
#		pdb.set_trace()
		try:
			self.ydata = yaml.safe_load(argv[2])
			subject=argv[1]
			event_id = self.ydata['event_id']
			event_status = self.ydata['event_status']
			log.debug('event_id:%s, event_status:%s subject: %s' % (event_id,event_status,subject))
			# Establish MySQL connection
			self.mysql_setup()
			# Zendesk setup
			self.mycsr.execute("SELECT lower(macro),value FROM globalmacro WHERE macro like '%ZENDESK%';")
			self.zdp = dict([ (macro[10:-1], value) for (macro,value) in self.mycsr.fetchall() ])
			self.zd = Zendesk(self.zdp['url'], self.zdp['email'], self.zdp['token'], api_version=2,
				use_api_token=True, client_args={ "disable_ssl_certificate_validation": True })
			log.debug('email:%s, enduser:%s' % (self.zdp['email'],self.zdp['enduser']))
			
			self.zd_user = self.get_zendesk_user(self.zdp['email'])
			self.zd_enduser = self.get_zendesk_user(self.zdp['enduser'])
			
			# If the status is 'OK' and we can find the ticket 
			# matching our external_id we close the ticket
			if not self.update_zendesk_ticket(event_id,event_status,subject):
				self.create_zendesk_ticket(event_id,event_status,subject)
			self.db.close()
			exit(0)
		except Exception as e:
			log.error('48 Failed with: [%s]. Ciao!' % e)
			exit(1)
Example #2
0
	def __init__(self, url, username, password, token):
		self._username = username
		self._password = password
		self._url = url
		self._token = token
		self._zd = Zendesk(self._url, self._username, self._password, self._token, api_version=2)
		self._headers = {'content-type': 'application/json'}
Example #3
0
	def __init__(self):
		if not argv[1].startswith('support@'):
			log.debug('wrong argument 1: %s' % argv[1] )
			exit(2)
		self.zabbix_conf = '/etc/zabbix/zabbix_server.conf'
		try:
			# Input data mangling
			self.ydata = yaml.load(argv[3])
			log.debug(argv[3])
			event_id = argv[2].split(':')[0]
			event_status = argv[2].split(':')[1].strip()
			log.debug('event_id:%s, event_status:%s' % (event_id,event_status))
			# Establish MySQL connection
			self.mysql_setup()
			# Zendesk setup
			self.mycsr.execute("SELECT lower(macro),value FROM globalmacro WHERE macro like '%ZENDESK%';")
			self.zdp = dict([ (macro[10:-1], value) for (macro,value) in self.mycsr.fetchall() ])
			self.zd = Zendesk(self.zdp['url'], self.zdp['email'], self.zdp['token'], api_version=2,
				use_api_token=True, client_args={ "disable_ssl_certificate_validation": True })
			self.zd_user = self.get_zendesk_user(self.zdp['email'])
			self.zd_enduser = self.get_zendesk_user(self.zdp['enduser'])
			
			# If the status is 'OK' and we can find the ticket 
			# matching our external_id we close the ticket
			if not self.update_zendesk_ticket(event_id,event_status):
				self.create_zendesk_ticket(event_id,event_status)
			self.db.close()
			exit(0)
		except Exception as e:
			log.error('Failed with: [%s]. Ciao!' % e)
			exit(1)
Example #4
0
    def __init__(self):
        if not argv[1].startswith('support@'):
            log.debug('wrong argument 1: %s' % argv[1])
            exit(2)
        self.zabbix_conf = '/etc/zabbix/zabbix_server.conf'
        try:
            # Input data mangling
            self.ydata = yaml.load(argv[3])
            log.debug(argv[3])
            event_id = argv[2].split(':')[0]
            event_status = argv[2].split(':')[1].strip()
            log.debug('event_id:%s, event_status:%s' %
                      (event_id, event_status))
            # Establish MySQL connection
            self.mysql_setup()
            # Zendesk setup
            self.mycsr.execute(
                "SELECT lower(macro),value FROM globalmacro WHERE macro like '%ZENDESK%';"
            )
            self.zdp = dict([(macro[10:-1], value)
                             for (macro, value) in self.mycsr.fetchall()])
            self.zd = Zendesk(
                self.zdp['url'],
                self.zdp['email'],
                self.zdp['token'],
                api_version=2,
                use_api_token=True,
                client_args={"disable_ssl_certificate_validation": True})
            self.zd_user = self.get_zendesk_user(self.zdp['email'])
            self.zd_enduser = self.get_zendesk_user(self.zdp['enduser'])

            # If the status is 'OK' and we can find the ticket
            # matching our external_id we close the ticket
            if not self.update_zendesk_ticket(event_id, event_status):
                self.create_zendesk_ticket(event_id, event_status)
            self.db.close()
            exit(0)
        except Exception as e:
            log.error('Failed with: [%s]. Ciao!' % e)
            exit(1)
Example #5
0
def get_zendesk():
    """Instantiate and return a Zendesk client"""
    # Verify required Zendesk settings
    zendesk_url = settings.ZENDESK_URL
    zendesk_email = settings.ZENDESK_USER_EMAIL
    zendesk_password = settings.ZENDESK_USER_PASSWORD
    if not zendesk_url or not zendesk_email or not zendesk_password:
        log.error('Zendesk settings error: please set ZENDESK_URL, '
                  'ZENDESK_USER_EMAIL and ZENDESK_USER_PASSWORD.')
        statsd.incr('questions.zendesk.settingserror')
        raise ZendeskSettingsError('Missing Zendesk settings.')

    return Zendesk(zendesk_url, zendesk_email, zendesk_password, api_version=2)
Example #6
0
def undo_last_ticket_migration():
    mapping_path = 'migration_data/Case/prod-mapping.json'
    mapping = json.load(open(mapping_path,'r', encoding='utf-8-sig'))

    ids = [str(value) for _,value in mapping.items()]

    batches=[]
    slices = round(len(ids)/100+0.5)
    slice_size = 100

    for i in range(slices):
        batches.append(ids[i*slice_size:slice_size + i*slice_size])

    zd_config = global_config['zendesk']
    zd = Zendesk(**zd_config)
    for batch in batches:
        if len(batch) >0:
            path = f'/tickets/destroy_many.json?ids={",".join(batch)}'
            response = zd.delete(path,'job_status')
            print(response)
    os.remove(mapping_path)
    print('Scheduled for deleting')
Example #7
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)
Example #8
0
class z2z:
    def __init__(self):
        if not argv[1].startswith('support@'):
            log.debug('wrong argument 1: %s' % argv[1])
            exit(2)
        self.zabbix_conf = '/etc/zabbix/zabbix_server.conf'
        try:
            # Input data mangling
            self.ydata = yaml.load(argv[3])
            log.debug(argv[3])
            event_id = argv[2].split(':')[0]
            event_status = argv[2].split(':')[1].strip()
            log.debug('event_id:%s, event_status:%s' %
                      (event_id, event_status))
            # Establish MySQL connection
            self.mysql_setup()
            # Zendesk setup
            self.mycsr.execute(
                "SELECT lower(macro),value FROM globalmacro WHERE macro like '%ZENDESK%';"
            )
            self.zdp = dict([(macro[10:-1], value)
                             for (macro, value) in self.mycsr.fetchall()])
            self.zd = Zendesk(
                self.zdp['url'],
                self.zdp['email'],
                self.zdp['token'],
                api_version=2,
                use_api_token=True,
                client_args={"disable_ssl_certificate_validation": True})
            self.zd_user = self.get_zendesk_user(self.zdp['email'])
            self.zd_enduser = self.get_zendesk_user(self.zdp['enduser'])

            # If the status is 'OK' and we can find the ticket
            # matching our external_id we close the ticket
            if not self.update_zendesk_ticket(event_id, event_status):
                self.create_zendesk_ticket(event_id, event_status)
            self.db.close()
            exit(0)
        except Exception as e:
            log.error('Failed with: [%s]. Ciao!' % e)
            exit(1)

    def create_zendesk_ticket(self, event_id, event_status):
        collaborators = self.zbx_evt_recipients(event_id)
        subject = self.ydata['trigger']['name']
        #description = '%s\n\nZabbix severity: %s' % (self.ydata['desc'],self.ydata['trigger']['severity'])
        description = self.ydata['desc'].replace('"', '')
        priority = 'high' if self.ydata['trigger'][
            'severity'] == 'High' else 'normal'
        tkt_data = {
            'ticket': {
                'subject': subject,
                'description': description,
                'collaborators': collaborators,
                'set_tags': ['test'],
                'external_id': event_id,
                'priority': priority,
                'requester_id': self.zd_enduser['id'],
                'submitter_id': self.zd_enduser['id'],
                'organization_id': self.zd_enduser['organization_id'],
            }
        }
        ### Auto-close if status is "OK" and severity is "information"
        if event_status == 'OK' and self.ydata['trigger'][
                'severity'] == 'Information':
            tkt_data['ticket']['status'] = 'solved'
            tkt_data['ticket']['assignee_id'] = self.zd_user['id']

        ### TODO: ADD TKT_ID as acknowledge comment
        tkt_url = self.zd.create_ticket(data=tkt_data)
        tkt_id = get_id_from_url(tkt_url)
        #tkt = self.zd.show_ticket(ticket_id=tkt_id)
        #log.debug('Created ticket with ID %s'%tkt_id)
        #log.debug(json.dumps(tkt,sort_keys=True,indent=2))
        log.info('Created Zendesk ticket ID %s from Zabbix eventid %s' %
                 (tkt_id, event_id))
        #return tkt_id

    def update_zendesk_ticket(self, event_id, event_status):
        if event_status == 'OK':
            tkt = self.zd.list_all_tickets(external_id=event_id)
            log.debug(tkt)  # json.dumps(tkt,sort_keys=True,indent=2)
            if tkt['count'] == 1:
                tkt_id = tkt['tickets'][0]['id']
                desc = self.ydata['desc'].replace('"', '')
                #log.info('Update ticket %s' % tkt_id)
                if self.ydata['trigger']['severity'] == 'High':
                    tkt_data = {
                        'ticket': {
                            'comment': {
                                'public': True,
                                'body': desc
                            }
                        }
                    }
                    log.info('Updating ticket %s from Zabbix event %s' %
                             (tkt_id, event_id))
                else:
                    tkt_data = {
                        'ticket': {
                            'status': 'solved',
                            'assignee_id': self.zd_user['id'],
                            'comment': {
                                'public': True,
                                'author_id': self.zd_enduser['id'],
                                'body': '%s\n(Auto-closed by Zabbix)' % desc
                            }
                        }
                    }
                    log.info('Closing Zendesk ticket %s, event id: %s' %
                             (tkt_id, event_id))

                tkt_up = self.zd.update_ticket(ticket_id=tkt_id, data=tkt_data)
                #log.debug(json.dumps(tkt_up,sort_keys=True,indent=2))
                return True
        return False

    def mysql_setup(self):
        try:
            # Get MySQL connection parameters from zabbix conf file
            with open(self.zabbix_conf) as f:
                my = dict(ln.lower()[2:].split('=')
                          for ln in f.read().split('\n')
                          if ln.startswith('DB'))
            self.db = MySQLdb.connect(my['host'], my['user'], my['password'],
                                      my['name'])
            self.mycsr = self.db.cursor()
        except IOError as e:
            log.error(e)
            return False
        except KeyError as e:
            log.error('Could not find %s' % e)
            return False
        else:
            return True

    def get_zendesk_user(self, email):
        cache_file = '/tmp/zendesk_user_%s' % email
        try:
            if time() - path.getmtime(cache_file) > 86400:
                remove(cache_file)
                log.debug('Cache file deleted')
            with open(cache_file, 'r') as f:
                data = yaml.load(f.read())
        except:
            data = self.zd.search_user(query='email:%s' % email)['users'][0]
            with open(cache_file, 'w') as f:
                f.write(yaml.dump(data))

        return data

    def zbx_evt_recipients(self, event_id):
        rows = ['*****@*****.**']
        try:
            sql = """SELECT m.sendto mail
FROM events e,functions f,items i, hosts_groups hg, groups g, users_groups uxg, usrgrp ug, media m
WHERE e.eventid=%s 
AND e.object=0 
AND e.source=0 
AND e.objectid=f.triggerid 
AND f.itemid=i.itemid 
AND hg.hostid=i.hostid 
AND ug.usrgrpid=uxg.usrgrpid
AND m.userid=uxg.userid 
AND LOWER(g.name)=LOWER(ug.name) 
AND hg.groupid=g.groupid;"""
            self.mycsr.execute(sql % event_id)
            rows.extend([r[0] for r in self.mycsr.fetchall()])
            return rows
        except:
            return rows
Example #9
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 = {
Example #10
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})
Example #11
0
def get_zd_instance():
    migration_plan = json.load(open('migration_plan.json', 'r'))
    zd_config = migration_plan['zendesk']
    return Zendesk(**zd_config)
Example #12
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
Example #13
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',
    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",
Example #15
0
import re
from zendesk import Zendesk

def get_id_from_url(url):
    match = re.match(r".*/(?P<identifier>\d+)\.(json|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',
        'ticket-field-entries': {
            '@type': 'array',
Example #16
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)
                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 =  {
Example #18
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',
Example #19
0
class z2z:
	def __init__(self):
		if not argv[1].startswith('support@'):
			log.debug('wrong argument 1: %s' % argv[1] )
			exit(2)
		self.zabbix_conf = '/etc/zabbix/zabbix_server.conf'
		try:
			# Input data mangling
			self.ydata = yaml.load(argv[3])
			log.debug(argv[3])
			event_id = argv[2].split(':')[0]
			event_status = argv[2].split(':')[1].strip()
			log.debug('event_id:%s, event_status:%s' % (event_id,event_status))
			# Establish MySQL connection
			self.mysql_setup()
			# Zendesk setup
			self.mycsr.execute("SELECT lower(macro),value FROM globalmacro WHERE macro like '%ZENDESK%';")
			self.zdp = dict([ (macro[10:-1], value) for (macro,value) in self.mycsr.fetchall() ])
			self.zd = Zendesk(self.zdp['url'], self.zdp['email'], self.zdp['token'], api_version=2,
				use_api_token=True, client_args={ "disable_ssl_certificate_validation": True })
			self.zd_user = self.get_zendesk_user(self.zdp['email'])
			self.zd_enduser = self.get_zendesk_user(self.zdp['enduser'])
			
			# If the status is 'OK' and we can find the ticket 
			# matching our external_id we close the ticket
			if not self.update_zendesk_ticket(event_id,event_status):
				self.create_zendesk_ticket(event_id,event_status)
			self.db.close()
			exit(0)
		except Exception as e:
			log.error('Failed with: [%s]. Ciao!' % e)
			exit(1)

	
	def create_zendesk_ticket(self,event_id,event_status):
		collaborators = self.zbx_evt_recipients(event_id)	
		subject = self.ydata['trigger']['name']
		#description = '%s\n\nZabbix severity: %s' % (self.ydata['desc'],self.ydata['trigger']['severity'])
		description = self.ydata['desc'].replace('"','')
		priority = 'high' if self.ydata['trigger']['severity'] == 'High' else 'normal'
		tkt_data = { 'ticket': {
			'subject': subject,
			'description': description,
			'collaborators': collaborators,
			'set_tags': ['test'],
			'external_id': event_id,
			'priority': priority,
			'requester_id': self.zd_enduser['id'],
			'submitter_id': self.zd_enduser['id'],
			'organization_id': self.zd_enduser['organization_id'],
		}}
		### Auto-close if status is "OK" and severity is "information"
		if event_status == 'OK' and self.ydata['trigger']['severity'] == 'Information':
			tkt_data['ticket']['status'] = 'solved'
			tkt_data['ticket']['assignee_id'] = self.zd_user['id']

		### TODO: ADD TKT_ID as acknowledge comment
		tkt_url = self.zd.create_ticket(data=tkt_data)
		tkt_id = get_id_from_url(tkt_url)
		#tkt = self.zd.show_ticket(ticket_id=tkt_id)
		#log.debug('Created ticket with ID %s'%tkt_id)
		#log.debug(json.dumps(tkt,sort_keys=True,indent=2))
		log.info('Created Zendesk ticket ID %s from Zabbix eventid %s' % (tkt_id,event_id))
		#return tkt_id


	def update_zendesk_ticket(self,event_id,event_status):
		if event_status == 'OK':
			tkt = self.zd.list_all_tickets(external_id=event_id)
			log.debug(tkt) # json.dumps(tkt,sort_keys=True,indent=2)
			if tkt['count']==1:
				tkt_id = tkt['tickets'][0]['id']
				desc = self.ydata['desc'].replace('"','')
				#log.info('Update ticket %s' % tkt_id)
				if self.ydata['trigger']['severity'] == 'High':
					tkt_data = {'ticket':{
						'comment':{'public':True, 'body': desc}
					}}
					log.info('Updating ticket %s from Zabbix event %s' % (tkt_id,event_id))
				else:
					tkt_data = {'ticket':{
						'status': 'solved',
						'assignee_id': self.zd_user['id'],
						'comment':{
							'public':True, 
							'author_id': self.zd_enduser['id'],
							'body': '%s\n(Auto-closed by Zabbix)'%desc
						}
					}}
					log.info('Closing Zendesk ticket %s, event id: %s' % (tkt_id,event_id))

				tkt_up = self.zd.update_ticket(ticket_id=tkt_id,data=tkt_data)
				#log.debug(json.dumps(tkt_up,sort_keys=True,indent=2))
				return True
		return False

	
	def mysql_setup(self):
		try:
			# Get MySQL connection parameters from zabbix conf file
			with open(self.zabbix_conf) as f:
				my = dict( ln.lower()[2:].split('=') for ln in
					f.read().split('\n') if ln.startswith('DB') )
			self.db = MySQLdb.connect(my['host'], my['user'], my['password'], my['name'])
			self.mycsr = self.db.cursor()
		except IOError as e:
			log.error(e)
			return False
		except KeyError as e: 
			log.error('Could not find %s'%e)
			return False
		else:
			return True


	def get_zendesk_user(self,email):
		cache_file = '/tmp/zendesk_user_%s' % email
		try:
			if time()-path.getmtime(cache_file) > 86400:
				remove(cache_file)
				log.debug('Cache file deleted')
			with open(cache_file, 'r') as f: 
				data = yaml.load(f.read())
		except:
			data = self.zd.search_user(query='email:%s'%email)['users'][0]
			with open(cache_file, 'w') as f: 
				f.write(yaml.dump(data) )
		
		return data
			

	def zbx_evt_recipients(self,event_id):
		rows = ['*****@*****.**']
		try:
			sql = """SELECT m.sendto mail
FROM events e,functions f,items i, hosts_groups hg, groups g, users_groups uxg, usrgrp ug, media m
WHERE e.eventid=%s 
AND e.object=0 
AND e.source=0 
AND e.objectid=f.triggerid 
AND f.itemid=i.itemid 
AND hg.hostid=i.hostid 
AND ug.usrgrpid=uxg.usrgrpid
AND m.userid=uxg.userid 
AND LOWER(g.name)=LOWER(ug.name) 
AND hg.groupid=g.groupid;"""
			self.mycsr.execute(sql % event_id)
			rows.extend([ r[0] for r in self.mycsr.fetchall() ])
			return rows
		except:
			return rows
Example #20
0
class ZendeskTask(object):

	_username 	= ""
	_url 		= ""
	_password 	= ""
	_token 		= ""
	_headers	= {}

	def __init__(self, url, username, password, token):
		self._username = username
		self._password = password
		self._url = url
		self._token = token
		self._zd = Zendesk(self._url, self._username, self._password, self._token, api_version=2)
		self._headers = {'content-type': 'application/json'}

	def search_by_email(self, email):
		return self._zd.search_user(query=email)

	def get_all_organizations(self):
		zen_orgs = []
		runLoop = True
		page = 1

		while runLoop:		
			results = self._zd.list_organizations(page=page)

			if int(results['count']) > 0:
				for org in results['organizations']:
					zen_orgs.append(org)
				page+=1
			if results['next_page'] is None:
				runLoop = False

		return zen_orgs

	def update_organization(self, orgId, data):
		return self._zd.update_organization(organization_id=orgId, data=data)

	def update_organization_v2(self, orgId, data):
		# Use requests module instead
		username = self._username + '/token'
		url = '{0}/api/v2/organizations/{1}.json'.format(self._url, orgId)
		r = requests.put(url, auth=(username, self._password), headers=self._headers, data=json.dumps(data))
		return r.content

	def create_organization(self, data):
		return self._zd.create_organization(data=data)

	def create_organization_v2(self, data):
		# Use requests module instead
		username = self._username + '/token'
		url = '{0}/api/v2/organizations.json'.format(self._url)
		r = requests.post(url, auth=(username, self._password), headers=self._headers, data=json.dumps(data))
		return r.content
	
	def update_user(self, userId, data):
		return self._zd.update_user(user_id=userId, data=data)

	def list_organization_fields(self):
		r = self._zd.list_organization_fields()
		return { "count" : r['count'], "fields" : r['organization_fields'] }

	def search_organization_by_name(self, name):
		return self._zd.autocomplete_organizations(name=name)

	def get_existing_organization_field_options(self, field_id):
		return self._zd.show_organization_field(field_id=field_id)['organization_field']['custom_field_options']

	def add_organization_field_dropdown(self, field_id, field_name='Vict0r Duan', field_value='test1'):
		# Dropdown fields need all options to be added
		existing_fields = self.get_existing_organization_field_options(field_id=field_id)

		existing_fields.append({ 'name' : field_name, 'value' : field_value })
		data = { "organization_field" : { "custom_field_options" : [{"name": "test", "value": "test2"}] }}
		try:
			print data
			print self._zd.update_organization_fields(field_id=field_id, data=data)
		except Exception, err:
			print err
			return self.get_existing_organization_field_options(field_id=field_id)

		return self.get_existing_organization_field_options(field_id=field_id)
Example #21
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
Example #22
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
Example #23
0
import requests as r
import json as j
from trello import Trello
from zendesk import Zendesk

trl = Trello()
zd = Zendesk()


def create_ticket_card(id):
    tk = zd.get_ticket(id)
    ticket_name = f"{id} - {tk['ticket']['subject']}"
    ticket_desc = tk['ticket']['description']

    response = trl.create_card(ticket_name, ticket_desc)

    if response == r.codes.ok:
        print(f'Card do ticket {id} criado com sucesso.')
from zendesk import Zendesk, get_id_from_url
import httplib2
import simplejson

	################################################################
	## NEW CONNECTION CLIENT
	################################################################
zendesk = Zendesk('https://23andme.zendesk.com', '*****@*****.**', 'lC3mXMSIU3aF9z8bsLXZEqNktxz3Q4kbwcBgehN3')

	################################################################
	## 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',
	#         'ticket_field_entries': [
	#             {
	#                 'ticket_field_id': 1,
	#                 'value': 'venti'
	#             },
	#             {
	#                 'ticket_field_id': 2,