def close_incidents(name, username): """This command will close a specific incident (running the close flow or all open incidents). Useful for development.""" from dispatch.incident.flows import incident_closed_flow from dispatch.incident.models import Incident from dispatch.database import SessionLocal install_plugins() incidents = [] db_session = SessionLocal() if not name: incidents = db_session.query(Incident).all() else: incidents = [ db_session.query(Incident).filter(Incident.name == x).first() for x in name ] for i in incidents: if i.conversation: if i.status == "Active": command = { "channel_id": i.conversation.channel_id, "user_id": username } try: incident_closed_flow(command=command, db_session=db_session, incident_id=i.id) except Exception: click.echo("Incident close failed.")
def get_zulip_client_by_org_id(org_id): try: session_local = SessionLocal() return_data = {} org_obj = org_get(db_session=session_local, org_id=org_id) if org_obj and org_obj.zulip_is_active: if org_id in all_zulip_client_dict: return_data = all_zulip_client_dict[org_id] else: all_zulip_client = {} config = get_api(org_obj.zulip_user_name, org_obj.zulip_password, org_obj.zulip_site) if config: client = zulip.Client(email=config.get('email'), api_key=config.get('api_key'), site=org_obj.zulip_site) all_zulip_client[org_obj.id] = { "org_obj": org_obj, "client": ZulipCore(org_obj, client), } return_data = all_zulip_client[org_obj.id] except Exception as e: log.error(f"get_zulip_client_by_org_id failure,msg={e}") finally: session_local.close() return return_data
def get_zulip_client(): try: all_zulip_client = {} session_local = SessionLocal() org_list = get_all_org(db_session=session_local) for org_obj in org_list: if not org_obj.zulip_is_active: continue config = get_api(org_obj.zulip_user_name, org_obj.zulip_password, org_obj.zulip_site) client = zulip.Client(email=config.get('email'), api_key=config.get('api_key'), site=org_obj.zulip_site) all_zulip_client[org_obj.id] = { "org_obj": org_obj, "client": ZulipCore(org_obj, client), } all_zulip_client[org_obj.id]['client'].init_subcribe_team() except Exception as e: log.error(f"_get_workers failure,msg={e}") finally: try: session_local.close() except: pass return all_zulip_client
def _get_workers(self): try: worker_list = [] session_local = SessionLocal() all_team = get_team_by_org_id_list(db_session=session_local, org_id=self.org_obj.id) use_zulip_team_list = [ team.id for team in all_team if team.flex_form_data.get('use_zulip', False) ] for team_id in use_zulip_team_list: inner_worker_list = get_worker_by_team( db_session=session_local, team_id=team_id) if inner_worker_list: worker_list.extend(inner_worker_list) worker_dict = defaultdict(list) for worker in worker_list: team_code = worker.team.code worker_dict[f"{self.org_obj.code}/{team_code}"].append(worker) except Exception as e: log.error(f"_get_workers failure,msg={e}") finally: session_local.close() return worker_dict
def add_planning_plugin( plugin_id: id, service_id: id, db_session: SessionLocal, planning_plugin_type=KandboxPlannerPluginType.kandbox_env, ): """Adds a planning_plugin.""" # We load the service service = service_service.get(db_session=db_session, service_id=service_id) # plugin = plugin_service.get(db_session=db_session, plugin_id=plugin_id) # We get or create a new service_plugin service_plugin = get_or_create( db_session=db_session, service_id=service.id, plugin_id=plugin_id, planning_plugin_type=planning_plugin_type, ) service.planning_plugins.append(service_plugin) # We add and commit the changes db_session.add(service) db_session.commit() event_service.log( db_session=db_session, source="Kandbox Planning", description=f"{plugin.name} is added to service with type {planning_plugin_type}", # service_id=service_id, ) return service_plugin
def list_tasks(client: Any, file_id: str): """Returns all tasks in file.""" doc = get_file(client, file_id) document_meta = {"document": {"id": file_id, "name": doc["name"]}} all_comments = list_comments(client, file_id) task_comments = filter_comments(all_comments) tasks = [] for t in task_comments: status = get_task_status(t) assignees = get_assignees(t["content"]) description = (t.get("quotedFileContent", {}).get("value", ""), ) tickets = get_tickets(t["replies"]) # this is a dirty hack because google doesn't return emailAddresses for comments # complete with conflicting docs # https://developers.google.com/drive/api/v2/reference/comments#resource from dispatch.database import SessionLocal from dispatch.individual.models import IndividualContact db_session = SessionLocal() owner = (db_session.query(IndividualContact).filter( IndividualContact.name == t["author"]["displayName"]).first()) if not owner: log.error( f"Unable to identify owner by displayName: {t['author']['displayName']}" ) continue db_session.close() task_meta = { "task": { "id": t["id"], "status": status, "description": description, "owner": owner.email, "created_at": t["createdTime"], "assignees": assignees, "tickets": tickets, "web_link": f'https://docs.google.com/a/{GOOGLE_DOMAIN}/document/d/{file_id}/edit?disco={t["id"]}', } } tasks.append({**document_meta, **task_meta}) return tasks
def register(self, cls): from dispatch.database import SessionLocal from dispatch.plugin import service as plugin_service from dispatch.plugin.models import Plugin db_session = SessionLocal() record = plugin_service.get_by_slug(db_session=db_session, slug=cls.slug) if not record: plugin = Plugin( title=cls.title, slug=cls.slug, type=cls.type, version=cls.version, author=cls.author, author_url=cls.author_url, required=cls.required, multiple=cls.multiple, description=cls.description, enabled=cls.enabled, ) db_session.add(plugin) else: # we only update values that should change record.tile = cls.title record.version = cls.version record.author = cls.author record.author_url = cls.author_url record.description = cls.description db_session.add(record) db_session.commit() self.add(f"{cls.__module__}.{cls.__name__}") return cls
def register(self, cls): from dispatch.database import SessionLocal from dispatch.plugin import service as plugin_service from dispatch.plugin.models import Plugin db_session = SessionLocal() record = plugin_service.get_by_slug(db_session=db_session, slug=cls.slug) if cls.slug == "kandbox_env": logger.debug("Debugging loading kandbox_env") if not record: config = {} config_spec = {} try: config_spec = cls.config_form_spec config = cls.default_config except Exception as e: logger.warn( f"Unable to find config spec for plugin: {cls.slug}, type = {cls.type} " ) plugin = Plugin( title=cls.title, slug=cls.slug, type=cls.type, version=cls.version, author=cls.author, author_url=cls.author_url, required=cls.required, multiple=cls.multiple, description=cls.description, enabled=cls.enabled, config=config, config_form_spec=config_spec, ) db_session.add(plugin) else: # we only update values that should change record.tile = cls.title record.version = cls.version record.author = cls.author record.author_url = cls.author_url record.description = cls.description db_session.add(record) db_session.commit() db_session.close() self.add(f"{cls.__module__}.{cls.__name__}") return cls
def __init__(self, team_id=None): # Create the database connection. self.db_session = SessionLocal() self.cnx = self.db_session if team_id is None: # TODO In future, I get default from db raise Exception("internal error: team_id can not be None") else: self.team_id = team_id team = team_service.get(db_session=self.db_session, team_id=self.team_id) if team is None: raise Exception("team_id is invalid")
def reactivate_participant(user_email: str, incident_id: int, db_session: SessionLocal): """Reactivates a participant.""" # We load the incident incident = incident_service.get(db_session=db_session, incident_id=incident_id) # We get information about the individual contact_plugin = plugin_service.get_active(db_session=db_session, plugin_type="contact") individual_info = contact_plugin.instance.get(user_email) individual_fullname = individual_info["fullname"] log.debug( f"Reactivating {individual_fullname} on incident {incident.name}...") participant = get_by_incident_id_and_email(db_session=db_session, incident_id=incident_id, email=user_email) if not participant: log.debug( f"{individual_fullname} is not an inactive participant of incident {incident.name}." ) return False # We mark the participant as active participant.is_active = True # We create a role for the participant participant_role_in = ParticipantRoleCreate( role=ParticipantRoleType.participant) participant_role = participant_role_service.create( db_session=db_session, participant_role_in=participant_role_in) participant.participant_roles.append(participant_role) # We add and commit the changes db_session.add(participant) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description=f"{individual_fullname} reactivated", incident_id=incident_id, ) return True
def remove_participant(user_email: str, incident_id: int, db_session: SessionLocal): """Removes a participant.""" # We load the incident incident = incident_service.get(db_session=db_session, incident_id=incident_id) # We get information about the individual contact_plugin = plugin_service.get_active(db_session=db_session, plugin_type="contact") individual_info = contact_plugin.instance.get(user_email) individual_fullname = individual_info["fullname"] log.debug( f"Removing {individual_fullname} from incident {incident.name}...") participant = get_by_incident_id_and_email(db_session=db_session, incident_id=incident_id, email=user_email) if not participant: log.debug( f"Can't remove {individual_fullname}. They're not an active participant of incident {incident.name}." ) return False # We mark the participant as inactive participant.is_active = False # We make the participant renounce to their active roles participant_active_roles = participant_role_service.get_all_active_roles( db_session=db_session, participant_id=participant.id) for participant_active_role in participant_active_roles: participant_role_service.renounce_role( db_session=db_session, participant_role=participant_active_role) # We add and commit the changes db_session.add(participant) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description=f"{participant.individual.name} removed from incident", incident_id=incident_id, ) return True
def list_plugins(): """Shows all available plugins""" from dispatch.database import SessionLocal from dispatch.plugin import service as plugin_service db_session = SessionLocal() table = [] for p in plugins.all(): record = plugin_service.get_by_slug(db_session=db_session, slug=p.slug) installed = True if not record: installed = False table.append([ p.title, p.slug, p.version, installed, p.type, p.author, p.description ]) click.secho( tabulate( table, headers=[ "Title", "Slug", "Version", "Installed", "Type", "Author", "Description" ], ), fg="blue", )
async def process(client: SocketModeClient, req: SocketModeRequest): db_session = SessionLocal() background_tasks = BackgroundTasks() if req.type == "events_api": response = await handle_slack_event( db_session=db_session, client=client.web_client, request=req.payload, background_tasks=background_tasks, ) if req.type == "slash_commands": response = await handle_slack_command( db_session=db_session, client=client.web_client, request=req.payload, background_tasks=background_tasks, ) if req.type == "interactive": response = await handle_slack_action( db_session=db_session, client=client.web_client, request=req.payload, background_tasks=background_tasks, ) response = SocketModeResponse(envelope_id=req.envelope_id, payload=response) await client.send_socket_mode_response(response) # run the background tasks await background_tasks()
def remove_participant(user_email: str, incident_id: int, db_session: SessionLocal): """Removes a participant.""" # We load the incident incident = incident_service.get(db_session=db_session, incident_id=incident_id) # We get information about the individual contact_plugin = plugins.get(INCIDENT_PLUGIN_CONTACT_SLUG) individual_info = contact_plugin.get(user_email) individual_fullname = individual_info["fullname"] log.debug( f"Removing {individual_fullname} from incident {incident.name}...") participant = get_by_incident_id_and_email(db_session=db_session, incident_id=incident_id, email=user_email) if not participant: log.debug( f"Can't remove {individual_fullname}. They're not an active participant of incident {incident.name}." ) return False # We mark the participant as inactive participant.is_active = False # We make the participant renouce to their active roles participant_active_roles = participant_role_service.get_active_roles( db_session=db_session, participant_id=participant.id) for active_role in participant_active_roles: participant_role_service.renounce_role(db_session=db_session, participant_id=participant.id, role_type=active_role.role) # We add and commit the changes db_session.add(participant) db_session.commit() log.debug( f"Participant {participant.individual.name} has been removed from the incident." ) return True
def remove_planning_plugin(user_email: str, service_id: int, db_session: SessionLocal): """Removes a planning_plugin.""" # We load the service service = service_service.get(db_session=db_session, service_id=service_id) # We get information about the plugin contact_plugin = plugins.get(INCIDENT_PLUGIN_CONTACT_SLUG) plugin_info = contact_plugin.get(user_email) plugin_fullname = plugin_info["fullname"] log.debug(f"Removing {plugin_fullname} from service {service.name}...") planning_plugin = get_by_service_id_and_email( db_session=db_session, service_id=service_id, code=user_email ) if not planning_plugin: log.debug( f"Can't remove {plugin_fullname}. They're not an active planning_plugin of service {service.name}." ) return False # We mark the planning_plugin as inactive planning_plugin.is_active = False # We make the planning_plugin renounce to their active roles planning_plugin_active_roles = planning_plugin_role_service.get_all_active_roles( db_session=db_session, planning_plugin_id=planning_plugin.id ) for planning_plugin_active_role in planning_plugin_active_roles: planning_plugin_role_service.renounce_role( db_session=db_session, planning_plugin_role=planning_plugin_active_role ) # We add and commit the changes db_session.add(planning_plugin) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description=f"{planning_plugin.plugin.name} removed from service", service_id=service_id, ) return True
def db(): if database_exists(str(config.SQLALCHEMY_DATABASE_URI)): drop_database(str(config.SQLALCHEMY_DATABASE_URI)) create_database(str(config.SQLALCHEMY_DATABASE_URI)) Base.metadata.create_all(engine) # Create the tables. _db = SessionLocal() yield _db drop_database(str(config.SQLALCHEMY_DATABASE_URI))
def reactivate_planning_plugin(user_email: str, service_id: int, db_session: SessionLocal): """Reactivates a planning_plugin.""" # We load the service service = service_service.get(db_session=db_session, service_id=service_id) # We get information about the plugin contact_plugin = plugins.get(INCIDENT_PLUGIN_CONTACT_SLUG) plugin_info = contact_plugin.get(user_email) plugin_fullname = plugin_info["fullname"] log.debug(f"Reactivating {plugin_fullname} on service {service.name}...") planning_plugin = get_by_service_id_and_email( db_session=db_session, service_id=service_id, code=user_email ) if not planning_plugin: log.debug( f"{plugin_fullname} is not an inactive planning_plugin of service {service.name}." ) return False # We mark the planning_plugin as active planning_plugin.is_active = True # We create a role for the planning_plugin planning_plugin_role_in = ServicePluginRoleCreate(role=ServicePluginRoleType.planning_plugin) planning_plugin_role = planning_plugin_role_service.create( db_session=db_session, planning_plugin_role_in=planning_plugin_role_in ) planning_plugin.planning_plugin_role.append(planning_plugin_role) # We add and commit the changes db_session.add(planning_plugin) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description=f"{plugin_fullname} reactivated", service_id=service_id, ) return True
def uu_init_job_data(*, session: SessionLocal, data_list: list): try: i = 0 for update_job in data_list: _job_data = get_by_code(db_session=session, code=update_job['code']) if _job_data: # update update_job_new = JobUpdate(**update_job) update(db_session=session, job=_job_data, job_in=update_job_new) else: # add create(db_session=session, tags=[], scheduled_secondary_workers=[], **update_job) i += 1 return True if i > 0 else False except Exception as e: session.rollback() return False
def reactivate_participant(user_email: str, incident_id: int, db_session: SessionLocal): """Reactivates a participant.""" # We load the incident incident = incident_service.get(db_session=db_session, incident_id=incident_id) # We get information about the individual contact_plugin = plugins.get(INCIDENT_PLUGIN_CONTACT_SLUG) individual_info = contact_plugin.get(user_email) individual_fullname = individual_info["fullname"] log.debug( f"Reactivating {individual_fullname} on incident {incident.name}...") participant = get_by_incident_id_and_email(db_session=db_session, incident_id=incident_id, email=user_email) if not participant: log.debug( f"{individual_fullname} is not an inactive participant of incident {incident.name}." ) return False # We mark the participant as active participant.is_active = True # We create a role for the participant participant_role_in = ParticipantRoleCreate( role=ParticipantRoleType.participant) participant_role = participant_role_service.create( db_session=db_session, participant_role_in=participant_role_in) participant.participant_role.append(participant_role) # We add and commit the changes db_session.add(participant) db_session.commit() log.debug(f"{individual_fullname} has been reactivated.") return True
def add_participant(user_email: str, incident_id: id, db_session: SessionLocal, role: ParticipantRoleType = None): """Adds a participant.""" # We load the incident incident = incident_service.get(db_session=db_session, incident_id=incident_id) # We add the participant to the incident individual = individual_service.get_or_create(db_session=db_session, email=user_email) participant_role = participant_role_service.create(db_session=db_session, role=role) participant = get_or_create( db_session=db_session, incident_id=incident.id, individual_id=individual.id, role=participant_role, ) individual.participant.append(participant) incident.participants.append(participant) # We add and commit the changes db_session.add(individual) db_session.add(incident) db_session.commit() log.debug(f"{individual.name} has been added to incident {incident.name}.") return True
def save_status_report( user_email: str, conditions: str, actions: str, needs: str, incident_id: int, db_session: SessionLocal, ): """Saves a new status report.""" # we load the incident instance incident = incident_service.get(db_session=db_session, incident_id=incident_id) # we create a new status report status_report = create( db_session=db_session, conditions=conditions, actions=actions, needs=needs ) # we load the participant participant = participant_service.get_by_incident_id_and_email( db_session=db_session, incident_id=incident_id, email=user_email ) # we save the status report participant.status_reports.append(status_report) incident.status_reports.append(status_report) db_session.add(participant) db_session.add(incident) db_session.commit() log.debug(f"New status report created by {participant.individual.name}")
def create_reminder(db_session: SessionLocal, owner_email: str, documents: List[Document]): """Contains the logic for document evergreen reminders.""" # send email contact_fullname = contact_weblink = DISPATCH_HELP_EMAIL plugin = plugin_service.get_active(db_session=db_session, plugin_type="email") if not plugin: log.warning("Document reminder not sent, no email plugin enabled.") return notification_template = DOCUMENT_EVERGREEN_REMINDER items = [] for doc in documents: items.append({ "name": doc.name, "description": doc.description, "weblink": doc.weblink, }) notification_type = "document-evergreen-reminder" name = subject = notification_text = "Document Evergreen Reminder" plugin.instance.send( owner_email, notification_text, notification_template, notification_type, name=name, subject=subject, contact_fullname=contact_fullname, contact_weblink=contact_weblink, items=items, # plugin expect dicts ) for doc in documents: doc.evergreen_last_reminder_at = datetime.utcnow() db_session.add(doc) db_session.commit()
def update_user(email: str, role: str): """Updates a user's roles.""" from dispatch.database import SessionLocal from dispatch.auth import service as user_service from dispatch.auth.models import UserUpdate db_session = SessionLocal() user = user_service.get_by_email(email=email, db_session=db_session) if not user: click.secho(f"No user found. Email: {email}", fg="red") return user_service.update(user=user, user_in=UserUpdate(id=user.id, role=role), db_session=db_session) click.secho("User successfully updated.", fg="green")
def get_or_add_redis_team_flex_data(redis_conn, team_id): flex_form_data = {} try: db_session = None key = f"{team_id}_flex_form_data" if redis_conn.exists(key) <= 0: db_session = SessionLocal() team_data = get(db_session=db_session, team_id=team_id) redis_conn.set(key, json.dumps(team_data.flex_form_data)) flex_form_data = team_data.flex_form_data else: value = redis_conn.get(key) if isinstance(value, bytes): value = value.decode('utf-8') flex_form_data = json.loads(value) except: pass finally: if db_session: db_session.close() return flex_form_data
def populate_database(): """Populates database with default values.""" from dispatch.database import SessionLocal from dispatch.incident_type.models import IncidentType from dispatch.incident_priority.models import IncidentPriority, IncidentPriorityType db_session = SessionLocal() db_session.add( IncidentType(name="Other", slug="other", description="Default incident type.")) for i in IncidentPriorityType: db_session.add(IncidentPriority(name=i.value)) db_session.commit() click.secho("Success.", fg="green")
def uninstall_plugins(plugins): """Uninstalls all plugins, or only one.""" from dispatch.database import SessionLocal from dispatch.plugin import service as plugin_service db_session = SessionLocal() for plugin_slug in plugins: plugin = plugin_service.get_by_slug(db_session=db_session, slug=plugin_slug) if not plugin: click.secho( f"Plugin slug {plugin_slug} does not exist. Make sure you're passing the plugin's slug.", fg="red", ) plugin_service.delete(db_session=db_session, plugin_id=plugin.id)
def wrapper(*args, **kwargs): background = False if not kwargs.get("db_session"): db_session = SessionLocal() background = True kwargs["db_session"] = db_session if not kwargs.get("slack_client"): slack_client = dispatch_slack_service.create_slack_client() kwargs["slack_client"] = slack_client try: metrics_provider.counter("function.call.counter", tags={ "function": fullname(func), "slack": True }) start = time.perf_counter() result = func(*args, **kwargs) elapsed_time = time.perf_counter() - start metrics_provider.timer( "function.elapsed.time", value=elapsed_time, tags={ "function": fullname(func), "slack": True }, ) return result except Exception as e: # we generate our own guid for now, maybe slack provides us something we can use? slack_interaction_guid = str(uuid.uuid4()) log.exception( e, extra=dict(slack_interaction_guid=slack_interaction_guid)) # notify the user the interaction failed user_id = args[0] channel_id = args[2] message = f"Sorry, we've run into an unexpected error. For help, please reach out to the incident commander and provide them with the following token: {slack_interaction_guid}." dispatch_slack_service.send_ephemeral_message( kwargs["slack_client"], channel_id, user_id, message) finally: if background: kwargs["db_session"].close()
def install_plugins(force): """Installs all plugins, or only one.""" from dispatch.database import SessionLocal from dispatch.plugin import service as plugin_service from dispatch.plugin.models import Plugin db_session = SessionLocal() for p in plugins.all(): record = plugin_service.get_by_slug(db_session=db_session, slug=p.slug) if not record: click.secho( f"Installing plugin... Slug: {p.slug} Version: {p.version}", fg="blue") record = Plugin( title=p.title, slug=p.slug, type=p.type, version=p.version, author=p.author, author_url=p.author_url, required=p.required, multiple=p.multiple, description=p.description, enabled=p.enabled, ) db_session.add(record) if force: click.secho( f"Updating plugin... Slug: {p.slug} Version: {p.version}", fg="blue") # we only update values that should change record.tile = p.title record.version = p.version record.author = p.author record.author_url = p.author_url record.description = p.description record.required = p.required record.type = p.type db_session.add(record) db_session.commit()
def list_plugins(): """Shows all available plugins""" from dispatch.database import SessionLocal from dispatch.plugin import service as plugin_service db_session = SessionLocal() table = [] for p in plugins.all(): record = plugin_service.get_by_slug(db_session=db_session, slug=p.slug) if not record: log.warning( f"Plugin {p.slug} available, but not installed. Run `dispatch plugins install` to install it." ) continue table.append( [ record.title, record.slug, record.version, record.enabled, record.type, record.author, record.description, ] ) click.secho( tabulate( table, headers=[ "Title", "Slug", "Version", "Enabled", "Type", "Author", "Description", ], ), fg="blue", )
def incident_load_csv_command(input, first_row_is_header): """Load incidents via CSV.""" import csv from dispatch.database import SessionLocal from datetime import datetime from dispatch.incident import service as incident_service db_session = SessionLocal() if first_row_is_header: reader = csv.DictReader(input) for row in reader: incident = incident_service.get_by_name( db_session=db_session, incident_name=row["name"] ) if incident: incident.created_at = datetime.fromisoformat(row["created"]) else: click.secho(f"No incident found. Name: {row['name']}", fg="red")