diff --git a/docs/admin-guide.md b/docs/admin-guide.md index 5cb9acfa0..4f811fa94 100644 --- a/docs/admin-guide.md +++ b/docs/admin-guide.md @@ -206,7 +206,7 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, repository it can be found at `${bootstrap_repository}/adf-build/shared/repo_templates/codecommit.yml`. - - **default-scm-branch** allows you to configure the default branch that + - `default-scm-branch` allows you to configure the default branch that should be used with all source-code management platforms that ADF supports. For any new installation of the AWS Deployment Framework, this will default to `main`, as this is the default branch used by CodeCommit. @@ -217,11 +217,13 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, `main`. As new repositories will most likely use this branch name as their default branch. - `deployment-maps` tracks all source code management configuration. - - **allow-empty-target** allows you to configure deployment maps with empty - targets. + - `allow-empty-target`, when set to `enabled` this allows you to configure + deployment maps with empty targets. + If all targets get evaluated to empty, the ADF pipeline is still created based on the remaining providers (e.g. source and build). It just does not have a deploy stage. + This is useful when you need to: - target an OU that does not have any AWS Accounts (initially or temporarily). @@ -242,7 +244,7 @@ Config has five components in `main-notification-endpoint`, `scp`, `scm`, More information about setting up ADF with multiple AWS Organizations can be found in the [Multi-Organization Guide](multi-organization-guide.md) - - **default-scm-codecommit-account-id** allows you to configure the default + - `default-scm-codecommit-account-id` allows you to configure the default account id that should be used with all source-code management platforms that ADF supports. If not set here, the deployment account id is taken as default value. diff --git a/docs/multi-organization-guide.md b/docs/multi-organization-guide.md index 70a8e6880..7356efbaf 100644 --- a/docs/multi-organization-guide.md +++ b/docs/multi-organization-guide.md @@ -251,9 +251,9 @@ a multi-organization ADF setup: - With the adfconfig setting `allow-empty-target` ([ADF Admin Guide](admin-guide.md)), ADF can be instructed to ignore any target that is not resolvable or empty (because no AWS Accounts exists in it). It is suggested to set this setting - to `True`. Even though the OU structure and general setup across the different + to `enabled`. Even though the OU structure and general setup across the different AWS Organization stages is usually identical, the number of created - AWS Accounts might not be. When this setting is set to `True`, temporary + AWS Accounts might not be. When this setting is set to `enabled`, temporary empty OUs are just ignored and do not lead to an error. 4. The source branch for the application code may be different per AWS Organization - The above described custom `adfconfig` configuration allows a different diff --git a/src/lambda_codebase/initial_commit/adfconfig.yml.j2 b/src/lambda_codebase/initial_commit/adfconfig.yml.j2 index 4f7d8b15a..8eef343ad 100644 --- a/src/lambda_codebase/initial_commit/adfconfig.yml.j2 +++ b/src/lambda_codebase/initial_commit/adfconfig.yml.j2 @@ -12,6 +12,7 @@ regions: {%- for Region in TargetRegions %} - {{ Region }} {%- endfor %} + config: main-notification-endpoint: - type: {{ NotificationEndpointType }} # slack or email @@ -33,8 +34,11 @@ config: # Optional: # default-scm-codecommit-account-id: "123456789012" deployment-maps: - allow-empty-target: "False" - # ^ Needs to be "True" or "False". Defaults to "False" when not set. - #org: - # Optional: Use this variable to define the AWS Organization in case of staged multi-organization ADF deployments - #stage: dev + allow-empty-target: disabled + # ^ Needs to be set to "enabled" to activate. Defaults to "disabled" when + # not set. +# Optional config for multi-organization deployments of ADF: +# org: +# # Optional: Use this variable to define the AWS Organization in case of +# # staged multi-organization ADF deployments +# stage: dev diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py index 66859803e..06e78b928 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/main.py @@ -56,7 +56,7 @@ "ACCOUNT_BOOTSTRAPPING_STATE_MACHINE_ARN" ) ADF_DEFAULT_SCM_FALLBACK_BRANCH = 'main' -ADF_DEFAULT_DEPLOYMENT_MAPS_ALLOW_EMPTY_TARGET = False +ADF_DEFAULT_DEPLOYMENT_MAPS_ALLOW_EMPTY_TARGET = 'disabled' ADF_DEFAULT_ORG_STAGE = "none" LOGGER = configure_logger(__name__) @@ -189,7 +189,7 @@ def prepare_deployment_account(sts, deployment_account_id, config): 'deployment_maps/allow_empty_target', config.config.get('deployment-maps', {}).get( 'allow-empty-target', - str(ADF_DEFAULT_DEPLOYMENT_MAPS_ALLOW_EMPTY_TARGET), + ADF_DEFAULT_DEPLOYMENT_MAPS_ALLOW_EMPTY_TARGET, ) ) deployment_account_parameter_store.put_parameter( diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/target.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/target.py index 7994bbf75..ef6c2270f 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/target.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/target.py @@ -150,10 +150,11 @@ def __init__( self.organizations = organizations # Set adf_deployment_maps_allow_empty_target as bool parameter_store = ParameterStore(DEPLOYMENT_ACCOUNT_REGION, boto3) - adf_deployment_maps_allow_empty_target_bool = parameter_store.fetch_parameter( - "deployment_maps/allow_empty_target" - ).lower().capitalize() == "True" - self.adf_deployment_maps_allow_empty_target = adf_deployment_maps_allow_empty_target_bool + self.adf_deployment_maps_allow_empty_target = ( + parameter_store.fetch_parameter( + "deployment_maps/allow_empty_target" + ).lower() == "enabled" + ) @staticmethod @@ -192,7 +193,7 @@ def _create_response_object(self, responses): ) if accounts_found == 0: - if self.adf_deployment_maps_allow_empty_target is False: + if not self.adf_deployment_maps_allow_empty_target: raise NoAccountsFoundError(f"No accounts found in {self.path}.") LOGGER.info( "Create_response_object: 0 AWS accounts found for path %s. " @@ -209,7 +210,7 @@ def _target_is_account_id(self): except ClientError as client_err: if ( client_err.response["Error"]["Code"] == "AccountNotFoundException" and - self.adf_deployment_maps_allow_empty_target is True + self.adf_deployment_maps_allow_empty_target ): LOGGER.info("IGNORE - Account was not found in AWS Org for id %s", self.path) responses_list = [] @@ -244,7 +245,7 @@ def _target_is_ou_id(self): no_target_found = ( client_err.response["Error"]["Code"] == "ParentNotFoundException" ) - if no_target_found and self.adf_deployment_maps_allow_empty_target is True: + if no_target_found and self.adf_deployment_maps_allow_empty_target: LOGGER.info( "Note: Target OU was not found in the AWS Org for id %s", self.path, @@ -266,7 +267,7 @@ def _target_is_ou_path(self, resolve_children=False): no_target_found = ( client_err.response["Error"]["Code"] == "ParentNotFoundException" ) - if no_target_found and self.adf_deployment_maps_allow_empty_target is True: + if no_target_found and self.adf_deployment_maps_allow_empty_target: LOGGER.info( "Note: Target OU was not found in AWS Org for path %s", self.path, @@ -320,7 +321,7 @@ def fetch_accounts_for_target(self): ) return - if self.adf_deployment_maps_allow_empty_target is True: + if self.adf_deployment_maps_allow_empty_target: return if self.path is None: diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/tests/test_target.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/tests/test_target.py index 89bee9ccb..741447e75 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/tests/test_target.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/tests/test_target.py @@ -53,7 +53,7 @@ def test_fetch_accounts_for_target_ou_path(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] cls = Target( @@ -77,7 +77,7 @@ def test_fetch_accounts_for_target_account_id(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] cls = Target( @@ -100,7 +100,7 @@ def test_fetch_accounts_for_target_ou_id(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] cls = Target( @@ -123,7 +123,7 @@ def test_fetch_accounts_for_approval(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] cls = Target( @@ -146,7 +146,7 @@ def test_fetch_account_error(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] cls = Target( @@ -168,7 +168,7 @@ def test_fetch_account_error_invalid_account_id(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] cls = Target( @@ -190,7 +190,7 @@ def test_target_structure_respects_wave(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] test_target_config = {"path": "/some/random/ou", "wave": {"size": 2}} @@ -288,7 +288,7 @@ def test_target_structure_respects_multi_region(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] test_target_config = {"path": "/some/random/ou", "wave": {"size": 20}} @@ -335,7 +335,7 @@ def test_target_structure_respects_multi_action_single_region(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] test_target_config = {"path": "/some/random/ou"} @@ -379,7 +379,7 @@ def test_target_structure_respects_multi_action_multi_region(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] test_target_config = {"path": "/some/random/ou"} @@ -423,7 +423,7 @@ def test_target_structure_respects_change_set_approval_single_region(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] test_target_config = {"path": "/some/random/ou"} @@ -468,7 +468,7 @@ def test_target_wave_structure_respects_exclude_config(): expected_calls = [ call( 'deployment_maps/allow_empty_target', - 'False', + 'disabled', ), ] test_target_config = { diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/stubs/stub_adfconfig.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/stubs/stub_adfconfig.yml index 5a2da20ae..8945cbf7b 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/stubs/stub_adfconfig.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/stubs/stub_adfconfig.yml @@ -22,4 +22,4 @@ config: scp: keep-default-scp: enabled deployment-maps: - allow-empty-target: "False" + allow-empty-target: disabled diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/test_main.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/test_main.py index 839b81f3e..1e3743ade 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/test_main.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/tests/test_main.py @@ -158,7 +158,7 @@ def test_prepare_deployment_account_defaults(param_store_cls, cls, sts): 'scm/default_scm_codecommit_account_id', deployment_account_id, ), - call('deployment_maps/allow_empty_target', 'False'), + call('deployment_maps/allow_empty_target', 'disabled'), call('org/stage', 'none'), call('notification_type', 'email'), call('notification_endpoint', 'john@example.com'), @@ -203,7 +203,7 @@ def test_prepare_deployment_account_specific_config(param_store_cls, cls, sts): 'stage': 'test-stage', } cls.config['deployment-maps'] = { - 'allow-empty-target': 'False', + 'allow-empty-target': 'disabled', } prepare_deployment_account( sts=sts, @@ -260,7 +260,7 @@ def test_prepare_deployment_account_specific_config(param_store_cls, cls, sts): 'scm/default_scm_codecommit_account_id', deployment_account_id, ), - call('deployment_maps/allow_empty_target', 'False'), + call('deployment_maps/allow_empty_target', 'disabled'), call('org/stage', 'test-stage'), call('notification_type', 'slack'), call(