oncall-engine/engine/apps/grafana_plugin/tests/test_self_hosted_install.py
Vadim Stepanov b2f4ffb98a
apps.get_model -> import (#2619)
# What this PR does

Remove
[`apps.get_model`](https://docs.djangoproject.com/en/3.2/ref/applications/#django.apps.apps.get_model)
invocations and use inline `import` statements in places where models
are imported within functions/methods to avoid circular imports.

I believe `import` statements are more appropriate for most use cases as
they allow for better static code analysis & formatting, and solve the
issue of circular imports without being unnecessarily dynamic as
`apps.get_model`. With `import` statements, it's possible to:

- Jump to model definitions in most IDEs
- Automatically sort inline imports with `isort`
- Find import errors faster/easier (most IDEs highlight broken imports)
- Have more consistency across regular & inline imports when importing
models

This PR also adds a flake8 rule to ban imports of `django.apps.apps`, so
it's harder to use `apps.get_model` by mistake (it's possible to ignore
this rule by using `# noqa: I251`). The rule is not enforced on
directories with migration files, because `apps.get_model` is often used
to get a historical state of a model, which is useful when writing
migrations ([see this SO answer for more
details](https://stackoverflow.com/a/37769213)). So `apps.get_model` is
considered OK in migrations (even necessary in some cases).

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
2023-07-25 09:43:23 +00:00

172 lines
7.1 KiB
Python

import json
from unittest.mock import patch
import pytest
from django.conf import settings
from django.test import override_settings
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
GRAFANA_TOKEN = "TEST_TOKEN"
STACK_ID = 1
ORG_ID = 5
GRAFANA_API_URL = "hello.com"
LICENSE = "OpenSource"
STACK_SLUG = "asdfasdf"
ORG_SLUG = "hellooo"
ORG_TITLE = "nmvcnmvnmvc"
REGION_SLUG = "nmcvnmcvnmcvnmcv"
CLUSTER_SLUG = "nmcvnmcvnmcvnmcvnmcv"
SELF_HOSTED_SETTINGS = {
"GRAFANA_API_URL": GRAFANA_API_URL,
"STACK_ID": STACK_ID,
"ORG_ID": ORG_ID,
"LICENSE": LICENSE,
"STACK_SLUG": STACK_SLUG,
"ORG_SLUG": ORG_SLUG,
"ORG_TITLE": ORG_TITLE,
"REGION_SLUG": REGION_SLUG,
"CLUSTER_SLUG": CLUSTER_SLUG,
}
UNABLE_TO_FIND_GRAFANA_ERROR_MSG = f"Unable to connect to the specified Grafana API - {GRAFANA_API_URL}"
UNAUTHED_GRAFANA_API_ERROR_MSG = (
f"You are not authorized to communicate with the specified Grafana API - {GRAFANA_API_URL}"
)
@pytest.fixture
def make_self_hosted_install_header():
def _make_instance_context_header(token):
return {
"HTTP_X-Instance-Context": json.dumps({"grafana_token": token}),
}
return _make_instance_context_header
@override_settings(LICENSE=settings.CLOUD_LICENSE_NAME)
def test_a_cloud_license_gets_an_unauthorized_error(make_self_hosted_install_header):
client = APIClient()
url = reverse("grafana-plugin:self-hosted-install")
response = client.post(url, format="json", **make_self_hosted_install_header(GRAFANA_TOKEN))
assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.parametrize(
"grafana_api_status_code,expected_error_msg",
[
(status.HTTP_404_NOT_FOUND, UNABLE_TO_FIND_GRAFANA_ERROR_MSG),
(status.HTTP_401_UNAUTHORIZED, UNAUTHED_GRAFANA_API_ERROR_MSG),
(status.HTTP_401_UNAUTHORIZED, UNAUTHED_GRAFANA_API_ERROR_MSG),
],
)
@override_settings(SELF_HOSTED_SETTINGS=SELF_HOSTED_SETTINGS)
@patch("apps.grafana_plugin.views.self_hosted_install.GrafanaAPIClient")
def test_it_properly_handles_errors_from_the_grafana_api(
mocked_grafana_api_client, make_self_hosted_install_header, grafana_api_status_code, expected_error_msg
):
mocked_grafana_api_client.return_value.check_token.return_value = (None, {"status_code": grafana_api_status_code})
client = APIClient()
url = reverse("grafana-plugin:self-hosted-install")
response = client.post(url, format="json", **make_self_hosted_install_header(GRAFANA_TOKEN))
assert mocked_grafana_api_client.called_once_with(api_url=GRAFANA_API_URL, api_token=GRAFANA_TOKEN)
assert mocked_grafana_api_client.return_value.check_token.called_once_with()
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.data["error"] == expected_error_msg
@override_settings(SELF_HOSTED_SETTINGS=SELF_HOSTED_SETTINGS)
@pytest.mark.django_db
@patch("apps.grafana_plugin.views.self_hosted_install.GrafanaAPIClient")
@patch("apps.grafana_plugin.views.self_hosted_install.sync_organization")
@patch("apps.grafana_plugin.views.self_hosted_install.Organization.provision_plugin")
@patch("apps.grafana_plugin.views.self_hosted_install.Organization.revoke_plugin")
def test_if_organization_exists_it_is_updated(
mocked_revoke_plugin,
mocked_provision_plugin,
mocked_sync_organization,
mocked_grafana_api_client,
make_self_hosted_install_header,
make_organization,
):
organization = make_organization(stack_id=STACK_ID, org_id=ORG_ID)
provision_plugin_response = {"stackId": STACK_ID, "orgId": ORG_ID, "onCallToken": "HELLOOO", "license": LICENSE}
mocked_provision_plugin.return_value = provision_plugin_response
mocked_grafana_api_client.return_value.check_token.return_value = (None, {"status_code": status.HTTP_200_OK})
mocked_grafana_api_client.return_value.is_rbac_enabled_for_organization.return_value = True
client = APIClient()
url = reverse("grafana-plugin:self-hosted-install")
response = client.post(url, format="json", **make_self_hosted_install_header(GRAFANA_TOKEN))
assert mocked_grafana_api_client.called_once_with(api_url=GRAFANA_API_URL, api_token=GRAFANA_TOKEN)
assert mocked_grafana_api_client.return_value.check_token.called_once_with()
assert mocked_grafana_api_client.return_value.is_rbac_enabled_for_organization.called_once_with()
assert mocked_sync_organization.called_once_with(organization)
assert mocked_provision_plugin.called_once_with()
assert mocked_revoke_plugin.called_once_with()
assert response.status_code == status.HTTP_201_CREATED
assert response.data == {"error": None, **provision_plugin_response}
organization.refresh_from_db()
assert organization.grafana_url == GRAFANA_API_URL
assert organization.api_token == GRAFANA_TOKEN
assert organization.is_rbac_permissions_enabled is True
@override_settings(SELF_HOSTED_SETTINGS=SELF_HOSTED_SETTINGS)
@pytest.mark.django_db
@patch("apps.grafana_plugin.views.self_hosted_install.GrafanaAPIClient")
@patch("apps.grafana_plugin.views.self_hosted_install.sync_organization")
@patch("apps.grafana_plugin.views.self_hosted_install.Organization.provision_plugin")
@patch("apps.grafana_plugin.views.self_hosted_install.Organization.revoke_plugin")
def test_if_organization_does_not_exist_it_is_created(
mocked_revoke_plugin,
mocked_provision_plugin,
mocked_sync_organization,
mocked_grafana_api_client,
make_self_hosted_install_header,
):
provision_plugin_response = {"stackId": STACK_ID, "orgId": ORG_ID, "onCallToken": "HELLOOO", "license": LICENSE}
mocked_provision_plugin.return_value = provision_plugin_response
mocked_grafana_api_client.return_value.check_token.return_value = (None, {"status_code": status.HTTP_200_OK})
mocked_grafana_api_client.return_value.is_rbac_enabled_for_organization.return_value = True
client = APIClient()
url = reverse("grafana-plugin:self-hosted-install")
response = client.post(url, format="json", **make_self_hosted_install_header(GRAFANA_TOKEN))
from apps.user_management.models import Organization
organization = Organization.objects.filter(stack_id=STACK_ID, org_id=ORG_ID).first()
assert mocked_grafana_api_client.called_once_with(api_url=GRAFANA_API_URL, api_token=GRAFANA_TOKEN)
assert mocked_grafana_api_client.return_value.check_token.called_once_with()
assert mocked_grafana_api_client.return_value.is_rbac_enabled_for_organization.called_once_with()
assert mocked_sync_organization.called_once_with(organization)
assert mocked_provision_plugin.called_once_with()
assert not mocked_revoke_plugin.called
assert response.status_code == status.HTTP_201_CREATED
assert response.data == {"error": None, **provision_plugin_response}
assert organization.stack_id == STACK_ID
assert organization.stack_slug == STACK_SLUG
assert organization.org_slug == ORG_SLUG
assert organization.org_title == ORG_TITLE
assert organization.region_slug == REGION_SLUG
assert organization.grafana_url == GRAFANA_API_URL
assert organization.api_token == GRAFANA_TOKEN
assert organization.is_rbac_permissions_enabled is True