Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added real data in the runbook table #7

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 42 additions & 45 deletions keep-ui/app/runbooks/runbook-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import { useRunBookTriggers } from "utils/hooks/useRunbook";
import { useForm, get } from "react-hook-form";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { getApiURL } from "@/utils/apiUrl";
import useSWR from "swr";
import { fetcher } from "@/utils/fetcher";
import { useSession } from "next-auth/react";

const customStyles = {
content: {
Expand All @@ -30,67 +34,49 @@ const customStyles = {
},
};

interface Incident {
id: number;
name: string;
interface Content {
id: string;
content: string;
link: string;
encoding: string|null;
file_name: string;
}

interface Runbook {
interface RunbookV2 {
id: number;
title: string;
incidents: Incident[];
contents:Content[],
provider_type: string,
provider_id: string
repo_id: string
file_path: string
}

const runbookData = [
{
id: 1,
title: "Database Recovery",
incidents: [
{ id: 101, name: "DB Outage on 2024-01-01" },
{ id: 102, name: "DB Backup Failure" },
],
},
{
id: 2,
title: "API Health Check",
incidents: [{ id: 201, name: "API Latency Issue" }],
},
{
id: 3,
title: "Server Restart Guide",
incidents: [
{ id: 301, name: "Unexpected Server Crash" },
{ id: 302, name: "Scheduled Maintenance" },
],
},
] as Runbook[];

const columnHelper = createColumnHelper<Runbook>();
const columnHelperv2 = createColumnHelper<RunbookV2>();

const columns = [
columnHelper.display({
const columnsv2 = [
columnHelperv2.display({
id: "title",
header: "Runbook Title",
cell: ({ row }) => {
return <div>{row.original.title}</div>;
},
}),
columnHelper.display({
id: "incidents",
header: "Incdients",
columnHelperv2.display({
id: "contents",
header: "Contents",
cell: ({ row }) => {
return (
<div>
{row.original.incidents?.map((incident: Incident) => (
<Badge key={incident.id} color="green" className="mr-2 mb-1">
{incident.name}
{row.original.contents?.map((content: Content) => (
<Badge key={content.id} color="green" className="mr-2 mb-1">
{content.file_name}
</Badge>
))}
</div>
);
},
}),
] as DisplayColumnDef<Runbook>[];
] as DisplayColumnDef<RunbookV2>[];

// function PreviewContent({type, data}:{type:string, data:string}){
// const [isModalOpen, setIsModalOpen] = useState(open);
Expand Down Expand Up @@ -266,6 +252,17 @@ function SettingsPage() {
function RunbookIncidentTable() {
const [offset, setOffset] = useState(0);
const [limit, setLimit] = useState(10);
const { data: session, status } = useSession();


let shouldFetch = session?.accessToken ? true : false;

const { data: runbooksData, error } = useSWR<RunbookV2[]>(
shouldFetch ? `${getApiURL()}/runbooks` : null,
(url:string) => {
return fetcher(url, session?.accessToken!);
},
);

// Modal state management

Expand All @@ -281,17 +278,17 @@ function RunbookIncidentTable() {
<SettingsPage />
</div>
<Card className="flex-1 overflow-auto">
<GenericTable<Runbook>
data={runbookData}
columns={columns}
rowCount={runbookData.length}
{runbooksData && <GenericTable<RunbookV2>
data={runbooksData}
columns={columnsv2}
rowCount={runbooksData.length}
offset={offset}
limit={limit}
onPaginationChange={handlePaginationChange}
onRowClick={(row) => {
console.log("Runbook clicked:", row);
}}
/>
/>}
</Card>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions keep-ui/utils/hooks/useRunbook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const useRunBookTriggers = (values: any, refresh: number) => {
const [synced, setSynced] = useState(false);
const [fileData, setFileData] = useState<any>({});
const [reposData, setRepoData] = useState<any>([]);
const { pathToMdFile, repoName, userName, providerId, domain, runBookTitle } = values || {};
const { pathToMdFile, repoName, userName, providerId, domain } = values || {};
const { data: session } = useSession();
const { installed_providers, providers } = (providersData?.data ||
{}) as ProvidersResponse;
Expand Down Expand Up @@ -55,7 +55,7 @@ export const useRunBookTriggers = (values: any, refresh: number) => {
}, [refresh]);

const handleSubmit = async (data: any) => {
const { pathToMdFile, repoName } = data;
const { pathToMdFile, repoName, runBookTitle } = data;
try {
if(!provider){
return toast("Please select a provider");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
"""add runbook table

Revision ID: 8902e1a17f66
Revision ID: 119c64cbf61c
Revises: 01ebe17218c0
Create Date: 2024-10-08 16:09:28.158034
Create Date: 2024-10-08 17:19:14.369121

"""

import sqlalchemy as sa
import sqlalchemy_utils
import sqlmodel
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "8902e1a17f66"
revision = "119c64cbf61c"
down_revision = "01ebe17218c0"
branch_labels = None
depends_on = None
Expand Down Expand Up @@ -41,6 +39,7 @@ def upgrade() -> None:
sa.Column("link", sa.Text(), nullable=True),
sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.Column("encoding", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("file_name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(["runbook_id"], ["runbook.id"], ondelete="CASCADE"),
sa.PrimaryKeyConstraint("id"),
Expand Down
5 changes: 4 additions & 1 deletion keep/api/models/db/runbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class RunbookContent(SQLModel, table=True):
content: str = Field(sa_column=Column(Text), nullable=False) # Using SQLAlchemy's Text type
link: str = Field(sa_column=Column(Text), nullable=False) # Using SQLAlchemy's Text type
encoding: Optional[str] = None
file_name: str
created_at: datetime = Field(default_factory=datetime.utcnow) # Timestamp for creation

class Config:
Expand Down Expand Up @@ -53,6 +54,7 @@ class RunbookContentDto(BaseModel, extra="ignore"):
id: UUID
content: str
link: str
file_name: str
encoding: Optional[str] = None

@classmethod
Expand All @@ -61,7 +63,8 @@ def from_orm(cls, content: "RunbookContent") -> "RunbookContentDto":
id=content.id,
content=content.content,
link=content.link,
encoding=content.encoding
encoding=content.encoding,
file_name=content.file_name
)

class RunbookDtoOut(RunbookDto):
Expand Down
2 changes: 1 addition & 1 deletion keep/api/routes/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import uuid
from typing import Callable, Optional

from fastapi import APIRouter, Body, Depends, HTTPException, Request, Query
from fastapi import APIRouter, Body, Depends, HTTPException, Request
from fastapi.responses import JSONResponse
from sqlmodel import Session, select
from starlette.datastructures import UploadFile
Expand Down
21 changes: 17 additions & 4 deletions keep/api/routes/runbooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
from keep.runbooks.runbooks_service import (
RunbookService
)
from keep.api.models.db.runbook import (
RunbookDtoOut
)


logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -118,3 +114,20 @@ def create_runbook(
runbook_dto= provider.pull_runbook(repo=repo, branch=branch, md_path=md_path, title=title)
return RunbookService.create_runbook(session, tenant_id, runbook_dto)


@router.get(
"",
description="All Runbooks",
# response_model=RunbookDtoOut,
)
def create_runbook(

authenticated_entity: AuthenticatedEntity = Depends(
IdentityManagerFactory.get_auth_verifier(["read:runbook"])
),
session: Session = Depends(get_session)
):
tenant_id = authenticated_entity.tenant_id
logger.info("get all Runbooks", extra={tenant_id: tenant_id})
return RunbookService.get_all_runbooks(session, tenant_id)

3 changes: 2 additions & 1 deletion keep/providers/github_provider/github_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ def _format_runbook(self, runbook, repo, title):
"contents": [{
"content":runbook.content,
"link": f"https://api.github.com/{repo.get('full_name')}/blob/{repo.get('default_branch')}/{runbook.path}",
"encoding": runbook.encoding
"encoding": runbook.encoding,
"file_name": runbook.name
}],
"title": title,
}
Expand Down
2 changes: 1 addition & 1 deletion keep/providers/gitlab_provider/gitlab_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ def pull_runbook(self, repo=None, branch=None, md_path=None, title=None):
except HTTPError as e:
raise Exception(f"Failed to get runbook: {e}")

return self._format_runbook(resp.json(), repo_met, title)
return self._format_runbook(resp.json(), repo_meta, title)

raise Exception("Failed to get runbook: repository or md_path not set")

Expand Down
21 changes: 15 additions & 6 deletions keep/runbooks/runbooks_service.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import logging
from typing import List, Optional
from typing import List
from pydantic import ValidationError
from sqlalchemy.orm import joinedload, selectinload
from uuid import UUID
import json
from sqlalchemy.orm import selectinload

from sqlmodel import Session, select
from keep.api.models.db.runbook import (
Expand Down Expand Up @@ -36,7 +34,8 @@ def create_runbook(session: Session, tenant_id: str, runbook_dto: dict):
runbook_id=new_runbook.id,
content=content["content"],
link=content["link"],
encoding=content["encoding"]
encoding=content["encoding"],
file_name=content["file_name"]
)
for content in contents
]
Expand All @@ -48,4 +47,14 @@ def create_runbook(session: Session, tenant_id: str, runbook_dto: dict):
result = RunbookDtoOut.from_orm(new_runbook)
return result
except ValidationError as e:
logger.exception(f"Failed to create runbook {e}")
logger.exception(f"Failed to create runbook {e}")

@staticmethod
def get_all_runbooks(session: Session, tenant_id: str) -> List[RunbookDtoOut]:
runbooks = session.exec(
select(Runbook)
.where(Runbook.tenant_id == tenant_id)
.options(selectinload(Runbook.contents)).limit(1000)
)

return [RunbookDtoOut.from_orm(runbook) for runbook in runbooks]
Loading