diff --git a/README.md b/README.md index f6c0e447..1eea669c 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,13 @@ Developer-friendly incident response with brilliant Slack integration. We prepared multiple environments: [production](https://grafana.com/docs/grafana-cloud/oncall/open-source/#production-environment), [developer](DEVELOPER.md) and hobby: 1. Download docker-compose.yaml: + ```bash curl -fsSL https://raw.githubusercontent.com/grafana/oncall/dev/docker-compose.yml -o docker-compose.yml ``` 2. Set variables: + ```bash echo "DOMAIN=http://localhost:8080 SECRET_KEY=my_random_secret_must_be_more_than_32_characters_long @@ -37,26 +39,31 @@ GRAFANA_PASSWORD=admin" > .env_hobby ``` 3. Launch services: + ```bash docker-compose --env-file .env_hobby -f docker-compose.yml up -d ``` 4. Issue one-time invite token: + ```bash docker-compose --env-file .env_hobby -f docker-compose.yml run engine python manage.py issue_invite_for_the_frontend --override ``` +**Note**: if you remove the plugin configuration and reconfigure it, you will need to generate a new one-time invite token for your new configuration. + 5. Go to [OnCall Plugin Configuration](http://localhost:3000/plugins/grafana-oncall-app), using log in credentials as defined above: `admin`/`admin` (or find OnCall plugin in configuration->plugins) and connect OnCall _plugin_ with OnCall _backend_: + ``` Invite token: ^^^ from the previous step. OnCall backend URL: http://engine:8080 Grafana Url: http://grafana:3000 ``` -6. Enjoy! Check our [OSS docs](https://grafana.com/docs/grafana-cloud/oncall/open-source/) if you want to set up Slack, Telegram, Twilio or SMS/calls through Grafana Cloud. - +6. Enjoy! Check our [OSS docs](https://grafana.com/docs/grafana-cloud/oncall/open-source/) if you want to set up Slack, Telegram, Twilio or SMS/calls through Grafana Cloud. ## Update version + To update your Grafana OnCall hobby environment: ```shell @@ -76,14 +83,13 @@ See [Grafana docs](https://grafana.com/docs/grafana/latest/administration/plugin - ## Stargazers over time [![Stargazers over time](https://starchart.cc/grafana/oncall.svg)](https://starchart.cc/grafana/oncall) - ## Further Reading -- *Migration from the PagerDuty* - [Migrator](https://github.com/grafana/oncall/tree/dev/tools/pagerduty-migrator) -- *Documentation* - [Grafana OnCall](https://grafana.com/docs/grafana-cloud/oncall/) -- *Blog Post* - [Announcing Grafana OnCall, the easiest way to do on-call management](https://grafana.com/blog/2021/11/09/announcing-grafana-oncall/) -- *Presentation* - [Deep dive into the Grafana, Prometheus, and Alertmanager stack for alerting and on-call management](https://grafana.com/go/observabilitycon/2021/alerting/?pg=blog) + +- _Migration from the PagerDuty_ - [Migrator](https://github.com/grafana/oncall/tree/dev/tools/pagerduty-migrator) +- _Documentation_ - [Grafana OnCall](https://grafana.com/docs/grafana-cloud/oncall/) +- _Blog Post_ - [Announcing Grafana OnCall, the easiest way to do on-call management](https://grafana.com/blog/2021/11/09/announcing-grafana-oncall/) +- _Presentation_ - [Deep dive into the Grafana, Prometheus, and Alertmanager stack for alerting and on-call management](https://grafana.com/go/observabilitycon/2021/alerting/?pg=blog) diff --git a/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx b/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx index 264315b3..e199bf02 100644 --- a/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx +++ b/grafana-plugin/src/containers/PluginConfigPage/PluginConfigPage.tsx @@ -11,12 +11,8 @@ import { Label, Legend, LoadingPlaceholder, - Icon, - Alert, - Modal, } from '@grafana/ui'; import cn from 'classnames/bind'; -import CopyToClipboard from 'react-copy-to-clipboard'; import { OnCallAppSettings } from 'types'; import Block from 'components/GBlock/Block'; @@ -28,6 +24,8 @@ import { createGrafanaToken, getPluginSyncStatus, startPluginSync, updateGrafana import { GRAFANA_LICENSE_OSS } from 'utils/consts'; import { getItem, setItem } from 'utils/localStorage'; +import { constructSyncErrorMessage, constructErrorActionMessage } from './helpers'; + import styles from './PluginConfigPage.module.css'; const cx = cn.bind(styles); @@ -45,6 +43,8 @@ export const PluginConfigPage = (props: Props) => { const [isSelfHostedInstall, setIsSelfHostedInstall] = useState(true); const [retrySync, setRetrySync] = useState(false); + const INVALID_INVITE_TOKEN_ERROR_MSG = `It seems like your invite token may be invalid. ${constructErrorActionMessage('generating a new invite token')}`; + const setupPlugin = useCallback(async () => { setItem('onCallApiUrl', onCallApiUrl); setItem('grafanaUrl', grafanaUrl); @@ -129,25 +129,37 @@ export const PluginConfigPage = (props: Props) => { }, []); const handleSyncException = useCallback((e) => { + const buildErrMsg = (msg: string): string => + constructSyncErrorMessage(msg, plugin.meta.jsonData.onCallApiUrl); + if (plugin.meta.jsonData?.onCallApiUrl) { - let statusMessage = plugin.meta.jsonData.onCallApiUrl + '\n' + e + ', retry or check settings & re-initialize.'; - if (e.response.status == 404) { - statusMessage += '\nIf Grafana OnCall was just installed, restart Grafana for OnCall routes to be available.'; + const { status: statusCode } = e.response; + + let statusMessage: string; + + if (statusCode == 403) { + statusMessage = buildErrMsg(INVALID_INVITE_TOKEN_ERROR_MSG); + } else if (statusCode === 404) { + statusMessage = buildErrMsg('If Grafana OnCall was just installed, restart Grafana for OnCall routes to be available.'); + } else if (statusCode === 502) { + statusMessage = buildErrMsg(`Unable to communicate with either the Grafana API, or Grafana OnCall engine API. ${constructErrorActionMessage('verify that the API URLs that you entered are correct')}`); + } else { + statusMessage = buildErrMsg(`An unknown error occured. ${constructErrorActionMessage()}. If the error still occurs please reach out to support.`) } setPluginStatusMessage(statusMessage); setRetrySync(true); } else { - setPluginStatusMessage('OnCall has not been setup, configure & initialize below.'); + setPluginStatusMessage(buildErrMsg('OnCall has not been setup, configure & initialize below.')); } setPluginStatusOk(false); setPluginConfigLoading(false); }, []); - const finishSync = useCallback((get_sync_response) => { - if (get_sync_response.token_ok) { + const finishSync = useCallback((getSyncResponse) => { + if (getSyncResponse.token_ok) { const versionInfo = - get_sync_response.version && get_sync_response.license - ? ` (${get_sync_response.license}, ${get_sync_response.version})` + getSyncResponse.version && getSyncResponse.license + ? ` (${getSyncResponse.license}, ${getSyncResponse.version})` : ''; let pluginStatusMessage = `Connected to OnCall${versionInfo}\n - OnCall URL: ${plugin.meta.jsonData.onCallApiUrl}\n` @@ -159,9 +171,8 @@ export const PluginConfigPage = (props: Props) => { setIsSelfHostedInstall(plugin.meta.jsonData?.license === GRAFANA_LICENSE_OSS); setPluginStatusOk(true); } else { - setPluginStatusMessage( - `OnCall failed to connect to this grafana via: ${plugin.meta.jsonData.grafanaUrl} check URL, network, and API key.` - ); + setPluginStatusMessage(constructSyncErrorMessage(INVALID_INVITE_TOKEN_ERROR_MSG, + plugin.meta.jsonData.grafanaUrl)); setRetrySync(true); } setPluginConfigLoading(false); @@ -221,14 +232,10 @@ export const PluginConfigPage = (props: Props) => { )}

{'Plugin <-> backend connection status'}

-            {pluginStatusMessage}
+            {pluginStatusMessage}
           
- {/*

{'Plugin <-> backend connection status'}

-
-                {pluginStatusMessage}
-              
*/} {retrySync && (