Dynamic Block
Dynamic Block
Dynamic blocks are used to define multiple instances of the same block type within a single resource. They are used to simplify the configuration of resources that can have multiple instances of the same block type.
The syntax of a dynamic block is as follows:
1#---------------------------------------------------2# AWS codepipeline3#---------------------------------------------------4
5resource "aws_codepipeline" "this" {141 collapsed lines
6 count = var.codepipeline_enable ? 1 : 07
8 name = var.codepipeline_name9 role_arn = var.codepipeline_role_arn10 pipeline_type = var.codepipeline_pipeline_type11 execution_mode = var.codepipeline_execution_mode12
13 dynamic "artifact_store" {14 iterator = artifact_store15 for_each = can(length(var.codepipeline_artifact_store)) ? var.codepipeline_artifact_store : []16
17 content {18 type = lookup(artifact_store.value, "type", null)19 location = lookup(artifact_store.value, "location", null)20 region = lookup(artifact_store.value, "region", null)21
22 dynamic "encryption_key" {23 iterator = encryption_key24 for_each = can(length(lookup(artifact_store.value, "encryption_key", []))) ? [lookup(artifact_store.value, "encryption_key", [])] : []25
26 content {27 id = lookup(encryption_key.value, "id", null)28 type = lookup(encryption_key.value, "type", null)29 }30 }31 }32 }33
34 dynamic "stage" {35 iterator = stage36 for_each = can(length(var.codepipeline_stage)) ? var.codepipeline_stage : []37
38 content {39 name = lookup(stage.value, "name", null)40
41 dynamic "action" {42 iterator = action43 for_each = can(length(lookup(stage.value, "action", []))) ? lookup(stage.value, "action", []) : []44
45 content {46 name = lookup(action.value, "name", null)47 category = lookup(action.value, "category", null)48 owner = lookup(action.value, "owner", null)49 provider = lookup(action.value, "provider", null)50 version = lookup(action.value, "version", null)51 configuration = lookup(action.value, "configuration", null)52 input_artifacts = lookup(action.value, "input_artifacts", null)53 output_artifacts = lookup(action.value, "output_artifacts", null)54 role_arn = lookup(action.value, "role_arn", null)55 run_order = lookup(action.value, "run_order", null)56 region = lookup(action.value, "region", null)57 namespace = lookup(action.value, "namespace", null)58 }59 }60 }61 }62
63 dynamic "trigger" {64 iterator = trigger65 for_each = can(length(var.codepipeline_trigger)) ? var.codepipeline_trigger : []66
67 content {68 provider_type = lookup(trigger.value, "provider_type", null)69
70 dynamic "git_configuration" {71 iterator = git_configuration72 for_each = can(length(lookup(trigger.value, "git_configuration", []))) ? [lookup(trigger.value, "git_configuration", [])] : []73
74 content {75 source_action_name = lookup(git_configuration.value, "source_action_name", null)76
77 dynamic "pull_request" {78 iterator = pull_request79 for_each = can(length(lookup(git_configuration.value, "pull_request", []))) ? [lookup(git_configuration.value, "pull_request", [])] : []80
81 content {82 events = lookup(pull_request.value, "events", null)83
84 dynamic "branches" {85 iterator = branches86 for_each = can(length(lookup(pull_request.value, "branches", []))) ? [lookup(pull_request.value, "branches", [])] : []87
88 content {89 includes = lookup(branches.value, "includes", null)90 excludes = lookup(branches.value, "excludes", null)91 }92 }93
94 dynamic "file_paths" {95 iterator = file_paths96 for_each = can(length(lookup(pull_request.value, "file_paths", []))) ? [lookup(pull_request.value, "file_paths", [])] : []97
98 content {99 includes = lookup(file_paths.value, "includes", null)100 excludes = lookup(file_paths.value, "excludes", null)101 }102 }103 }104 }105
106 dynamic "push" {107 iterator = push108 for_each = can(length(lookup(git_configuration.value, "push", []))) ? [lookup(git_configuration.value, "push", [])] : []109
110 content {111 dynamic "branches" {112 iterator = branches113 for_each = can(length(lookup(push.value, "branches", []))) ? [lookup(push.value, "branches", [])] : []114
115 content {116 includes = lookup(branches.value, "includes", null)117 excludes = lookup(branches.value, "excludes", null)118 }119 }120
121 dynamic "file_paths" {122 iterator = file_paths123 for_each = can(length(lookup(push.value, "file_paths", []))) ? [lookup(push.value, "file_paths", [])] : []124
125 content {126 includes = lookup(file_paths.value, "includes", null)127 excludes = lookup(file_paths.value, "excludes", null)128 }129 }130
131 dynamic "tags" {132 iterator = tags133 for_each = can(length(lookup(push.value, "tags", []))) ? lookup(push.value, "tags", []) : []134
135 content {136 includes = lookup(tags.value, "includes", null)137 excludes = lookup(tags.value, "excludes", null)138 }139 }140 }141 }142 }143 }144 }145 }146
147 dynamic "variable" {148 iterator = variable149 for_each = can(length(var.codepipeline_variable)) ? var.codepipeline_variable : []150
151 content {152 name = lookup(variable.value, "name", null)153 default_value = lookup(variable.value, "default_value", null)154 description = lookup(variable.value, "description", null)155 }156 }157
11 collapsed lines
158 tags = merge(159 local.codepipeline_stack_tags,160 {161 Name = var.codepipeline_name162 }163 )164
165 lifecycle {166 create_before_destroy = true167 ignore_changes = []168 }169}Explanation:
- The
dynamicblock is used to create multiple instances of thevariableblock within theaws_codepipelineresource. - The
iteratorargument is used to reference the current instance of the block. - The
for_eachargument is used to iterate over the list of variables defined in thevar.codepipeline_variablevariable. - The
contentblock is used to define the attributes of thevariableblock. - The
can()function is used to check if thevar.codepipeline_variablevariable is defined and not null. - The
lookup()function is used to access the value of the attribute in thevariableblock.
The dynamic block is used to create multiple instances of the variable block within the aws_codepipeline resource. The iterator argument is used to reference the current instance of the block, and the for_each argument is used to iterate over the list of variables defined in the var.codepipeline_variable variable.
The syntax of a nested dynamic block is as follows:
Nested Dynamic Block
1#---------------------------------------------------2# AWS codepipeline3#---------------------------------------------------4
5resource "aws_codepipeline" "this" {6 ...7 dynamic "stage" {8 iterator = stage9 for_each = can(length(var.codepipeline_stage)) ? var.codepipeline_stage : []10
11 content {12 name = lookup(stage.value, "name", null)13
14 dynamic "action" {15 iterator = action16 for_each = can(length(lookup(stage.value, "action", []))) ? lookup(stage.value, "action", []) : []17
18 content {19 name = lookup(action.value, "name", null)20 category = lookup(action.value, "category", null)21 owner = lookup(action.value, "owner", null)22 provider = lookup(action.value, "provider", null)23 version = lookup(action.value, "version", null)24 configuration = lookup(action.value, "configuration", null)25 input_artifacts = lookup(action.value, "input_artifacts", null)26 output_artifacts = lookup(action.value, "output_artifacts", null)27 role_arn = lookup(action.value, "role_arn", null)28 run_order = lookup(action.value, "run_order", null)29 region = lookup(action.value, "region", null)30 namespace = lookup(action.value, "namespace", null)31 }32 }33 }34 }35
36 ...37}Explanation:
-
AWS CodePipeline Resource:
- The
aws_codepipelineresource block defines the configuration for an AWS CodePipeline. It allows you to create and manage CI/CD pipelines in AWS.
- The
-
Dynamic Stage Block:
- The
dynamicblock is used to dynamically generate multiple instances of thestageblock within theaws_codepipelineresource. This is useful for pipelines with multiple stages, each having its own configuration. iterator(stage): References the current instance of thestageblock being created.for_each: Iterates over the list of stages defined in thevar.codepipeline_stagevariable. If the list is empty or null, the block is skipped.content: Defines the attributes of thestageblock.
- The
-
Stage Attributes:
name: The name of the stage, retrieved using thelookup()function from thestageblock. If not found, it returnsnull.
-
Nested Dynamic Action Block:
- A nested
dynamicblock within thestageblock is used to create multiple instances of theactionblock within eachstage. iterator(action): References the current instance of theactionblock being created.for_each: Iterates over the list of actions defined in theactionattribute of thestageblock. If the list is empty or null, the block is skipped.content: Defines the attributes of theactionblock.
- A nested
-
Action Attributes:
name: The name of the action, retrieved using thelookup()function from theactionblock. If not found, it returnsnull.category: The category of the action (e.g.,Source,Build,Deploy).owner: The owner of the action (e.g.,AWS).provider: The service provider for the action (e.g.,CodeBuild).version: The version of the action.configuration: A map of configuration settings for the action.input_artifacts: A list of input artifacts for the action.output_artifacts: A list of output artifacts for the action.role_arn: The ARN of the IAM role assumed by the action.run_order: The order in which the action runs within the stage.region: The AWS region where the action is executed.namespace: The namespace for variables generated by the action.
-
Helper Functions:
lookup(): Retrieves the value of the specified attribute from the block. If the attribute is not found, it returns a default value (e.g.,null).can(): Checks if thelookup()function returns a non-null value, ensuring that thefor_eachiteration only occurs if there are valid values.length(): Returns the length of the list being iterated over, used in conjunction withcan()to validate non-empty lists.
By using the dynamic block, the configuration becomes more flexible and scalable, allowing for easy management of complex pipelines with multiple stages and actions. This approach leverages Terraform’s powerful interpolation and iteration features to simplify the creation of intricate infrastructure setups.
Single Object Dynamic Block
In some cases, you may need to use a dynamic block where the block is not an array of objects but a single object, and it has a dynamic block inside it, or both the dynamic block and the block itself are single objects. In this scenario, you can use the for_each argument with a single object to create a single instance of the block.
1#---------------------------------------------------2# AWS CodePipeline Configuration3#---------------------------------------------------4
5resource "aws_codepipeline" "this" {6 # Definition of the AWS CodePipeline resource7
8 dynamic "artifact_store" {9 iterator = artifact_store10 for_each = can(length(var.codepipeline_artifact_store)) ? var.codepipeline_artifact_store : []11
12 content {13 type = lookup(artifact_store.value, "type", null)14 location = lookup(artifact_store.value, "location", null)15 region = lookup(artifact_store.value, "region", null)16
17 dynamic "encryption_key" {18 iterator = encryption_key19 for_each = can(length(keys(lookup(artifact_store.value, "encryption_key", {})))) ? [lookup(artifact_store.value, "encryption_key", {})] : []20
21 content {22 id = lookup(encryption_key.value, "id", null)23 type = lookup(encryption_key.value, "type", null)24 }25 }26 }27 }28 ...29}Explanation:
-
AWS CodePipeline Resource:
- The
aws_codepipelineresource block defines the configuration for an AWS CodePipeline. It allows you to create and manage CI/CD pipelines in AWS.
- The
-
Dynamic Artifact Store Block:
- The
dynamicblock is used to dynamically generate multiple instances of theartifact_storeblock within theaws_codepipelineresource. This is useful for pipelines with multiple artifact stores, each having its own configuration. iterator(artifact_store): References the current instance of theartifact_storeblock being created.for_each: Iterates over the list of artifact stores defined in thevar.codepipeline_artifact_storevariable. If the list is empty or null, the block is skipped.content: Defines the attributes of theartifact_storeblock.
- The
-
Artifact Store Attributes:
type: The type of the artifact store (e.g.,S3), retrieved using thelookup()function from theartifact_storeblock. If not found, it returnsnull.location: The location of the artifact store (e.g., S3 bucket name).region: The AWS region where the artifact store is located.
-
Nested Dynamic Encryption Key Block:
- A nested
dynamicblock within theartifact_storeblock is used to create an instance of theencryption_keyblock if an encryption key is specified. iterator(encryption_key): References the current instance of theencryption_keyblock being created.for_each: Iterates over a single-item list containing theencryption_keyobject if it exists. If the object is empty or null, the block is skipped.content: Defines the attributes of theencryption_keyblock.
- A nested
-
Encryption Key Attributes:
id: The ID of the encryption key, retrieved using thelookup()function from theencryption_keyblock. If not found, it returnsnull.type: The type of the encryption key (e.g.,KMS).
- Helper Functions:
lookup():- Retrieves the value of the specified attribute from the block.
- If the attribute is not found, it returns a default value (e.g.,
null).
can():- Checks if the
lookup()function returns a non-null value. - Ensures that the
for_eachiteration only occurs if there are valid values. - Example:
can(length(var.codepipeline_stage))ensures thefor_eachloop only runs if the list is not empty.
- Checks if the
length():- Returns the length of the list being iterated over.
- Used in conjunction with
can()to validate non-empty lists. - Example:
length(var.codepipeline_stage)returns the number of stages in the pipeline.
keys():- Returns a list of keys from a map.
- Useful for checking the existence of keys in a nested object.
- Example:
keys(lookup(artifact_store.value, "encryption_key", {}))checks if theencryption_keymap has any keys.
- Usage of Helper Functions:
can()andlength():- Ensure that dynamic blocks are only created if the corresponding lists are non-empty.
- Prevents unnecessary block creation and potential errors in the configuration.
lookup():- Provides a safe way to access attributes within dynamic blocks.
- Allows setting default values if the attribute does not exist.
keys():- Validates the existence of keys within nested objects.
- Ensures that the
for_eachloop only runs if the nested object is not empty.
By using these helper functions, the configuration becomes more robust and flexible, allowing for dynamic generation of resources based on variable inputs. This approach simplifies the management of complex infrastructure setups and enhances the scalability of the configuration.