From eb9e83f7727746604d8c0116e9622bb52d10f873 Mon Sep 17 00:00:00 2001 From: Guillaume Charest <1690085+gcharest@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:31:01 +0000 Subject: [PATCH 1/4] chore: move dev module to modules/dev folder --- app/main.py | 6 -- app/modules/dev/google_service.py | 93 +++++++++++++++++++++++++++++++ app/modules/google_service.py | 50 ----------------- app/modules/sre/sre.py | 7 +-- 4 files changed, 96 insertions(+), 60 deletions(-) create mode 100644 app/modules/dev/google_service.py delete mode 100644 app/modules/google_service.py diff --git a/app/main.py b/app/main.py index 69218cc0..28d986e4 100644 --- a/app/main.py +++ b/app/main.py @@ -6,7 +6,6 @@ from slack_bolt import App from dotenv import load_dotenv from modules import ( - google_service, secret, atip, aws, @@ -67,11 +66,6 @@ def main(bot): stop_run_continuously = scheduled_tasks.run_continuously() server_app.add_event_handler("shutdown", lambda: stop_run_continuously.set()) - # Register Google Service command for dev purposes only - if PREFIX == "dev-": - bot.command(f"/{PREFIX}google")(google_service.google_service_command) - bot.view("google_service_view")(google_service.open_modal) - def get_bot(): SLACK_TOKEN = os.environ.get("SLACK_TOKEN", None) diff --git a/app/modules/dev/google_service.py b/app/modules/dev/google_service.py new file mode 100644 index 00000000..b35bbeb7 --- /dev/null +++ b/app/modules/dev/google_service.py @@ -0,0 +1,93 @@ +"""Testing new google service (will be removed)""" +import os +import json +from datetime import datetime, timedelta, timezone +from integrations.google_workspace import ( + google_directory, + google_drive, + google_calendar, +) +from dotenv import load_dotenv + +load_dotenv() + +SRE_DRIVE_ID = os.environ.get("SRE_DRIVE_ID") +SRE_INCIDENT_FOLDER = os.environ.get("SRE_INCIDENT_FOLDER") +INCIDENT_TEMPLATE = os.environ.get("INCIDENT_TEMPLATE") + + +def open_modal(client, body, folders): + if not folders: + return + folder_names = [i["name"] for i in folders] + blocks = [ + {"type": "section", "text": {"type": "mrkdwn", "text": f"*{name}*"}} + for name in folder_names + ] + view = { + "type": "modal", + "title": {"type": "plain_text", "text": "Folder List"}, + "blocks": blocks, + } + client.views_open(trigger_id=body["trigger_id"], view=view) + + +def google_service_command(ack, client, body, respond): + # ack() + + # folders = google_drive.list_folders_in_folder(SRE_INCIDENT_FOLDER) + + # if not folders: + # respond("The folder ID is invalid. Please check the environment variables.") + # return + + # respond(f"Found {len(folders)} folders.") + + # files = google_drive.list_files_in_folder(SRE_INCIDENT_FOLDER) + + # if not files: + # respond("The folder ID is invalid. Please check the environment variables.") + # return + + # respond(f"Found {len(files)} files.") + + # find_docs = google_drive.get_file_by_name('incidents', SRE_INCIDENT_FOLDER) + # if not find_docs: + # respond("The folder ID is invalid. Please check the environment variables.") + # return + + # respond(f"Found {len(find_docs)} files.") + items = [ + {"id": "guillaume.charest@cds-snc.ca"}, + {"id": "sylvia.mclaughlin@cds-snc.ca"}, + ] + now = datetime.now(timezone.utc) + days = 1 + # time_min is the current time + days and time_max is the current time + 60 days + days + time_min = (now + timedelta(days=days)).isoformat() + time_max = (now + timedelta(days=(60 + days))).isoformat() + freebusy_results = google_calendar.get_freebusy(time_min, time_max, items) + # respond(freebusy_results) + response = json.dumps(freebusy_results, indent=4) + respond(response) + print(freebusy_results) + # respond(f"Healthcheck status: {google_drive.healthcheck()}") + # folders = google_drive.list_folders_in_folder(SRE_INCIDENT_FOLDER) + # if not folders: + # respond("The folder ID is invalid. Please check the environment variables.") + # return + # users = google_directory.list_users() + # if not users: + # respond("There was an error retrieving the users.") + # return + # respond(f"Found {len(users)} users.") + # groups = google_directory.list_groups() + # if not groups: + # respond("There was an error retrieving the groups.") + # return + # respond(f"Found {len(groups)} groups.") + # group_members = google_directory.list_group_members(groups[0]["id"]) + # if not group_members: + # respond("There was an error retrieving the group members.") + # return + # respond(f"Found {len(group_members)} group members in group {groups[0]['name']}.") diff --git a/app/modules/google_service.py b/app/modules/google_service.py deleted file mode 100644 index 8616f8c9..00000000 --- a/app/modules/google_service.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Testing new google service (will be removed)""" -import os - -from integrations.google_workspace import google_directory -from dotenv import load_dotenv - -load_dotenv() - -SRE_DRIVE_ID = os.environ.get("SRE_DRIVE_ID") -SRE_INCIDENT_FOLDER = os.environ.get("SRE_INCIDENT_FOLDER") -INCIDENT_TEMPLATE = os.environ.get("INCIDENT_TEMPLATE") - - -def open_modal(client, body, folders): - if not folders: - return - folder_names = [i["name"] for i in folders] - blocks = [ - {"type": "section", "text": {"type": "mrkdwn", "text": f"*{name}*"}} - for name in folder_names - ] - view = { - "type": "modal", - "title": {"type": "plain_text", "text": "Folder List"}, - "blocks": blocks, - } - client.views_open(trigger_id=body["trigger_id"], view=view) - - -def google_service_command(client, body, respond): - # respond(f"Healthcheck status: {google_drive.healthcheck()}") - # folders = google_drive.list_folders_in_folder(SRE_INCIDENT_FOLDER) - # if not folders: - # respond("The folder ID is invalid. Please check the environment variables.") - # return - users = google_directory.list_users() - if not users: - respond("There was an error retrieving the users.") - return - respond(f"Found {len(users)} users.") - groups = google_directory.list_groups() - if not groups: - respond("There was an error retrieving the groups.") - return - respond(f"Found {len(groups)} groups.") - group_members = google_directory.list_group_members(groups[0]["id"]) - if not group_members: - respond("There was an error retrieving the group members.") - return - respond(f"Found {len(group_members)} group members in group {groups[0]['name']}.") diff --git a/app/modules/sre/sre.py b/app/modules/sre/sre.py index c12dc743..cab728f3 100644 --- a/app/modules/sre/sre.py +++ b/app/modules/sre/sre.py @@ -6,9 +6,8 @@ import os from modules.incident import incident_helper -from modules import google_service from modules.sre import geolocate_helper, webhook_helper -from modules.dev import aws_dev +from modules.dev import aws_dev, google_service from integrations.slack import commands as slack_commands help_text = """ @@ -62,13 +61,13 @@ def sre_command(ack, command, logger, respond, client, body): respond(f"SRE Bot version: {os.environ.get('GIT_SHA', 'unknown')}") case "google": if PREFIX == "dev-": - google_service.google_service_command(client, body, respond) + google_service.google_service_command(ack, client, body, respond) else: respond("This command is only available in the dev environment.") return case "aws": if PREFIX == "dev-": - aws_dev.aws_dev_command(client, body, respond) + aws_dev.aws_dev_command(ack, client, body, respond) else: respond("This command is only available in the dev environment.") return From 9a6981487bf021d3a7544f331cd1c09fe6dde624 Mon Sep 17 00:00:00 2001 From: Guillaume Charest <1690085+gcharest@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:36:57 +0000 Subject: [PATCH 2/4] fix: set proper delegated email and scopes --- app/integrations/google_workspace/google_calendar.py | 5 +++-- .../integrations/google_workspace/test_google_calendar.py | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/integrations/google_workspace/google_calendar.py b/app/integrations/google_workspace/google_calendar.py index e7ee1173..8cff21fe 100644 --- a/app/integrations/google_workspace/google_calendar.py +++ b/app/integrations/google_workspace/google_calendar.py @@ -6,6 +6,7 @@ from integrations.google_workspace.google_service import ( handle_google_api_errors, execute_google_api_call, + DEFAULT_DELEGATED_ADMIN_EMAIL, ) from integrations.utils.api import convert_string_to_camel_case @@ -35,13 +36,13 @@ def get_freebusy(time_min, time_max, items, **kwargs): "items": items, } body.update({convert_string_to_camel_case(k): v for k, v in kwargs.items()}) - return execute_google_api_call( "calendar", "v3", "freebusy", "query", - scopes=["https://www.googleapis.com/auth/calendar.readonly"], + delegated_user_email=DEFAULT_DELEGATED_ADMIN_EMAIL, + scopes=["https://www.googleapis.com/auth/calendar"], body=body, ) diff --git a/app/tests/integrations/google_workspace/test_google_calendar.py b/app/tests/integrations/google_workspace/test_google_calendar.py index 14de831b..bbb7e52e 100644 --- a/app/tests/integrations/google_workspace/test_google_calendar.py +++ b/app/tests/integrations/google_workspace/test_google_calendar.py @@ -64,6 +64,7 @@ def items(): return [{"id": "calendar1"}, {"id": "calendar2"}] +@patch("integrations.google_workspace.google_calendar.DEFAULT_DELEGATED_ADMIN_EMAIL", "test_email") @patch("integrations.google_workspace.google_calendar.execute_google_api_call") def test_get_freebusy_required_args_only(mock_execute_google_api_call, items): mock_execute_google_api_call.return_value = {} @@ -77,7 +78,8 @@ def test_get_freebusy_required_args_only(mock_execute_google_api_call, items): "v3", "freebusy", "query", - scopes=["https://www.googleapis.com/auth/calendar.readonly"], + delegated_user_email="test_email", + scopes=["https://www.googleapis.com/auth/calendar"], body={ "timeMin": time_min, "timeMax": time_max, @@ -86,6 +88,7 @@ def test_get_freebusy_required_args_only(mock_execute_google_api_call, items): ) +@patch("integrations.google_workspace.google_calendar.DEFAULT_DELEGATED_ADMIN_EMAIL", "test_email") @patch("integrations.google_workspace.google_calendar.execute_google_api_call") def test_get_freebusy_optional_args(mock_execute_google_api_call, items): mock_execute_google_api_call.return_value = {} @@ -109,7 +112,8 @@ def test_get_freebusy_optional_args(mock_execute_google_api_call, items): "v3", "freebusy", "query", - scopes=["https://www.googleapis.com/auth/calendar.readonly"], + delegated_user_email="test_email", + scopes=["https://www.googleapis.com/auth/calendar"], body={ "timeMin": time_min, "timeMax": time_max, From 8d93bcfc326b37298af278ae2765815f4fdaed80 Mon Sep 17 00:00:00 2001 From: Guillaume Charest <1690085+gcharest@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:37:25 +0000 Subject: [PATCH 3/4] chore: local dev test --- app/modules/dev/google_service.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/modules/dev/google_service.py b/app/modules/dev/google_service.py index b35bbeb7..f27bceda 100644 --- a/app/modules/dev/google_service.py +++ b/app/modules/dev/google_service.py @@ -68,9 +68,10 @@ def google_service_command(ack, client, body, respond): time_max = (now + timedelta(days=(60 + days))).isoformat() freebusy_results = google_calendar.get_freebusy(time_min, time_max, items) # respond(freebusy_results) - response = json.dumps(freebusy_results, indent=4) - respond(response) - print(freebusy_results) + first_available_start, first_available_end = google_calendar.find_first_available_slot( + freebusy_results, days) + respond(f"First available slot: {first_available_start} to {first_available_end}") + # respond(f"Healthcheck status: {google_drive.healthcheck()}") # folders = google_drive.list_folders_in_folder(SRE_INCIDENT_FOLDER) # if not folders: From e98fcd83a793d0a87fd5753363c1bbd5aba5276c Mon Sep 17 00:00:00 2001 From: Guillaume Charest <1690085+gcharest@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:38:21 +0000 Subject: [PATCH 4/4] chore: run fmt & lint --- app/modules/dev/google_service.py | 9 ++++----- .../google_workspace/test_google_calendar.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/modules/dev/google_service.py b/app/modules/dev/google_service.py index f27bceda..2f22af7f 100644 --- a/app/modules/dev/google_service.py +++ b/app/modules/dev/google_service.py @@ -1,10 +1,7 @@ """Testing new google service (will be removed)""" import os -import json from datetime import datetime, timedelta, timezone from integrations.google_workspace import ( - google_directory, - google_drive, google_calendar, ) from dotenv import load_dotenv @@ -68,8 +65,10 @@ def google_service_command(ack, client, body, respond): time_max = (now + timedelta(days=(60 + days))).isoformat() freebusy_results = google_calendar.get_freebusy(time_min, time_max, items) # respond(freebusy_results) - first_available_start, first_available_end = google_calendar.find_first_available_slot( - freebusy_results, days) + ( + first_available_start, + first_available_end, + ) = google_calendar.find_first_available_slot(freebusy_results, days) respond(f"First available slot: {first_available_start} to {first_available_end}") # respond(f"Healthcheck status: {google_drive.healthcheck()}") diff --git a/app/tests/integrations/google_workspace/test_google_calendar.py b/app/tests/integrations/google_workspace/test_google_calendar.py index bbb7e52e..267c881d 100644 --- a/app/tests/integrations/google_workspace/test_google_calendar.py +++ b/app/tests/integrations/google_workspace/test_google_calendar.py @@ -64,7 +64,10 @@ def items(): return [{"id": "calendar1"}, {"id": "calendar2"}] -@patch("integrations.google_workspace.google_calendar.DEFAULT_DELEGATED_ADMIN_EMAIL", "test_email") +@patch( + "integrations.google_workspace.google_calendar.DEFAULT_DELEGATED_ADMIN_EMAIL", + "test_email", +) @patch("integrations.google_workspace.google_calendar.execute_google_api_call") def test_get_freebusy_required_args_only(mock_execute_google_api_call, items): mock_execute_google_api_call.return_value = {} @@ -88,7 +91,10 @@ def test_get_freebusy_required_args_only(mock_execute_google_api_call, items): ) -@patch("integrations.google_workspace.google_calendar.DEFAULT_DELEGATED_ADMIN_EMAIL", "test_email") +@patch( + "integrations.google_workspace.google_calendar.DEFAULT_DELEGATED_ADMIN_EMAIL", + "test_email", +) @patch("integrations.google_workspace.google_calendar.execute_google_api_call") def test_get_freebusy_optional_args(mock_execute_google_api_call, items): mock_execute_google_api_call.return_value = {}