148 lines
6.2 KiB
Python
148 lines
6.2 KiB
Python
# ============================================================
|
||
# Система: Единая библиотека, Центр ИИ НИУ ВШЭ
|
||
# Модуль: Управления базовыми объектами 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")
|