103 lines
5.8 KiB
Markdown
103 lines
5.8 KiB
Markdown
|
# 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.
|
||
|
|