Skip to content

Commit

Permalink
feat: add multi-org generate_params.py (#672)
Browse files Browse the repository at this point in the history
## Why?

When running ADF in a multi-org setup, this feature allows you to set stage-specific files in the repositories' `params` folder. This feature doesn't break existing parameter generation. It just adds a new feature.

## Example

Let's assume that we have a three AWS Org setup with a dev, int and prod AWS Org. 
That implies that the SSM param "/adf/org/stage" will have one of the following values: [dev, int, prod]. For now, let's assume the value is set to "dev".
Let's further assume that, the `params` folder of our target repository has the following structure:

- params:
   - global_dev.yml
   - global_int.yml
   - global_prod.yml
   - global.yml

With this feature, the param file global_dev.yml will be selected based on the value "dev" in SSM param "/adf/org/stage".

---------

Co-authored-by: Andreas Falkenberg
Co-authored-by: Simon Kok
  • Loading branch information
AndyEfaa authored Feb 5, 2024
1 parent fac17ba commit ef662ec
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
36 changes: 31 additions & 5 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,12 @@ the corresponding OU parameter file will not be referenced.

```txt
global.yml
└───deployment_account_region.yml (e.g. global_eu-west-1.yml)
└───ou.yml (e.g. ou-1a2b-3c4d5e.yml)
└───ou_region.yml (e.g. ou-1a2b-3c4d5e_eu-west-1.yml)
└───account.yml (e.g. dev-account-1.yml)
└───account_region.yml (e.g. dev-account-1_eu-west-1.yml)
└───deployment_org_stage.yml (e.g. global_dev.yml)
└───deployment_account_region.yml (e.g. global_eu-west-1.yml)
└───ou.yml (e.g. ou-1a2b-3c4d5e.yml)
└───ou_region.yml (e.g. ou-1a2b-3c4d5e_eu-west-1.yml)
└───account.yml (e.g. dev-account-1.yml)
└───account_region.yml (e.g. dev-account-1_eu-west-1.yml)
```

This concept also works for applying **Tags** to the resources within your
Expand Down Expand Up @@ -712,6 +713,31 @@ the root of the repository.
*Note:* Currently only Strings type values are supported as parameters to
CloudFormation templates when deploying via AWS CodePipeline.

#### CloudFormation Parameters in a Multi-Organization ADF Setup

The CloudFormation Parameter generation feature is fully compatible with
the [Multi-Organization ADF Setup](./multi-organization-guide.md) approach.

For example, in a setup with three AWS Organizations; with a separate
`dev`, an `int`, and a `prod` AWS Organization. This implies that the
SSM parameter `/adf/org/stage` will have one of the following three
values: `dev`, `int`, or `prod`; depending on the AWS organization
you are in. Let's further assume that your application in scope
requires AWS Organization specific parameters. In that case,
the `params` folder should have the following content:

```txt
params
└───global_dev.yml
└───global_int.yml
└───global_prod.yml
└───global.yml
```

Where it will prefer the AWS Organization specific configuration
`global_${org_stage}` over the `global` parameters in case they both
match the same parameter or tag.

### Serverless Transforms

If the template that is being deployed contains a transform, such as a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class PipelineDefinition(TypedDict):
DEPLOYMENT_ACCOUNT_REGION = os.environ["AWS_REGION"]
PROJECT_NAME = os.environ["ADF_PROJECT_NAME"]
EMPTY_PARAMS_DICT: ParametersAndTags = {'Parameters': {}, 'Tags': {}}
ADF_ORG_STAGE = os.getenv("ADF_ORG_STAGE", "dev")


class Parameters:
Expand Down Expand Up @@ -229,6 +230,7 @@ def create_parameter_files(self) -> None:
i.e. "/devsecops/security_eu-west-1"
1. f"{organization_unit_path}" i.e. "/devsecops/security"
1. f"{global}_{region}" i.e. "global_eu-west-1"
1. f"{global}_{stage}" i.e. "global_dev"
1. f"{global}" i.e. "global"
It will then generate a JSON file that holds all the parameters per
Expand Down Expand Up @@ -299,6 +301,14 @@ def create_parameter_files(self) -> None:
),
current_params
)
# Compare account_region final to global_stage
current_params = self._merge_params(
Parameters._parse(
params_root_path=self.cwd,
params_filename=f"global_{ADF_ORG_STAGE}",
),
current_params,
)
# Compare account_region final to global
current_params = self._merge_params(
Parameters._parse(
Expand Down

0 comments on commit ef662ec

Please sign in to comment.