aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar shtlrs <[email protected]>2024-04-01 15:05:27 +0200
committerGravatar shtlrs <[email protected]>2024-05-28 20:52:20 +0200
commit5285b30d4d9ad8eb70ed94b283fa255511f34e31 (patch)
tree645e71b9cff46c45cf7c2bd643d1a05b700ad545
parentBump dependencies to latest (diff)
paginate pod logs instead of truncating them
-rw-r--r--arthur/config.py1
-rw-r--r--arthur/exts/kubernetes/pods.py53
-rw-r--r--arthur/pagination.py63
3 files changed, 92 insertions, 25 deletions
diff --git a/arthur/config.py b/arthur/config.py
index 146db73..bb88838 100644
--- a/arthur/config.py
+++ b/arthur/config.py
@@ -27,6 +27,7 @@ class Config(
guild_id: int = 267624335836053506
devops_channel_id: int = 675756741417369640
sentry_dsn: str = ""
+ trashcan: str = "<:trashcan:637136429717389331>"
GIT_SHA = environ.get("GIT_SHA", "development")
diff --git a/arthur/exts/kubernetes/pods.py b/arthur/exts/kubernetes/pods.py
index 0a82fb9..bab3f79 100644
--- a/arthur/exts/kubernetes/pods.py
+++ b/arthur/exts/kubernetes/pods.py
@@ -3,6 +3,7 @@
import zoneinfo
from datetime import datetime
+import discord
import humanize
from discord.ext import commands
from kubernetes_asyncio.client.rest import ApiException
@@ -12,6 +13,7 @@ from tabulate import tabulate
from arthur.apis.kubernetes import pods
from arthur.bot import KingArthur
from arthur.config import CONFIG
+from arthur.pagination import LinePaginator
from arthur.utils import generate_error_message
MAX_MESSAGE_LENGTH = 2000
@@ -46,9 +48,10 @@ class Pods(commands.Cog):
pod_list = await pods.list_pods(namespace)
if len(pod_list.items) == 0:
- return await ctx.send(
+ await ctx.send(
generate_error_message(description="No pods found, check the namespace exists.")
)
+ return
tables = [[]]
@@ -95,7 +98,7 @@ class Pods(commands.Cog):
for table in tables:
await ctx.send(tabulate_pod_data(table))
- return None
+ return
@pods_cmd.command(name="logs", aliases=["log", "tail"])
@commands.check(lambda ctx: ctx.channel.id == CONFIG.devops_channel_id)
@@ -116,46 +119,46 @@ class Pods(commands.Cog):
pod_names = [pod_name]
if pod_names is None:
- return await ctx.send(
+ await ctx.send(
generate_error_message(description="No pods found for the provided deployment.")
)
+ return
for pod in pod_names:
try:
logs = await pods.tail_pod(namespace, pod, lines=lines)
except ApiException as e:
if e.status == 404: # noqa: PLR2004, 404 is a known error
- return await ctx.send(
+ await ctx.send(
generate_error_message(
description="Pod or namespace not found, check the name."
)
)
- return await ctx.send(generate_error_message(description=str(e)))
+ return
+ await ctx.send(generate_error_message(description=str(e)))
+ return
if len(logs) == 0:
- return await ctx.send(
- generate_error_message(description="No logs found for the pod.")
- )
+ await ctx.send(generate_error_message(description="No logs found for the pod."))
+ return
- truncated = False
+ logs = logs.splitlines()
- if len(logs) > MAX_MESSAGE_LENGTH - 100:
- truncated = True
- while len(logs) > MAX_MESSAGE_LENGTH - 100:
- logs = logs[: logs.rfind("\n")]
-
- message = f"**Logs for pod `{pod}` in namespace `{namespace}`**\n"
-
- if truncated:
- message += "`[Logs truncated]`\n"
-
- message += "```"
- message += logs
- message += "```"
-
- await ctx.send(message)
+ logs_embed = discord.Embed(
+ title=f"**Logs for pod `{pod}` in namespace `{namespace}`**",
+ colour=discord.Colour.blue(),
+ )
+ await LinePaginator.paginate(
+ lines=logs,
+ ctx=ctx,
+ max_size=MAX_MESSAGE_LENGTH,
+ empty=False,
+ embed=logs_embed,
+ prefix="```\n",
+ suffix="```",
+ )
- return None
+ return
async def setup(bot: KingArthur) -> None:
diff --git a/arthur/pagination.py b/arthur/pagination.py
new file mode 100644
index 0000000..8db0ade
--- /dev/null
+++ b/arthur/pagination.py
@@ -0,0 +1,63 @@
+from collections.abc import Sequence
+
+import discord
+from discord.ext.commands import Context
+from pydis_core.utils.pagination import LinePaginator as _LinePaginator, PaginationEmojis
+
+from arthur.config import CONFIG
+
+
+class LinePaginator(_LinePaginator):
+ """
+ A class that aids in paginating code blocks for Discord messages.
+
+ See the super class's docs for more info.
+ """
+
+ @classmethod
+ async def paginate(
+ cls,
+ lines: list[str],
+ ctx: Context | discord.Interaction,
+ embed: discord.Embed,
+ prefix: str = "",
+ suffix: str = "",
+ max_lines: int | None = None,
+ max_size: int = 500,
+ scale_to_size: int = 4000,
+ restrict_to_user: discord.User | None = None,
+ timeout: int = 300,
+ footer_text: str | None = None,
+ url: str | None = None,
+ allowed_roles: Sequence[int] | None = None,
+ *,
+ reply: bool = False,
+ empty: bool = True,
+ exception_on_empty_embed: bool = False,
+ ) -> discord.Message | None:
+ """
+ Use a paginator and set of reactions to provide pagination over a set of lines.
+
+ Acts as a wrapper for the super class' `paginate` method to provide the pagination emojis by default.
+
+ Consult the super class's `paginate` method for detailed information.
+ """
+ return await super().paginate(
+ pagination_emojis=PaginationEmojis(delete=CONFIG.trashcan),
+ lines=lines,
+ ctx=ctx,
+ embed=embed,
+ prefix=prefix,
+ suffix=suffix,
+ max_lines=max_lines,
+ max_size=max_size,
+ scale_to_size=scale_to_size,
+ empty=empty,
+ restrict_to_user=restrict_to_user,
+ timeout=timeout,
+ footer_text=footer_text,
+ url=url,
+ exception_on_empty_embed=exception_on_empty_embed,
+ reply=reply,
+ allowed_roles=allowed_roles,
+ )