Merge dev to main (#69)
* Log (failed) attempt to notify a user with viewer role * Remove https:// prefix from BASE_URL docker env var * Fix cloud heartbeat name * Polishing telegram * Update docker-compose.yml * Update plugin README (#48) * Update README and screenshot, remove plop for build info since version is now displayed prominently * Sign build Co-authored-by: Michael Derynck <michael.derynck@grafana.com> * Build actions (#38) * Drone, github action changes * Minor version updates * Update frontend dependencies * Re-enable unit test Co-authored-by: Michael Derynck <michael.derynck@grafana.com> * Revert stylelint version (#52) * Revert stylelint version * Build plugin as well as lint * Build in previous step Co-authored-by: Michael Derynck <michael.derynck@grafana.com> * Update screenshot (#53) Co-authored-by: Michael Derynck <michael.derynck@grafana.com> * oncall images for docs (#55) * Update README.md * Top menu fix * Fix db encoding * Add api key docs * Reverting utf8 fix * bug fixes * fix for link for OSS version * Fixing utf8 and docker compose * 8080 -> 8000 port for consistency * makeReq * Fixing images * Fixing port * Fixing port * Fixing port * Fixing port * Fixing port * Fixing port * Fixing port * Fixing port * Replace symlink with file for CHANGELOG.MD (#68) Co-authored-by: Michael Derynck <michael.derynck@grafana.com> Co-authored-by: Matias Bordese <mbordese@gmail.com> Co-authored-by: Matvey Kukuy <Matvey-Kuk@users.noreply.github.com> Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com> Co-authored-by: Matvey Kukuy <matvey@amixr.io> Co-authored-by: Michael Derynck <michael.derynck@grafana.com> Co-authored-by: Alyssa Wada <101596687+alyssawada@users.noreply.github.com> Co-authored-by: Yulia Shanyrova <yulia.shanyrova@grafana.com>
This commit is contained in:
parent
66e8cf2cbc
commit
846b898bb9
21 changed files with 74 additions and 58 deletions
|
|
@ -1,3 +1,5 @@
|
|||
RUNSERVER_PORT=8080
|
||||
|
||||
SLACK_CLIENT_OAUTH_ID=
|
||||
SLACK_CLIENT_OAUTH_SECRET=
|
||||
SLACK_API_TOKEN=
|
||||
|
|
@ -19,13 +21,13 @@ SENDGRID_FROM_EMAIL=
|
|||
|
||||
DJANGO_SETTINGS_MODULE=settings.dev
|
||||
SECRET_KEY=jkashdkjashdkjh
|
||||
BASE_URL=http://localhost:8000
|
||||
BASE_URL=http://localhost:8080
|
||||
|
||||
FEATURE_TELEGRAM_INTEGRATION_ENABLED=True
|
||||
FEATURE_SLACK_INTEGRATION_ENABLED=True
|
||||
FEATURE_EXTRA_MESSAGING_BACKENDS_ENABLED=
|
||||
|
||||
SLACK_INSTALL_RETURN_REDIRECT_HOST=http://localhost:8000
|
||||
SLACK_INSTALL_RETURN_REDIRECT_HOST=http://localhost:8080
|
||||
SOCIAL_AUTH_REDIRECT_IS_HTTPS=False
|
||||
|
||||
GRAFANA_INCIDENT_STATIC_API_KEY=
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ python manage.py createsuperuser
|
|||
3. Launch the backend:
|
||||
```bash
|
||||
# Http server:
|
||||
python manage.py runserver
|
||||
python manage.py runserver 8080
|
||||
|
||||
# Worker for background tasks (run it in the parallel terminal, don't forget to export .env there)
|
||||
python manage.py start_celery
|
||||
|
|
@ -73,7 +73,7 @@ python manage.py start_celery
|
|||
celery -A engine beat -l info
|
||||
```
|
||||
|
||||
4. All set! Check out internal API endpoints at http://localhost:8000/.
|
||||
4. All set! Check out internal API endpoints at http://localhost:8080/.
|
||||
|
||||
|
||||
### Frontend setup
|
||||
|
|
@ -102,7 +102,7 @@ python manage.py issue_invite_for_the_frontend --override
|
|||
6. Some configuration fields will appear be available. Fill them out and click Initialize OnCall
|
||||
```
|
||||
OnCall API URL:
|
||||
http://host.docker.internal:8000
|
||||
http://host.docker.internal:8080
|
||||
|
||||
Invitation Token (Single use token to connect Grafana instance):
|
||||
Response from the invite generator command (check above)
|
||||
|
|
@ -226,6 +226,7 @@ pytest --ds=settings.dev
|
|||
- Set Settings to settings/dev.py
|
||||
5. Create a new Django Server run configuration to Run/Debug the engine
|
||||
- Use a plugin such as EnvFile to load the .env file
|
||||
- Change port from 8000 to 8080
|
||||
|
||||
## Update drone build
|
||||
The .drone.yml build file must be signed when changes are made to it. Follow these steps:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<img width="400px" src="docs/img/logo.png">
|
||||
|
||||
Developer-friendly, incident response with brilliant Slack integration.
|
||||
Developer-friendly incident response with brilliant Slack integration.
|
||||
|
||||
<img width="60%" src="screenshot.png">
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ curl https://github.com/grafana/oncall/blob/dev/docker-compose.yml -o docker-com
|
|||
|
||||
2. Set variables:
|
||||
```bash
|
||||
echo "DOMAIN=http://localhost
|
||||
echo "DOMAIN=http://localhost:8080
|
||||
SECRET_KEY=my_random_secret_must_be_more_than_32_characters_long
|
||||
RABBITMQ_PASSWORD=rabbitmq_secret_pw
|
||||
MYSQL_PASSWORD=mysql_secret_pw
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ services:
|
|||
platform: linux/x86_64
|
||||
mem_limit: 500m
|
||||
cpus: 0.5
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
restart: always
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
|
|
|||
|
|
@ -92,13 +92,15 @@ services:
|
|||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
rabbitmq:
|
||||
condition: service_started
|
||||
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
platform: linux/x86_64
|
||||
mem_limit: 500m
|
||||
cpus: 0.5
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
restart: always
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
|
|
|||
BIN
docs/img/GrafanaOnCall_Stack_Fullcolor_black.png
Normal file
BIN
docs/img/GrafanaOnCall_Stack_Fullcolor_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
docs/img/How Grafana OnCall works_diagram.png
Normal file
BIN
docs/img/How Grafana OnCall works_diagram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
|
|
@ -21,15 +21,12 @@ To authorize, use the **Authorization** header:
|
|||
|
||||
```shell
|
||||
# With shell, you can just pass the correct header with each request
|
||||
curl "api_endpoint_here" --header "Authorization: meowmeowmeow"
|
||||
curl "api_endpoint_here" --header "Authorization: "api_key_here""
|
||||
```
|
||||
|
||||
Note that `meowmeowmeow` is a valid key for test purposes.
|
||||
Replace `meowmeowmeow` with your API key in production.
|
||||
Grafana OnCall uses API keys to allow access to the API. You can request a new OnCall API key in OnCall -> Settings page.
|
||||
|
||||
Grafana OnCall uses API keys to allow access to the API. You can request a new OnCall API key in the API section.
|
||||
|
||||
An API key is specific to a user and a Grafana stack. If you want to switch to a different team configuration, request a different API key.
|
||||
An API key is specific to a user and a Grafana stack. If you want to switch to a different stack configuration, request a different API key.
|
||||
|
||||
## Pagination
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ We prepared three environments for OSS users:
|
|||
|
||||
## Production Environment
|
||||
|
||||
TBD
|
||||
We prepared the helm chart for production environment: https://github.com/grafana/oncall/helm
|
||||
|
||||
## Slack Setup
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ Grafana OnCall Slack integration use a lot of Slack API features:
|
|||
# Choose the unique prefix instead of pretty-turkey-83
|
||||
# Localtunnel will generate an url, e.g. https://pretty-turkey-83.loca.lt
|
||||
# it is referred as <ONCALL_ENGINE_PUBLIC_URL> below
|
||||
lt --port 8000 -s pretty-turkey-83 --print-requests
|
||||
lt --port 8080 -s pretty-turkey-83 --print-requests
|
||||
```
|
||||
|
||||
3. If you use localtunnel, open your external URL and click "Continue" to allow requests to bypass the warning page.
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ class LiveSetting(models.Model):
|
|||
),
|
||||
"SEND_ANONYMOUS_USAGE_STATS": (
|
||||
"Grafana OnCall will send anonymous, but uniquely-identifiable usage analytics to Grafana Labs."
|
||||
" These statistics are sent to https://stats.grafana.org/. For more information on what's sent, look at"
|
||||
" https://github.com/grafana/oncall/blob/dev/engine/apps/oss_installation/usage_stats.py#L29"
|
||||
" These statistics are sent to https://stats.grafana.org/. For more information on what's sent, look at the "
|
||||
"<a href='https://github.com/grafana/oncall/blob/dev/engine/apps/oss_installation/usage_stats.py#L29'> source code</a>."
|
||||
),
|
||||
"GRAFANA_CLOUD_ONCALL_TOKEN": "Secret token for Grafana Cloud OnCall instance.",
|
||||
"GRAFANA_CLOUD_ONCALL_HEARTBEAT_ENABLED": "Enable hearbeat integration with Grafana Cloud OnCall.",
|
||||
|
|
|
|||
|
|
@ -226,9 +226,7 @@ USE_TZ = True
|
|||
# https://docs.djangoproject.com/en/2.1/howto/static-files/
|
||||
|
||||
STATIC_URL = "/static/"
|
||||
STATICFILES_DIRS = [
|
||||
"./static",
|
||||
]
|
||||
STATIC_ROOT = "./static/"
|
||||
|
||||
CELERY_BROKER_URL = "amqp://rabbitmq:rabbitmq@localhost:5672"
|
||||
|
||||
|
|
|
|||
|
|
@ -18,4 +18,4 @@ post-buffering=1
|
|||
|
||||
logger=stdio
|
||||
log-format=source=engine:uwsgi status=%(status) method=%(method) path=%(uri) latency=%(secs) google_trace_id=%(var.HTTP_X_CLOUD_TRACE_CONTEXT) protocol=%(proto) resp_size=%(size) req_body_size=%(cl)
|
||||
log-encoder=format ${strftime:%%Y-%%m-%%d %%H:%%M:%%S} ${msgnl}
|
||||
log-encoder=format ${strftime:%%Y-%%m-%%d %%H:%%M:%%S} ${msgnl}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
../CHANGELOG.md
|
||||
5
grafana-plugin/CHANGELOG.md
Normal file
5
grafana-plugin/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Change Log
|
||||
|
||||
## 0.0.71 (2022-06-06)
|
||||
|
||||
- Initial Release
|
||||
|
|
@ -100,7 +100,9 @@ const DefaultPageLayout: FC<DefaultPageLayoutProps> = observer((props) => {
|
|||
currentTeam &&
|
||||
currentUser &&
|
||||
store.isUserActionAllowed(UserAction.UpdateOwnSettings) &&
|
||||
(!currentUser.verified_phone_number || !currentUser.slack_user_identity) &&
|
||||
(!currentUser.verified_phone_number ||
|
||||
!currentUser.slack_user_identity ||
|
||||
currentUser.cloud_connection_status !== 3) &&
|
||||
!getItem(AlertID.CONNECTIVITY_WARNING)
|
||||
) && (
|
||||
<Alert
|
||||
|
|
@ -119,7 +121,9 @@ const DefaultPageLayout: FC<DefaultPageLayoutProps> = observer((props) => {
|
|||
{'. '}
|
||||
</>
|
||||
)}
|
||||
{!currentUser.verified_phone_number && 'Your phone number is not verified. '}
|
||||
{currentUser.cloud_connection_status !== 3 &&
|
||||
!currentUser.verified_phone_number &&
|
||||
'Your phone number is not verified. '}
|
||||
{currentTeam.slack_team_identity &&
|
||||
!currentUser.slack_user_identity &&
|
||||
'Your slack account is not connected. '}
|
||||
|
|
|
|||
|
|
@ -35,11 +35,10 @@ const cx = cn.bind(styles);
|
|||
interface Props extends PluginConfigPageProps<AppPluginMeta<OnCallAppSettings>> {}
|
||||
|
||||
export const PluginConfigPage = (props: Props) => {
|
||||
const grafanaUrlDefault = getItem('grafanaUrl') || window.location.origin;
|
||||
const { plugin } = props;
|
||||
const [onCallApiUrl, setOnCallApiUrl] = useState<string>(getItem('onCallApiUrl'));
|
||||
const [onCallInvitationToken, setOnCallInvitationToken] = useState<string>();
|
||||
const [grafanaUrl, setGrafanaUrl] = useState<string>(grafanaUrlDefault);
|
||||
const [grafanaUrl, setGrafanaUrl] = useState<string>(getItem('grafanaUrl'));
|
||||
const [pluginConfigLoading, setPluginConfigLoading] = useState<boolean>(true);
|
||||
const [pluginStatusOk, setPluginStatusOk] = useState<boolean>();
|
||||
const [pluginStatusMessage, setPluginStatusMessage] = useState<string>();
|
||||
|
|
@ -298,10 +297,10 @@ Seek for such a line: “Your invite token: <<LONG TOKEN>> , use it in the Graf
|
|||
label="OnCall backend URL"
|
||||
description={
|
||||
<Text>
|
||||
It should be rechable from Grafana. Possible options: <br />
|
||||
http://host.docker.internal:8000 (if you run backend in the docker locally)
|
||||
It should be reachable from Grafana. Possible options: <br />
|
||||
http://host.docker.internal:8080 (if you run backend in the docker locally)
|
||||
<br />
|
||||
http://localhost:8000 <br />
|
||||
http://localhost:8080 <br />
|
||||
...
|
||||
</Text>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ const CloudPhoneSettings = observer((props: CloudPhoneSettingsProps) => {
|
|||
}, []);
|
||||
|
||||
const handleLinkClick = (link: string) => {
|
||||
window.location.replace(link);
|
||||
window.open(link, '_blank');
|
||||
};
|
||||
|
||||
const syncUser = async () => {
|
||||
|
|
|
|||
|
|
@ -30,12 +30,19 @@
|
|||
background: var(--highlighted-row-bg);
|
||||
}
|
||||
|
||||
/* This is for Grafana 8, remove later */
|
||||
@media (max-width: 1540px) {
|
||||
.page-header__tabs > ul > li > a > div {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1540px) {
|
||||
.page-header__tabs > div > div > a > div {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
.sidemenu {
|
||||
position: fixed !important;
|
||||
|
|
|
|||
|
|
@ -69,10 +69,6 @@ const CloudPage = observer((props: CloudPageProps) => {
|
|||
setApiKeyError(false);
|
||||
}, []);
|
||||
|
||||
const saveKeyAndConnect = () => {
|
||||
setShowConfirmationModal(true);
|
||||
};
|
||||
|
||||
const disconnectCloudOncall = () => {
|
||||
setCloudIsConnected(false);
|
||||
store.cloudStore.disconnectToCloud();
|
||||
|
|
@ -105,7 +101,7 @@ const CloudPage = observer((props: CloudPageProps) => {
|
|||
};
|
||||
|
||||
const handleLinkClick = (link: string) => {
|
||||
window.location.replace(link);
|
||||
window.open(link, '_blank');
|
||||
};
|
||||
|
||||
const renderButtons = (user: Cloud) => {
|
||||
|
|
@ -130,10 +126,9 @@ const CloudPage = observer((props: CloudPageProps) => {
|
|||
return (
|
||||
<Button
|
||||
variant="secondary"
|
||||
icon="external-link-alt"
|
||||
size="sm"
|
||||
className={cx('table-button')}
|
||||
onClick={() => handleLinkClick(user?.cloud_data?.link)}
|
||||
onClick={() => getLocationSrv().update({ query: { page: 'users', p: page, id: user.id } })}
|
||||
>
|
||||
Configure notifications
|
||||
</Button>
|
||||
|
|
@ -343,7 +338,7 @@ const CloudPage = observer((props: CloudPageProps) => {
|
|||
>
|
||||
<Input id="cloudApiKey" onChange={handleChangeCloudApiKey} />
|
||||
</Field>
|
||||
<Button variant="primary" onClick={saveKeyAndConnect} disabled={!cloudApiKey} size="md">
|
||||
<Button variant="primary" onClick={connectToCloud} disabled={!cloudApiKey} size="md">
|
||||
Save key and connect
|
||||
</Button>
|
||||
</VerticalGroup>
|
||||
|
|
@ -387,23 +382,6 @@ const CloudPage = observer((props: CloudPageProps) => {
|
|||
) : (
|
||||
DisconnectedBlock
|
||||
)}
|
||||
|
||||
{showConfirmationModal && (
|
||||
<Modal
|
||||
isOpen
|
||||
title="Are you sure you want to connect to cloud?"
|
||||
onDismiss={() => setShowConfirmationModal(false)}
|
||||
>
|
||||
<HorizontalGroup>
|
||||
<Button variant="primary" onClick={connectToCloud}>
|
||||
Continue
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={() => setShowConfirmationModal(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</Modal>
|
||||
)}
|
||||
</VerticalGroup>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -22,3 +22,8 @@
|
|||
.description-style > a {
|
||||
color: var(--primary-text-link);
|
||||
}
|
||||
|
||||
.description-style {
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ import {
|
|||
} from '@grafana/ui';
|
||||
import cn from 'classnames/bind';
|
||||
import { omit } from 'lodash-es';
|
||||
import { observe } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Lambda } from 'mobx/lib/internal';
|
||||
import { AlignType } from 'rc-table/lib/interface';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
|
||||
|
|
@ -46,6 +48,23 @@ class LiveSettings extends React.Component<LiveSettingsProps, LiveSettingsState>
|
|||
hideValues: true,
|
||||
};
|
||||
|
||||
disposer: Lambda;
|
||||
|
||||
constructor(props: LiveSettingsProps) {
|
||||
super(props);
|
||||
|
||||
const { store } = props;
|
||||
|
||||
this.disposer = observe(store.userStore, (change) => {
|
||||
if (change.name === 'currentUserPk') {
|
||||
this.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.disposer();
|
||||
}
|
||||
componentDidMount() {
|
||||
this.update();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import plugin from '../../package.json'; // eslint-disable-line
|
||||
|
||||
export const APP_TITLE = 'Grafana OnCall';
|
||||
export const APP_SUBTITLE = `Incident Response (${plugin?.version})`;
|
||||
export const APP_SUBTITLE = `Developer-friendly incident response (${plugin?.version})`;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue