Я нашел способ автоматически применить CfnCondition к каждому ресурсу в стеке, используя Construct # onPrepare в Stack
На приведенной выше странице Construct#onPrepare()
:
Выполнение окончательных модификаций перед синтезом
Этот метод может быть реализован производными конструкциями для выполнения окончательных изменений перед синтезом. prepare () будет вызываться после подготовки дочерних конструкций.
Это расширенная функция фреймворка. Используйте это только в том случае, если вы понимаете последствия.
Следующий код CDK (пример кода - я только вставляю соответствующие биты здесь) находится в Kotlin, но будет применяться к любой поддерживаемый язык CDK:
class MyStack internal constructor(app: App, name: String) : Stack(app, name) {
private lateinit var myCondition: CfnCondition
init {
myCondition = CfnCondition.Builder.create(this, "myCondition")
.expression(Fn.condition...) // Fill in your condition
.build()
}
/**
* Use the `Stack#onPrepare` hook to find all CF resources and apply our stack standard CF condition on them.
* See:
* * [Stack.onPrepare]: https://docs.aws.amazon.com/cdk/api/latest/typescript/api/core/construct.html#core_Construct_onPrepare
*/
override fun onPrepare() {
super.onPrepare()
findAllCfnResources(this.node).forEach { it.cfnOptions.condition = this.myCondition }
}
/**
* Recurse through all children nodes and accumulate [CfnResource] nodes.
*/
private fun findAllCfnResources(node: ConstructNode): List<CfnResource> {
val nodes = node.children.map { it.node } + node
val cfnResources: List<CfnResource> = nodes.flatMap { it.findAll() }.mapNotNull { it as? CfnResource }
if (node.children.isEmpty()) {
return cfnResources
}
return node.children.fold(cfnResources) {
accumulatedCfnResources, it -> accumulatedCfnResources + findAllCfnResources(it.node)
}
}
}
Юнит-тест (Junit и AssertJ, также в Kotlin), который я добавил, проверяет, что он охватывает все ресурсы:
private val mapper = ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
private lateinit var stack: Stack
private lateinit var synthesizedStackCfTemplate: JsonNode
@BeforeEach
fun setUp() {
val app = App()
stack = MyStack(app, "MyUnitTestStack")
synthesizedStackCfTemplate = mapper.valueToTree(app.synth().getStackArtifact(stack.artifactId).template)
}
@Test
fun `All CfnResources have the expected CF Condition`() {
val expectedCondition = "myCondition"
val softly = SoftAssertions()
synthesizedStackCfTemplate.get("Resources").forEach { resource ->
softly.assertThat(resource.get("Condition")?.asText())
.describedAs("Resource is missing expected CF condition [$expectedCondition]: $resource")
.isEqualTo(expectedCondition)
}
softly.assertAll()
}