Refactor gcom api calls when syncing org (#3489)

Make one API call instead of two.
This commit is contained in:
Matias Bordese 2023-12-04 10:08:59 -03:00 committed by GitHub
parent a3e3d8bc9d
commit 9eb09c0272
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 43 deletions

View file

@ -371,11 +371,7 @@ class GcomAPIClient(APIClient):
or feature_enabled_via_enable_key_comma_delimited
)
def is_rbac_enabled_for_stack(self, stack_id: str) -> bool:
"""
NOTE: must use an "Admin" GCOM token when calling this method
"""
instance_info = self.get_instance_info(stack_id, True)
def is_rbac_enabled_for_instance(self, instance_info: GCOMInstanceInfo = None) -> bool:
if not instance_info:
return False
return self._feature_toggle_is_enabled(instance_info, "accessControlOnCall")

View file

@ -12,7 +12,7 @@ class TestIsRbacEnabledForStack:
TEST_FEATURE_TOGGLE = "helloWorld"
@pytest.mark.parametrize(
"gcom_api_response,expected",
"instance_info,expected",
[
(None, False),
({}, False),
@ -22,16 +22,9 @@ class TestIsRbacEnabledForStack:
({"config": {"feature_toggles": {"accessControlOnCall": "true"}}}, True),
],
)
@patch("apps.grafana_plugin.helpers.client.GcomAPIClient.api_get")
def test_it_returns_based_on_feature_toggle_value(
self, mocked_gcom_api_client_api_get, gcom_api_response, expected
):
stack_id = 5
mocked_gcom_api_client_api_get.return_value = (gcom_api_response, {"status_code": 200})
def test_it_returns_based_on_feature_toggle_value(self, instance_info, expected):
api_client = GcomAPIClient("someFakeApiToken")
assert api_client.is_rbac_enabled_for_stack(stack_id) == expected
assert mocked_gcom_api_client_api_get.called_once_with(f"instances/{stack_id}?config=true")
assert api_client.is_rbac_enabled_for_instance(instance_info) == expected
@pytest.mark.parametrize(
"instance_info_feature_toggles,delimiter,expected",

View file

@ -13,24 +13,9 @@ logger.setLevel(logging.DEBUG)
def sync_organization(organization: Organization) -> None:
grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token)
# NOTE: checking whether or not RBAC is enabled depends on whether we are dealing with an open-source or cloud
# stack. For Cloud we should make a call to the GCOM API, using an admin API token, and get the list of
# feature_toggles enabled for the stack. For open-source, simply make a HEAD request to the grafana instance's API
# and consider RBAC enabled if the list RBAC permissions endpoint returns 200. We cannot simply rely on the HEAD
# call in cloud because if an instance is not active, the grafana gateway will still return 200 for the
# HEAD request.
if settings.LICENSE == settings.CLOUD_LICENSE_NAME:
gcom_client = GcomAPIClient(settings.GRAFANA_COM_ADMIN_API_TOKEN)
rbac_is_enabled = gcom_client.is_rbac_enabled_for_stack(organization.stack_id)
else:
rbac_is_enabled = grafana_api_client.is_rbac_enabled_for_organization()
organization.is_rbac_permissions_enabled = rbac_is_enabled
_sync_instance_info(organization)
grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token)
_, check_token_call_status = grafana_api_client.check_token()
if check_token_call_status["connected"]:
organization.api_token_status = Organization.API_TOKEN_STATUS_OK
@ -62,7 +47,7 @@ def sync_organization(organization: Organization) -> None:
def _sync_instance_info(organization: Organization) -> None:
if organization.gcom_token:
gcom_client = GcomAPIClient(organization.gcom_token)
instance_info = gcom_client.get_instance_info(organization.stack_id)
instance_info = gcom_client.get_instance_info(organization.stack_id, include_config_query_param=True)
if not instance_info or instance_info["orgId"] != organization.org_id:
return
@ -73,7 +58,17 @@ def _sync_instance_info(organization: Organization) -> None:
organization.region_slug = instance_info["regionSlug"]
organization.grafana_url = instance_info["url"]
organization.cluster_slug = instance_info["clusterSlug"]
organization.is_rbac_permissions_enabled = gcom_client.is_rbac_enabled_for_instance(instance_info)
organization.gcom_token_org_last_time_synced = timezone.now()
else:
# NOTE: checking whether or not RBAC is enabled depends on whether we are dealing with an open-source or cloud
# stack. For Cloud we should make a call to the GCOM API, using an admin API token, and get the list of
# feature_toggles enabled for the stack. For open-source, simply make a HEAD request to the grafana instance's API
# and consider RBAC enabled if the list RBAC permissions endpoint returns 200. We cannot simply rely on the HEAD
# call in cloud because if an instance is not active, the grafana gateway will still return 200 for the
# HEAD request.
grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token)
organization.is_rbac_permissions_enabled = grafana_api_client.is_rbac_enabled_for_organization()
def sync_users_and_teams(client: GrafanaAPIClient, organization: Organization) -> None:

View file

@ -312,18 +312,36 @@ def test_sync_organization_is_rbac_permissions_enabled_open_source(make_organiza
assert organization.is_rbac_permissions_enabled == grafana_api_response
@pytest.mark.parametrize("gcom_api_response", [False, True])
@patch("apps.user_management.sync.GcomAPIClient")
@override_settings(LICENSE=settings.CLOUD_LICENSE_NAME)
@override_settings(GRAFANA_COM_ADMIN_API_TOKEN="mockedToken")
@patch("apps.user_management.sync.GcomAPIClient.api_get")
@pytest.mark.parametrize(
"instance_info,expected",
[
({"config": {"feature_toggles": {}}}, False),
({"config": {"feature_toggles": {"accessControlOnCall": "false"}}}, False),
({"config": {"feature_toggles": {"accessControlOnCall": "true"}}}, True),
],
)
@pytest.mark.django_db
def test_sync_organization_is_rbac_permissions_enabled_cloud(mocked_gcom_client, make_organization, gcom_api_response):
def test_sync_organization_is_rbac_permissions_enabled_cloud(
mocked_gcom_client, make_organization, instance_info, expected
):
stack_id = 5
organization = make_organization(stack_id=stack_id)
organization = make_organization(stack_id=stack_id, gcom_token="TEST_GCOM_TOKEN")
api_check_token_call_status = {"connected": True}
mocked_gcom_client.return_value.is_rbac_enabled_for_stack.return_value = gcom_api_response
instance_info.update(
{
"orgId": organization.org_id,
"slug": organization.stack_slug,
"orgSlug": organization.org_slug,
"orgName": organization.org_title,
"regionSlug": organization.region_slug,
"url": organization.grafana_url,
"clusterSlug": organization.cluster_slug,
}
)
mocked_gcom_client.return_value = (instance_info, {"status_code": 200})
api_users_response = (
{
@ -367,10 +385,7 @@ def test_sync_organization_is_rbac_permissions_enabled_cloud(mocked_gcom_client,
sync_organization(organization)
organization.refresh_from_db()
assert mocked_gcom_client.return_value.called_once_with("mockedToken")
assert mocked_gcom_client.return_value.is_rbac_enabled_for_stack.called_once_with(stack_id)
assert organization.is_rbac_permissions_enabled == gcom_api_response
assert organization.is_rbac_permissions_enabled == expected
@pytest.mark.django_db