cloud-foundation-fabric/modules/__docs/20231106-factories.md

103 lines
5.8 KiB
Markdown
Raw Normal View History

# Factories Refactor and Plan Forward
**authors:** [Ludo](https://github.com/ludoo)
**last modified:** February 16, 2024
## Status
Under discussion.
## Context
Factories evolved progressively in Fabric, from the original firewall factory module, to a semi-standardized approach to management of repeated resources. This progression happened piecemeal and it's now time to define a clear strategy for factories in both Fabric and FAST, so that we can remove guesswork from new developments and provide a predictive approach to users.
The remainder of this section provides a summary of the current status.
### Modules
Several modules implement factories for repeated resources which are typically dependent from the main resource managed in the module:
- `billing-account` provides a factory for billing alert rules tied to the billing account
- `dns-response-policy` provides a factory for rules in within the policy
- `net-firewall-policy` provides a factory for rules within the policy
- `net-vpc` provides a factory for subnets in the VPC
- `net-vpc-firewall` provides a factory for VPC firewall rules
- `organization` and `folder` provide a factory for hierarchical firewall rules within their policy
- `organization`, `folder` and `project` provide a factory for organization policies
The common pattern for modules is management of *multiple resources* typically dependent from the single *main resource* managed by the module.
### Blueprints
The `factories` folder in blueprints contains a collection of factories with a fuzzier approach
- `bigquery-factory` manages tables and views for 1-n datasets by wrapping the `bigquery-dataset` module via simple locals
- `cloud-identity-group-factory` manages Cloud Identity group members for 1-n groups by wrapping the `cloud-identity-group` via simple locals
- `net-vpc-firewall-yaml` is the original factory module managing VPC firewall rules, superseded by the factory in the `net-vpc-firewall` module
- `project-factory` combines the project, service account, and (planned) billing account and VPC modules to implement end-to-end project creation and configuration
There's no clear common pattern for these factories, where some could be moved to the respective module and the project factory combines a collection of modules to implement a process.
### FAST
FAST currently leverages module-level factories (organization policies, subnets, firewalls, etc.), and also provides the project factory as a dedicated level 3 stage by wrapping the relevant blueprint and localizing a few variables for the environment (`prefix`, `labels`).
## Proposal
While the current approach is reasonably clear in regards to modules, it has never been formalized in a set of guidelines that can help authors define when and how new factories would made sense.
On top of this, the `factories` blueprints folder contains code that that should really be moved to module-level factories, and the project factory which could/should be published directly as a FAST stage, since those are consumable as standalone modules.
This proposal aims at addressing the above problems.
### Module-level factory approach
The current approach for module-level factories can be summarized in a single principle:
> factories implemented in modules manage multiple resources which depend from one single main resource (or a small set of main resources) which are the main driver of the module.
For example, the module managing a firewall policy exposes a factory for its rules, or the module managing a VPC exposes a factory for its subnets. But the project module would not expose a projects factory, as one project maps to a single module invocation.
The proposal on factory modules then is to:
- align all factory variables to the same standard, outlined below
- move the groups and bigquery factories from blueprints to the respective modules
- eventually add more factories when it makes sense to do so (e.g. for KMS keys, service accounts, etc.)
The variable interface for module-level factories should use a single top-level `factory_configs` variable, whose type is an object with one or more attributes which are named according to the specific factory. This will allow composing multiple factory configurations into a single variable in FAST stages, by avoiding name overlaps. An example:
```hcl
variable "factory_configs" {
description = "Path to folder containing budget alerts data files."
type = object({
budgets_data_path = optional(string, "data/billing-budgets")
})
nullable = false
default = {}
}
```
### Blueprint factories
The `factories` folder in blueprints will be emptied, and a single README left in it pointing to all the module-level and FAST stage factories available.
As outlined above, the existing factories will be moved to modules (bigquery and groups), FAST (project factory), or deleted (firewall rules).
### FAST factories
The only change for FAST factories will be moving the project factory from blueprints to the stage folder, and updating the path used for the environment-level wrapping stage.
### File schema and filesystem organization
Factory files schema must mimick and implement the variable interface for the module, including optionals and validation - which are implemented in code and checks.
With notable exceptions (currently only the `cidrs.yaml` file consumed by firewall factories), the following convention for files/directory is proposed:
- Factories should consume directories (vs single files)
- All files should contain a dictionary of resources or a single resource
- If the factory accepts one resource per file (e.g. VPC subnets), the file name should be used for the resource name and the YAML should allow defining a `name:` override
- Files in a directory should be parsed together and flattened into a single dictionary
This allows developers to implement multiple resources in a single file or to use one file per resource, as they see fit.