Post stack slug to chatops proxy (#4559)
# What this PR does It's part of work on https://github.com/grafana/oncall-gateway/issues/247. I added stack_slug to call to the chatops-proxy tenant/register API. On a side note I figured out that we didn't cleanup slack integration in chatops-proxy, once it's uninstalled on OnCall side, so it's [fixed](https://github.com/grafana/oncall/pull/4559/files#diff-1784f1d0d65fa477f4562e73aa23fe1c757b171f36e03f12600bdb021f121307R577) as well. Changes are validated locally.
This commit is contained in:
parent
d0ec596046
commit
bc6272744b
5 changed files with 58 additions and 4 deletions
|
|
@ -65,7 +65,7 @@ class ChatopsProxyAPIClient:
|
|||
|
||||
# OnCall Tenant
|
||||
def register_tenant(
|
||||
self, service_tenant_id: str, cluster_slug: str, service_type: str, stack_id: int
|
||||
self, service_tenant_id: str, cluster_slug: str, service_type: str, stack_id: int, stack_slug: str
|
||||
) -> tuple[Tenant, requests.models.Response]:
|
||||
url = f"{self.api_base_url}/tenants/register"
|
||||
d = {
|
||||
|
|
@ -74,6 +74,7 @@ class ChatopsProxyAPIClient:
|
|||
"cluster_slug": cluster_slug,
|
||||
"service_type": service_type,
|
||||
"stack_id": stack_id,
|
||||
"stack_slug": stack_slug,
|
||||
}
|
||||
}
|
||||
response = requests.post(url=url, json=d, headers=self._headers)
|
||||
|
|
@ -170,6 +171,22 @@ class ChatopsProxyAPIClient:
|
|||
self._check_response(response)
|
||||
return OAuthInstallation(**response.json()["oauth_installation"]), response
|
||||
|
||||
def delete_oauth_installation(
|
||||
self,
|
||||
stack_id: int,
|
||||
provider_type: str,
|
||||
grafana_user_id: int,
|
||||
) -> tuple[bool, requests.models.Response]:
|
||||
url = f"{self.api_base_url}/oauth_installations/uninstall"
|
||||
d = {
|
||||
"stack_id": stack_id,
|
||||
"provider_type": provider_type,
|
||||
"grafana_user_id": grafana_user_id,
|
||||
}
|
||||
response = requests.post(url=url, json=d, headers=self._headers)
|
||||
self._check_response(response)
|
||||
return response.json()["removed"], response
|
||||
|
||||
def _check_response(self, response: requests.models.Response):
|
||||
"""
|
||||
Wraps an exceptional response to ChatopsProxyAPIException
|
||||
|
|
|
|||
|
|
@ -18,14 +18,16 @@ def register_oncall_tenant_async(**kwargs):
|
|||
cluster_slug = kwargs.get("cluster_slug")
|
||||
service_type = kwargs.get("service_type")
|
||||
stack_id = kwargs.get("stack_id")
|
||||
stack_slug = kwargs.get("stack_slug")
|
||||
|
||||
client = ChatopsProxyAPIClient(settings.ONCALL_GATEWAY_URL, settings.ONCALL_GATEWAY_API_TOKEN)
|
||||
try:
|
||||
client.register_tenant(service_tenant_id, cluster_slug, service_type, stack_id)
|
||||
client.register_tenant(service_tenant_id, cluster_slug, service_type, stack_id, stack_slug)
|
||||
except ChatopsProxyAPIException as api_exc:
|
||||
task_logger.error(
|
||||
f'msg="Failed to register OnCall tenant: {api_exc.msg}" service_tenant_id={service_tenant_id} cluster_slug={cluster_slug}'
|
||||
)
|
||||
# TODO: remove this check once new upsert tenant api is released
|
||||
if api_exc.status == 409:
|
||||
# 409 Indicates that it's impossible to register tenant, because tenant already registered.
|
||||
# Not retrying in this case, because manual conflict-resolution needed.
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ def get_slack_oauth_response_from_chatops_proxy(stack_id) -> dict:
|
|||
return slack_installation.oauth_response
|
||||
|
||||
|
||||
def register_oncall_tenant(service_tenant_id: str, cluster_slug: str, stack_id: int):
|
||||
def register_oncall_tenant(service_tenant_id: str, cluster_slug: str, stack_id: int, stack_slug: str):
|
||||
"""
|
||||
register_oncall_tenant tries to register oncall tenant synchronously and fall back to task in case of any exceptions
|
||||
to make sure that tenant is registered.
|
||||
|
|
@ -61,6 +61,7 @@ def register_oncall_tenant(service_tenant_id: str, cluster_slug: str, stack_id:
|
|||
cluster_slug,
|
||||
SERVICE_TYPE_ONCALL,
|
||||
stack_id,
|
||||
stack_slug,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
|
|
@ -141,3 +142,23 @@ def unlink_slack_team(service_tenant_id: str, slack_team_id: str):
|
|||
"service_type": SERVICE_TYPE_ONCALL,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def uninstall_slack(stack_id: int, grafana_user_id: int) -> bool:
|
||||
"""
|
||||
uninstall_slack uninstalls slack integration from chatops-proxy and returns bool indicating if it was removed.
|
||||
If such installation does not exist - returns True as well.s
|
||||
"""
|
||||
client = ChatopsProxyAPIClient(settings.ONCALL_GATEWAY_URL, settings.ONCALL_GATEWAY_API_TOKEN)
|
||||
try:
|
||||
removed, response = client.delete_oauth_installation(stack_id, PROVIDER_TYPE_SLACK, grafana_user_id)
|
||||
except ChatopsProxyAPIException as api_exc:
|
||||
if api_exc.status == 404:
|
||||
return True
|
||||
logger.exception(
|
||||
"uninstall_slack: error trying to install slack from chatops-proxy: " "error=%s",
|
||||
api_exc,
|
||||
)
|
||||
return False
|
||||
|
||||
return removed is True
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from rest_framework.views import APIView
|
|||
from apps.api.permissions import RBACPermission
|
||||
from apps.auth_token.auth import PluginAuthentication
|
||||
from apps.base.utils import live_settings
|
||||
from apps.chatops_proxy.utils import uninstall_slack as uninstall_slack_from_chatops_proxy
|
||||
from apps.slack.client import SlackClient
|
||||
from apps.slack.errors import SlackAPIError
|
||||
from apps.slack.scenarios.alertgroup_appearance import STEPS_ROUTING as ALERTGROUP_APPEARANCE_ROUTING
|
||||
|
|
@ -573,8 +574,19 @@ class ResetSlackView(APIView):
|
|||
"Grafana OnCall is temporary unable to connect your slack account or install OnCall to your slack workspace",
|
||||
status=400,
|
||||
)
|
||||
if settings.UNIFIED_SLACK_APP_ENABLED:
|
||||
# If unified slack app is enabled - uninstall slack integration from chatops-proxy first and on success -
|
||||
# uninstall it from OnCall.
|
||||
removed = uninstall_slack_from_chatops_proxy(request.user.organization.stack_id, request.user.user_id)
|
||||
else:
|
||||
# just a placeholder value to continute uninstallation until UNIFIED_SLACK_APP_ENABLED is not enabled
|
||||
removed = True
|
||||
if not removed:
|
||||
return Response({"error": "Failed to uninstall slack integration"}, status=500)
|
||||
|
||||
try:
|
||||
uninstall_slack_integration(request.user.organization, request.user)
|
||||
except SlackInstallationExc as e:
|
||||
return Response({"error": e.error_message}, status=400)
|
||||
|
||||
return Response(status=200)
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ class OrganizationQuerySet(models.QuerySet):
|
|||
def create(self, **kwargs):
|
||||
instance = super().create(**kwargs)
|
||||
if settings.FEATURE_MULTIREGION_ENABLED:
|
||||
register_oncall_tenant(str(instance.uuid), settings.ONCALL_BACKEND_REGION, instance.stack_id)
|
||||
register_oncall_tenant(
|
||||
str(instance.uuid), settings.ONCALL_BACKEND_REGION, instance.stack_id, instance.stack_slug
|
||||
)
|
||||
return instance
|
||||
|
||||
def delete(self):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue