Skip to content

Commit

Permalink
Merge branch 'main' into feat-pd-service-re
Browse files Browse the repository at this point in the history
  • Loading branch information
talboren authored Nov 21, 2024
2 parents e60b3f2 + 4463c01 commit a480cb1
Show file tree
Hide file tree
Showing 409 changed files with 6,201 additions and 3,962 deletions.
5 changes: 4 additions & 1 deletion docker/Dockerfile.api
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ RUN chgrp -R 0 /app && chmod -R g=u /app
RUN chown -R keep:keep /app
RUN chown -R keep:keep /venv
USER keep
ENTRYPOINT ["gunicorn", "keep.api.api:get_app", "--bind" , "0.0.0.0:8080" , "--workers", "4" , "-k" , "uvicorn.workers.UvicornWorker", "-c", "/venv/lib/python3.11/site-packages/keep/api/config.py"]

ENTRYPOINT ["/venv/lib/python3.11/site-packages/keep/entrypoint.sh"]

CMD ["gunicorn", "keep.api.api:get_app", "--bind" , "0.0.0.0:8080" , "--workers", "4" , "-k" , "uvicorn.workers.UvicornWorker", "-c", "/venv/lib/python3.11/site-packages/keep/api/config.py"]
2 changes: 2 additions & 0 deletions docker/Dockerfile.dev.api
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ RUN . /venv/bin/activate && poetry install --no-root
ENV PYTHONPATH="/app:${PYTHONPATH}"
ENV PATH="/venv/bin:${PATH}"
ENV VIRTUAL_ENV="/venv"
ENV POSTHOG_DISABLED="true"

ENTRYPOINT ["/app/keep/entrypoint.sh"]

CMD ["gunicorn", "keep.api.api:get_app", "--bind" , "0.0.0.0:8080" , "--workers", "1" , "-k" , "uvicorn.workers.UvicornWorker", "-c", "./keep/api/config.py", "--reload"]
1 change: 1 addition & 0 deletions docs/deployment/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ General configuration variables control the core behavior of the Keep server. Th
| **KEEP_API_URL** | Specifies the Keep API URL | No | Constructed from HOST and PORT | Valid URL |
| **KEEP_STORE_RAW_ALERTS** | Enables storing of raw alerts | No | "false" | "true" or "false" |
| **TENANT_CONFIGURATION_RELOAD_TIME** | Time in minutes to reload tenant configurations | No | 5 | Positive integer |
| **KEEP_LIVE_DEMO_MODE** | Keep will simulate incoming alerts and other activity | No | "false" | "true" or "false" |

### Logging and Environment
<Info>
Expand Down
Binary file added docs/images/appdynamics_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/appdynamics_9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 95 additions & 6 deletions docs/providers/documentation/appdynamics-provider.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,108 @@ description: "AppDynamics provider allows you to get AppDynamics `alerts/actions
## Authentication Parameters
The AppDynamics provider requires the following authentication parameter:

- `AppDynamics Username`: Required. This is your AppDynamics account username.
- `AppDynamics Password`: This is the password associated with your AppDynamics Username.
- `AppDynamics Access Token`: Required if username/password is not provided for Bearer token authentication.
- `AppDynamics Username`: Required for Basic Auth authentication. This is your AppDynamics account username.
- `AppDynamics Password`: Required for Basic Auth authentication. This is the password associated with your AppDynamics Username.
- `AppDynamics Account Name`: This is your account's name.
- `App Id`: The Id of the Application in which you would like to install the webhook.
- `Host`: This is the hostname of the AppDynamics instance you wish to connect to. It identifies the AppDynamics server that the API will interact with.

## Connecting with the Provider
1. Ensure you have a AppDynamics account with the necessary [permissions](https://docs.appdynamics.com/accounts/en/cisco-appdynamics-on-premises-user-management/roles-and-permissions). The basic permissions required are `Account Owner` or `Administrator`. Alternatively you can create an account [instructions](https://docs.appdynamics.com/accounts/en/global-account-administration/access-management/manage-user-accounts)

Obtain AppDynamics Username and Password:
1. Ensure you have a AppDynamics account with the necessary [permissions](https://docs.appdynamics.com/accounts/en/cisco-appdynamics-on-premises-user-management/roles-and-permissions). The basic permissions required are `Account Owner` or `Administrator`. Alternatively you can create an account (instructions)[https://docs.appdynamics.com/accounts/en/global-account-administration/access-management/manage-user-accounts]
2. Find your account name [here](https://accounts.appdynamics.com/overview).
## Provider configuration

1. Find your account name [here](https://accounts.appdynamics.com/overview).
2. Get the appId of the Appdynamics instance in which you wish to install the webhook into.
3. Determine the Host [here](https://accounts.appdynamics.com/overview).
4. Get the appId of the Appdynamics instance in which you wish to install the webhook into.

### Basic Auth authentication

1. Obtain AppDynamics **Username** and **Password**
2. Go to **Basic Auth** tab under **Authentication** section
3. Enter **Username** and **Password**

<Frame>
<img src="/images/appdynamics_9.png" width="1000" alt="Keep add AppDynamics Username and Password"/>
</Frame>

### Access Token authentication

1. Log in to the **Controller UI** as an **Account Owner** or other roles with the **Administer users**, **groups**, **roles** permission.
2. Go to **Administration**

<Frame>
<img src="/images/appdynamics_1.png" width="1000" alt="AppDynamics Administration"/>
</Frame>

3. Go to **API Client** tab

<Frame>
<img src="/images/appdynamics_2.png" width="1000" alt="AppDynamics API Client tab"/>
</Frame>

4. Click **+ Create**

<Frame>
<img src="/images/appdynamics_3.png" width="1000" alt="Create new AppDynamics API Client"/>
</Frame>

5. Fill Client **Name** and **Description**
6. Click **Generate Secret**

<Frame>
<img src="/images/appdynamics_4.png" width="1000" alt="AppDynamics generate API Client Secret"/>
</Frame>

<Tip>
This API Client secret is not an authentication token yet
</Tip>

7. Add **Account Owner** and/or **Administrator** roles

<Frame>
<img src="/images/appdynamics_5.png" width="1000" alt="AppDynamics add API Client roles"/>
</Frame>

8. Click **Save**

<Frame>
<img src="/images/appdynamics_6.png" width="1000" alt="AppDynamics save API Client"/>
</Frame>

9. Click **Generate Temporary Token**

<Frame>
<img src="/images/appdynamics_7.png" width="1000" alt="AppDynamics Generate API Client Temporary Access Token"/>
</Frame>

<Tip>
This token is not persistent, but since Keep uses it just once to install Webhook, we will use it without oAuth
</Tip>

10. Click **Save** one again
<Warning>
This is important. Otherwise generated token will not be saved and authentication will fail
</Warning>
11. Copy generated token

<Frame>
<img src="/images/appdynamics_8.png" width="1000" alt="AppDynamics copy API Client Temporary Access Token"/>
</Frame>

12. Go to **Access Token** tab under **Authentication** section

<Frame>
<img src="/images/appdynamics_10.png" width="1000" alt="Keep add AppDynamics Access Token"/>
</Frame>

13. Enter Access Token

## Connecting provider

1. Ensure **Install webhook** is checked
2. Click **Connect**

## Webhook Integration Modifications

Expand Down
8 changes: 8 additions & 0 deletions keep-ui/app/(keep)/[...not-found]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"use client";

import { notFound } from "next/navigation";

// https://github.com/vercel/next.js/discussions/50034
export default function NotFoundDummy() {
notFound();
}
2 changes: 1 addition & 1 deletion keep-ui/app/ai/ai.tsx → keep-ui/app/(keep)/ai/ai.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";
import { Card, List, ListItem, Title, Subtitle } from "@tremor/react";
import { useAIStats, usePollAILogs } from "utils/hooks/useAI";
import { useSession } from "next-auth/react";
import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession";
import { useApiUrl } from "utils/hooks/useConfig";
import { toast } from "react-toastify";
import { useEffect, useState, useRef, FormEvent } from "react";
Expand Down
4 changes: 2 additions & 2 deletions keep-ui/app/ai/model.ts → keep-ui/app/(keep)/ai/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ export interface AIStats {
incidents_count: number;
first_alert_datetime?: Date;
is_mining_enabled: boolean;
algorithm_verbose_name: string
algorithm_verbose_name: string;
}

export interface AILogs {
log: string;
}
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
import React, { useState, Fragment, useRef, FormEvent } from 'react';
import { Popover } from '@headlessui/react';
import { Button, Tab, TabGroup, TabList, TabPanels, TabPanel } from "@tremor/react";
import { IoColorPaletteOutline } from 'react-icons/io5';
import React, { useState, Fragment, useRef, FormEvent } from "react";
import { Popover } from "@headlessui/react";
import {
Button,
Tab,
TabGroup,
TabList,
TabPanels,
TabPanel,
} from "@tremor/react";
import { IoColorPaletteOutline } from "react-icons/io5";
import { FloatingArrow, arrow, offset, useFloating } from "@floating-ui/react";

const predefinedThemes = {
Transparent: {
critical: 'bg-white',
high: 'bg-white',
warning: 'bg-white',
low: 'bg-white',
info: 'bg-white'
critical: "bg-white",
high: "bg-white",
warning: "bg-white",
low: "bg-white",
info: "bg-white",
},
Keep: {
critical: 'bg-orange-400', // Highest opacity for critical
high: 'bg-orange-300',
warning: 'bg-orange-200',
low: 'bg-orange-100',
info: 'bg-orange-50' // Lowest opacity for info
critical: "bg-orange-400", // Highest opacity for critical
high: "bg-orange-300",
warning: "bg-orange-200",
low: "bg-orange-100",
info: "bg-orange-50", // Lowest opacity for info
},
Basic: {
critical: 'bg-red-200',
high: 'bg-orange-200',
warning: 'bg-yellow-200',
low: 'bg-green-200',
info: 'bg-blue-200'
}
critical: "bg-red-200",
high: "bg-orange-200",
warning: "bg-yellow-200",
low: "bg-green-200",
info: "bg-blue-200",
},
};

const themeKeyMapping = {
0: 'Transparent',
1: 'Keep',
2: 'Basic'
0: "Transparent",
1: "Keep",
2: "Basic",
};
type ThemeName = keyof typeof predefinedThemes;

export const ThemeSelection = ({ onThemeChange }: { onThemeChange: (theme: any) => void }) => {
export const ThemeSelection = ({
onThemeChange,
}: {
onThemeChange: (theme: any) => void;
}) => {
const arrowRef = useRef(null);
const [selectedTab, setSelectedTab] = useState<ThemeName>('Transparent');
const [selectedTab, setSelectedTab] = useState<ThemeName>("Transparent");

const { refs, floatingStyles, context } = useFloating({
strategy: "fixed",
Expand All @@ -50,22 +61,17 @@ export const ThemeSelection = ({ onThemeChange }: { onThemeChange: (theme: any)
handleApplyTheme(themeIndex as 0 | 1 | 2);
};




const handleApplyTheme = (themeKey: keyof typeof themeKeyMapping) => {
const themeName = themeKeyMapping[themeKey];
setSelectedTab(themeName as ThemeName);
};


};

const onApplyTheme = (close: () => void) => {
// themeName is now assured to be a key of predefinedThemes
const themeName: ThemeName = selectedTab;
const newTheme = predefinedThemes[themeName]; // This should now be error-free
onThemeChange(newTheme);
setSelectedTab('Transparent'); // Assuming 'Transparent' is a valid key
setSelectedTab("Transparent"); // Assuming 'Transparent' is a valid key
close(); // Close the popover
};

Expand All @@ -85,7 +91,7 @@ export const ThemeSelection = ({ onThemeChange }: { onThemeChange: (theme: any)
<Popover.Panel
className="bg-white z-30 p-4 rounded-sm"
ref={refs.setFloating}
style={{ ...floatingStyles, minWidth: '250px' }} // Adjust width here
style={{ ...floatingStyles, minWidth: "250px" }} // Adjust width here
>
<FloatingArrow
className="fill-white [&>path:last-of-type]:stroke-white"
Expand All @@ -100,19 +106,35 @@ export const ThemeSelection = ({ onThemeChange }: { onThemeChange: (theme: any)
<Tab>Basic</Tab>
</TabList>
<TabPanels>
{Object.keys(predefinedThemes).map(themeName => (
{Object.keys(predefinedThemes).map((themeName) => (
<TabPanel key={themeName}>
{Object.entries(predefinedThemes[themeName as keyof typeof predefinedThemes]).map(([severity, color]) => (
<div key={severity} className="flex justify-between items-center my-2">
<span>{severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase()}</span>
<div className={`w-6 h-6 rounded-full border border-gray-400 ${color}`}></div>
{Object.entries(
predefinedThemes[
themeName as keyof typeof predefinedThemes
]
).map(([severity, color]) => (
<div
key={severity}
className="flex justify-between items-center my-2"
>
<span>
{severity.charAt(0).toUpperCase() +
severity.slice(1).toLowerCase()}
</span>
<div
className={`w-6 h-6 rounded-full border border-gray-400 ${color}`}
></div>
</div>
))}
</TabPanel>
))}
</TabPanels>
</TabGroup>
<Button className="mt-5" color="orange" onClick={() => onApplyTheme(close)}>
<Button
className="mt-5"
color="orange"
onClick={() => onApplyTheme(close)}
>
Apply theme
</Button>
</Popover.Panel>
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Modal from "@/components/ui/Modal"; // Ensure this path matches your proj
import { Button, Icon, Switch, Text } from "@tremor/react";
import { toast } from "react-toastify";
import { useApiUrl } from "utils/hooks/useConfig";
import { useSession } from "next-auth/react";
import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession";
import { XMarkIcon } from "@heroicons/react/24/outline";
import "./ViewAlertModal.css";
import React, { useState } from "react";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import AlertsPage from "../alerts.client";
import AlertsPage from "../alerts";

type PageProps = {
params: { id: string };
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Select, { components } from "react-select";
import { Button, TextInput, Text } from "@tremor/react";
import { PlusIcon } from "@heroicons/react/20/solid";
import { useForm, Controller, SubmitHandler } from "react-hook-form";
import { Providers } from "./../providers/providers";
import { useSession } from "next-auth/react";
import { Providers } from "../providers/providers";
import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession";
import { useApiUrl } from "utils/hooks/useConfig";
import { AlertDto } from "./models";
import Modal from "@/components/ui/Modal";
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import Modal from "@/components/ui/Modal";
import { Button, Divider, Title } from "@tremor/react";
import Select from "@/components/ui/Select";
import { CreateOrUpdateIncidentForm } from "@/features/create-or-update-incident";
import { useSession } from "next-auth/react";
import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession";
import { FormEvent, useCallback, useEffect, useState } from "react";
import { toast } from "react-toastify";
import { useApiUrl } from "utils/hooks/useConfig";
import { useIncidents, usePollIncidents } from "../../utils/hooks/useIncidents";
import Loading from "../loading";
import {
useIncidents,
usePollIncidents,
} from "../../../utils/hooks/useIncidents";
import Loading from "@/app/(keep)/loading";
import { AlertDto } from "./models";
import { getIncidentName } from "@/entities/incidents/lib/utils";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Select, {
import { useState } from "react";
import { AlertDto, Status } from "./models";
import { useApiUrl } from "utils/hooks/useConfig";
import { useSession } from "next-auth/react";
import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession";
import { toast } from "react-toastify";
import {
CheckCircleIcon,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useState } from "react";
import Modal from "@/components/ui/Modal";
import { Callout, Button, Title, Card } from "@tremor/react";
import { useSession } from "next-auth/react";
import { useHydratedSession as useSession } from "@/shared/lib/hooks/useHydratedSession";
import { toast } from "react-toastify";
import Loading from "../loading";
import Loading from "@/app/(keep)/loading";
import { AlertDto } from "./models";
import { IncidentDto, IncidentCandidateDto } from "@/entities/incidents/model";
import { useApiUrl } from "utils/hooks/useConfig";
Expand Down
Loading

0 comments on commit a480cb1

Please sign in to comment.