unip-controller/controller/src/basic_resources/rbac.py

149 lines
6.2 KiB
Python
Raw Normal View History

2025-01-29 13:13:51 +00:00
# ============================================================
# Система: Единая библиотека, Центр ИИ НИУ ВШЭ
# Модуль: Управления базовыми объектами Kubernetes
# Авторы: Полежаев В.А., Хританков А.С.
# Дата создания: 2024 г.
# ============================================================
"""
RBAC basic resources module. Implements reusable RBAC-related functions.
"""
import kopf
from kubernetes.client import RbacAuthorizationV1Api, ApiException, CoreV1Api, ApiClient
_DEFAULT_SA_NAME = 'default'
def update_default_sa(api_client, namespace, manifest, logger):
"""
Обновляет сервисный аккаунт (ServiceAccount) 'default'.
Функция является идемпотентной.
Если сервисный аккаунт отсутствует, то обработчик выбрасывает
исключение kopf.TemporaryError, что приводит к повторному
вызову метода спустия заданную задержку.
Если сервисный аккаунт существует, то его спецификация
замещается переданной в параметре `manifest`.
:api_client: Kubernetes API клиент
:param namespace: Пространство имен
:param manifest: Спецификация сервисного аккаунта
:param logger: kopf logger
:return: None.
"""
core_v1_api = CoreV1Api(api_client)
try:
core_v1_api.read_namespaced_service_account(_DEFAULT_SA_NAME, namespace)
except ApiException as exc:
if exc.status == 404:
# SA с именем 'default' всегда существует и создается Kubernetes,
# если отсутствует - нужно подождать
logger.info(f'SA {_DEFAULT_SA_NAME} does not exists.')
raise kopf.TemporaryError(f"Waiting for SA {_DEFAULT_SA_NAME} "
f"to be created by Kubernetes system...",
delay=10)
raise exc
logger.info(f"SA {_DEFAULT_SA_NAME} exists, trying to replace...")
core_v1_api.replace_namespaced_service_account(name=_DEFAULT_SA_NAME, namespace=namespace, body=manifest)
def delete_sa_if_exists(api_client: ApiClient, name, namespace, logger):
core_v1_api = CoreV1Api(api_client)
try:
# не имеет смысла для default SA - будет пересоздан Kubernetes
# оставлено для общего соответствия и на случай изменения имени SA
core_v1_api.delete_namespaced_service_account(name=name, namespace=namespace)
except ApiException as exc:
if exc.status == 404:
logger.warn(f"SA {name} doesnt exist, do nothing")
return
raise exc
logger.info(f"SA {name} is deleted")
def create_role(api_client, name, namespace, manifest):
"""
Создает роль (Role).
Функция является идемпотентной. Если роль существует,
то она будет обновлена.
:param api_client: Kubernetes API клиент
:param name: Имя роли
:param namespace: Пространство имен
:param manifest: Спецификация роли
:return: None.
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
rbac_v1_api.replace_namespaced_role(name=name, namespace=namespace, body=manifest)
def delete_role_if_exists(api_client, name, namespace, logger):
"""
Удаляет роль (Role), если она существует.
Функция является идемпотентной.
Если роль существует, то она будет удалена.
Если роль не существует, то ничего не произойдет.
:param api_client: Kuberentes API клиент
:param name: Имя роли
:param namespace: Пространство имен
:param logger: kopf logger
:return: None
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
try:
rbac_v1_api.delete_namespaced_role(name=name, namespace=namespace)
except ApiException as exc:
if exc.status == 404:
logger.warn(f"Role {name} doesnt exist, do nothing")
return
raise exc
logger.info(f"Role {name} is deleted")
def create_rb(api_client, name, namespace, manifest):
"""
Создает привязку роли (RoleBinding).
Функция является идемпотентной. Если привязка роли существует,
то она будет обновлена.
:param api_client: Kubernetes API клиент
:param name: Имя привязки роли
:param namespace: Пространство имен
:param manifest: Спецификация привязки роли
:return: None.
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
rbac_v1_api.replace_namespaced_role_binding(name=name, namespace=namespace, body=manifest)
def delete_rb_if_exists(api_client, name, namespace, logger):
"""
Удаляет привязку роли (RoleBinding), если она существует.
Функция является идемпотентной.
Если привязка роли существует, то она будет удалена.
Если привязка роли не существует, то ничего не произойдет.
:param api_client: Kuberentes API клиент
:param name: Имя привязки роли
:param namespace: Пространство имен
:param logger: kopf logger
:return: None
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
try:
rbac_v1_api.delete_namespaced_role_binding(name=name,
namespace=namespace)
except ApiException as exc:
if exc.status == 404:
logger.warn(f"RoleBinding {name} doesnt exist, do nothing")
return
raise exc
logger.info(f"RoleBinding {name} is deleted")