Валідація є частиною життєвого циклу додатка AWS CDK, що описано в офіційній документації в розділі Синтез додатка CDK:
Усі конструкції, які реалізували метод validate, можуть здійснювати валідацію для перевірки того, що вони знаходяться в стані, яке дозволяє коректно виконати розгортання. Ви отримаєте сповіщення про будь-які помилки валідації, що виникли під час цього етапу. Загалом, рекомендується виконувати валідацію якнайшвидше (зазвичай, як тільки ви отримуєте деякі вхідні дані) та кидати виключення якомога раніше. Раннє виконання валідації покращує надійність, оскільки трасування стеку буде більш точним, і це гарантує, що ваш код може продовжувати виконуватись безпечно.
Хоча є хороші статті, що описують, як обробляти валідацію AWS CDK у TypeScript, я не зміг знайти відповідний приклад у Python. Після створення кількох валідацій у Python, наступні приклади доповнюють статті, згадані нижче.
Наступні приклади були розроблені за допомогою AWS CDK v2.176.0 і Python 3.13.1.
Приклад валідації
Реалізація валідації здійснюється за допомогою методу validate, який повертає список повідомлень про помилки. Якщо список порожній, помилок немає, а кілька записів відповідають різним перевіркам валідації, що не пройшли. Логіка валідації інкапсульована в класі, позначеному @jsii.implements(IValidation),, що вказує на правильний тип для використання при валідації. У цьому конкретному випадку перевіряється, що передане у валідацію відро Amazon S3 використовує власний AWS KMS ключ, що дає більше контролю над процесом шифрування порівняно з типовим шифруванням, яке використовує Amazon S3.
@jsii.implements(IValidation)
class KodlotS3KmsValidator:
"""Перевірка, чи зашифроване відро S3 за допомогою власного KMS ключа."""
def __init__(self, s3_bucket: s3.Bucket):
self.s3_bucket = s3_bucket
def validate(self) -> List[str]:
error_messages: List[str] = []
if self.s3_bucket.encryption_key is None:
error_messages.append(f"Відро повинно бути зашифроване за допомогою власного KMS ключа")
return error_messages
Приклад конструкції AWS CDK
Це базовий приклад конструкції AWS CDK, яка додає одну валідацію за допомогою методу addvalidation_ вузла конструкції в дереві області видимості. Під час реалізації була допущена помилка, коли створювався власний AWS KMS ключ, але він не передавався в параметр encryptionkey_ конструкції Amazon S3 Bucket.
class KodlotS3Bucket(Construct):
"""Відро S3 з валідаціями."""
def __init__(self, scope: Construct, construct_id: str, bucket_name: str) -> None:
super().__init__(scope, construct_id)
s3_kms_key = kms.Key(self, f"KodlotS3KmsKey{bucket_name.title()}")
self.s3_bucket = s3.Bucket(
self,
f"KodlotS3{bucket_name.title()}",
bucket_name=bucket_name,
encryption_key=None,
)
self.node.add_validation(KodlotS3KmsValidator(self.s3_bucket))
Цей тип помилки може бути легко не поміченим, і саме валідація допомагає вирішити цю проблему.
Запуск CDK синтезу або розгортання з цим прикладом призводить до такої помилки:
RuntimeError: Error: Validation failed with the following errors:
[KodlotS3Stack/KodlotBucket1] Bucket must be encrypted with a custom KMS key
Кілька валідацій
Може бути кілька валідаторів, які перевіряють різні аспекти наших конфігурацій, і вони можуть бути повторно використані для різних конструкцій, якщо ми знаходимо спільні шаблони. У цьому прикладі додано перевірку валідації, чи не було випадково налаштовано відро Amazon S3 для статичного хостингу вебсайтів, що в цьому випадку є помилкою.
@jsii.implements(IValidation)
class KodlotS3NotWebsiteValidator:
"""Перевірка, чи не налаштоване відро S3 для статичного хостингу вебсайтів."""
def __init__(self, s3_bucket: s3.Bucket):
self.s3_bucket = s3_bucket
def validate(self) -> List[str]:
error_messages: List[str] = []
if self.s3_bucket.is_website:
error_messages.append(f"Відро не повинно використовуватись для статичного хостингу вебсайтів")
return error_messages
Оновлений приклад конструкції AWS CDK
Щоб використати додатковий валідатор, який перевіряє, чи не налаштовано хостинг вебсайтів для відра Amazon S3, приклад конструкції CDK оновлюється, як показано нижче. Цього разу збережена оригінальна помилка — не переданий власний AWS KMS ключ. І тепер додатково є неправильна конфігурація передачі websiteindexdocument до конструкції Amazon S3 Bucket, що вказує на використання для статичного хостингу вебсайтів.
class KodlotS3Bucket(Construct):
"""Відро S3 з валідаціями."""
def __init__(self, scope: Construct, construct_id: str, bucket_name: str) -> None:
super().__init__(scope, construct_id)
s3_kms_key = kms.Key(self, f"KodlotS3KmsKey{bucket_name.title()}")
self.s3_bucket = s3.Bucket(
self,
f"KodlotS3{bucket_name.title()}",
bucket_name=bucket_name,
encryption_key=None,
website_index_document="index.html",
)
self.node.add_validation(KodlotS3KmsValidator(self.s3_bucket))
self.node.add_validation(KodlotS3NotWebsiteValidator(self.s3_bucket))
Цього разу з’являються дві різні проблеми з нашим відром Amazon S3, і, як ми бачимо нижче, обидві повідомляються механізмом валідації. Запуск CDK синтезу або розгортання з цим прикладом призводить до таких помилок:
RuntimeError: Error: Validation failed with the following errors:
[KodlotS3Stack/KodlotBucket1] Bucket must be encrypted with a custom KMS key
[KodlotS3Stack/KodlotBucket1] Bucket must not be used for static website hosting
Це дуже потужний інструмент, оскільки ми можемо збирати різні конфігураційні проблеми по всій нашій хмарній інфраструктурі та вирішувати їх усі разом, не потрібно перезапускати і виправляти їх одну за одною.
Валідація стека AWS CDK
Варто пам’ятати, що валідації не обмежуються лише конструкціями AWS CDK, їх також можна додавати на рівні стека AWS CDK. Тут, наприклад, можна перевірити, чи не містить певний стек небажані ресурси. Якщо є вимога, що наш стек не повинен містити жодних ресурсів AWS Lambda, то ми можемо змоделювати таку вимогу, використовуючи валідацію, представлену нижче.
Використовуючи дочірні елементи конструкції node, можна перевірити, чи є який-небудь ресурс екземпляром AWS CDK Function за допомогою вбудованої функції Python isinstance.
@jsii.implements(IValidation)
class KodlotNoLambdaInStackValidator:
"""Перевірка, що в заданому стеці НЕ визначено жодної функції Lambda."""
def __init__(self, stack: cdk.Stack):
self.stack = stack
def validate(self) -> List[str]:
error_messages: List[str] = []
for construct in self.stack.node.children:
if isinstance(construct, _lambda.Function):
error_messages.append(f"Стек не повинен містити функції Lambda")
return error_messages
Приклад стека AWS CDK
Для додавання валідації для стека ми використовуємо той самий метод addvalidation_, що й для конструкцій. Оскільки KodlotS3Stack був визначений як стек, який не повинен містити жодних функцій AWS Lambda, це чудове місце для тестування валідації стека. Якщо під час розробки буде допущена помилка, як це показано нижче, де розробник визначає ресурс AWS Lambda, валідація буде застосована.
class KodlotS3Stack(cdk.Stack):
"""Стек, що містить відра S3."""
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
KodlotS3Bucket(self, "KodlotBucket1", bucket_name="kodlot1")
inline_code = """
def handler(event, context):
return 200
"""
_lambda.Function(
self,
id="MyLambda",
runtime=_lambda.Runtime.PYTHON_3_13,
handler="index.handler",
code=_lambda.Code.from_inline(inline_code),
)
self.node.add_validation(KodlotNoLambdaInStackValidator(self))
Запуск CDK синтезу або розгортання з цим прикладом призводить до такої помилки:
RuntimeError: Error: Validation failed with the following errors:
[KodlotS3Stack] Stack must not contain any Lambda functions
Вбудовані валідації
Також варто перевірити, чи вже існують в AWS CDK перевірки для деяких аспектів нашої хмарної інфраструктури. У контексті Amazon S3, як виявляється, якщо ми налаштуємо ім'я відра k1, що призведе до невірної довжини імені, буде наступна вбудована помилка:
RuntimeError: Invalid S3 bucket name (value: k1)
Bucket name must be at least 3 and no more than 63 characters
Аналогічно, якщо ми налаштуємо ім'я відра k1_, що призведе до невірного символу підкреслення, буде наступна вбудована помилка:
RuntimeError: Invalid S3 bucket name (value: k_1)
Bucket name must only contain lowercase characters and the symbols, period (.) and dash (-) (offset: 3)
Висновки
Валідація AWS CDK є корисним механізмом для розробників, який можна використовувати разом з модульними та інтеграційними тестами для забезпечення загальної якості хмарної інфраструктури. Маючи можливість захоплювати загальні помилки конфігурації та визначати стандарти, ми отримуємо повторно використовувані валідації, які можна поширювати по різних компонентах. Валідації можуть бути додані на різних рівнях визначень AWS CDK, як для конструкцій AWS CDK, так і для стеків AWS CDK. Приємно бачити, що AWS CDK вже захоплює деякі загальні валідації, оскільки вони є основою для різних хмарних послуг і ресурсів і повинні завжди перевірятися, що знижує ймовірність виникнення помилок під час розгортання в продакшн.
Якщо у вас є питання, ви можете знайти мене на LinkedIn.
Перекладено з: AWS CDK Validation in Python