aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Chris Lovering <[email protected]>2024-02-12 20:58:56 +0000
committerGravatar Chris Lovering <[email protected]>2024-02-12 21:18:31 +0000
commitc53fa0af513193b6ff36cb8713482975e689fd31 (patch)
tree1f5b9f9a5165db35196f0731644137fced813f84
parentAdd API wrappers for github and grafana APIs (diff)
Add a cog to sync github teams to grafana teams
-rw-r--r--arthur/exts/grafana/team_sync.py89
1 files changed, 89 insertions, 0 deletions
diff --git a/arthur/exts/grafana/team_sync.py b/arthur/exts/grafana/team_sync.py
new file mode 100644
index 0000000..501f891
--- /dev/null
+++ b/arthur/exts/grafana/team_sync.py
@@ -0,0 +1,89 @@
+import aiohttp
+import discord
+from discord.ext import commands, tasks
+
+from arthur import logger
+from arthur.apis import github, grafana
+from arthur.bot import KingArthur
+
+
+class GrafanaTeamSync(commands.Cog):
+ """
+ Update Grafana team membership to match Github team membership.
+
+ Grafana team name must match Github team slug exactly.
+ Use `gh api orgs/{org-name}/teams` to get a list of teams in an org
+ """
+
+ def __init__(self, bot: KingArthur) -> None:
+ self.bot = bot
+ self.sync_github_grafana_teams.start()
+
+ async def _sync_teams(self, team: dict[str, str]) -> tuple[int, int]:
+ """
+ Ensure members in github are present in grafana teams.
+
+ Return the number of members missing from teh grafana team, and the number of members added.
+ """
+ github_team_members = {
+ member["login"]
+ for member in await github.list_team_members(team["name"], self.bot.http_session)
+ }
+ grafana_team_members = {
+ member["login"]
+ for member in await grafana.list_team_members(team["id"], self.bot.http_session)
+ if member.get("auth_module") == "oauth_github"
+ }
+
+ missing_members = github_team_members - grafana_team_members
+ grafana_users = await grafana.get_all_users(self.bot.http_session)
+ added_members = set()
+ for grafana_user in grafana_users:
+ if grafana_user["login"] not in missing_members:
+ continue
+ await grafana.add_user_to_team(
+ grafana_user["userId"],
+ team["id"],
+ self.bot.http_session,
+ )
+ added_members.add(grafana_user["login"])
+ return len(missing_members), len(added_members)
+
+ @tasks.loop(hours=12)
+ async def sync_github_grafana_teams(self, channel: discord.TextChannel | None = None) -> None:
+ """Update Grafana team membership to match Github team membership."""
+ grafana_teams = await grafana.list_teams(self.bot.http_session)
+ for team in grafana_teams:
+ logger.debug(f"Processing {team['name']}")
+ try:
+ missing, added = await self._sync_teams(team)
+ except aiohttp.ClientResponseError as e:
+ logger.error(e)
+ if channel:
+ await channel.send(e)
+ continue
+
+ if channel and missing:
+ await channel.send(
+ f"Found {missing} users not in the {team['name']} grafana team, added {added} of them."
+ )
+
+ @sync_github_grafana_teams.error
+ async def on_task_error(self, error: Exception) -> None:
+ """Ensure task errors are output."""
+ logger.error(error)
+
+ @commands.group(name="grafana", aliases=("graf",), invoke_without_command=True)
+ async def grafana_group(self, ctx: commands.Context) -> None:
+ """Commands for working with grafana API."""
+ await ctx.send_help(ctx.command)
+
+ @grafana_group.command(name="sync")
+ async def sync_teams(self, ctx: commands.Context) -> None:
+ """Sync Grafana & Github teams now."""
+ await self.sync_github_grafana_teams(ctx.channel)
+
+
+async def setup(bot: KingArthur) -> None:
+ """Add cog to bot."""
+ await bot.add_cog(GrafanaTeamSync(bot))