This stage is run for a specific tenant after [tenant bootstrap](../0-bootstrap-tenant/) has successfully created initial resources for the tenant, which is then decoupled from the organization.
It is logically equivalent and almost identical in code to the corresponding [organization resource management stage](../../stages/1-resman/), with a few notable differences:
- the hierarchy is rooted in the tenant top-level folder instead of the organization
- there's no management of tag values and keys since they organization-level resources (it could be implemented for tenant-specific tags if the need arises)
- automation service accounts for subsequent stages are configured but not created here (tenant-level bootstrap creates them and assigns organization-level permissions)
The stage runs with a dedicated service account for the tenant, which has no permissions at the organization level except for billing and organization policies, constrained by a condition on the tenant tag.
The following diagram is a high level reference of what this stage manages, showing one hypothetical tenant (additional tenants require additional instances of this stage being deployed):
```mermaid
%%{init: {'theme':'base'}}%%
classDiagram
Tenant_root~📁~ -- tn0_automation
Tenant_root~📁~ -- Networking~📁~
Tenant_root~📁~ -- Security~📁~
Tenant_root~📁~ -- Data_Platform~📁~
Data_Platform~📁~ -- DP_Dev~📁~
Data_Platform~📁~ -- DP_Prod~📁~
Tenant_root~📁~ -- GKE~📁~
GKE~📁~ -- GKE_Dev~📁~
GKE~📁~ -- GKE_Prod~📁~
Tenant_root~📁~ -- Teams~📁~
Teams~📁~ -- Team_0~📁~
Team_0~📁~ -- Team_0_Dev~📁~
Team_0~📁~ -- Team_0_Prod~📁~
Tenant_root~📁~ -- Sandbox~📁~
class Tenant_root~📁~ {
- IAM bindings()
- org policies()
}
class tn0_automation {
- GCS buckets
- IAM bindings()
}
class Data_Platform~📁~ {
- IAM bindings()
- tag bindings()
}
class DP_Dev~📁~ {
- IAM bindings()
- tag bindings()
}
class DP_Prod~📁~ {
- IAM bindings()
- tag bindings()
}
class GKE~📁~ {
- IAM bindings()
- tag bindings()
}
class GKE_Dev~📁~ {
- IAM bindings()
- tag bindings()
}
class GKE_Prod~📁~ {
- IAM bindings()
- tag bindings()
}
class Networking~📁~ {
- IAM bindings()
- tag bindings()
}
class Security~📁~ {
- IAM bindings()
- tag bindings()
}
class Sandbox~📁~ {
- IAM bindings()
- tag bindings()
}
class Teams~📁~ {
- IAM bindings()
- tag bindings()
}
class Team_0~📁~ {
- IAM bindings()
- tag bindings()
}
class Team_0_Dev~📁~ {
- IAM bindings()
- tag bindings()
}
class Team_0_Prod~📁~ {
- IAM bindings()
- tag bindings()
}
```
As most of the features of this stage follow the same design and configurations of the [organization-level resource management stage](../../stages/1-resman/), we will only focus on the tenant-specific configuration in this document.
## How to run this stage
As mentioned above this stage is decoupled from organization-level stages: it uses a service account and state bucket from the tenant-specific automation project, and its tfvars and provider files are also tenant-specific.
The `stage-links.sh` script can be used to get the commands needed for the provider and output files, just set the variable for the tenant shortname (the same one specified in the tenant bootstrap stage) and pass a single argument with your FAST output files folder path, or GCS bucket URI:
```bash
TENANT=tn0 ../../stage-links.sh ~/fast-config
```
The script output can be copy/pasted to a terminal:
```bash
# copy and paste the following commands for '1-resman-tenant'
Note that the `outputs_location` variable is disabled by default, you need to explicitly set it in your `terraform.tfvars` file if you want output files to be generated by this stage. This is a sample `terraform.tfvars` that configures it, refer to the [org-level bootstrap stage documentation](../../stages/0-bootstrap/README.md#output-files-and-cross-stage-variables) for more details:
Once the configuration is done just go through the usual `init/apply` cycle. On successful apply, a tfvars file specific for this tenant and a set of provider files will be created.
| [cicd-data-platform.tf](./cicd-data-platform.tf) | CI/CD resources for the data platform branch. | <code>iam-service-account</code> · <code>source-repository</code> | |
| [cicd-gke.tf](./cicd-gke.tf) | CI/CD resources for the data platform branch. | <code>iam-service-account</code> · <code>source-repository</code> | |
| [cicd-networking.tf](./cicd-networking.tf) | CI/CD resources for the networking branch. | <code>iam-service-account</code> · <code>source-repository</code> | |
| [cicd-project-factory.tf](./cicd-project-factory.tf) | CI/CD resources for the teams branch. | <code>iam-service-account</code> · <code>source-repository</code> | |
| [cicd-security.tf](./cicd-security.tf) | CI/CD resources for the security branch. | <code>iam-service-account</code> · <code>source-repository</code> | |
| [main.tf](./main.tf) | Module-level locals and resources. | | |
| [outputs-files.tf](./outputs-files.tf) | Output files persistence to local filesystem. | | <code>local_file</code> |
| [billing_account](variables.tf#L51) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | <codetitle="object({ id = string is_org_level = optional(bool, true) no_iam = optional(bool, false) })">object({…})</code> | ✓ | | <code>0-bootstrap</code> |
| [prefix](variables.tf#L226) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> |
| [root_node](variables.tf#L237) | Root folder node for the tenant, in folders/nnnnnn format. | <code>string</code> | ✓ | | |
| [short_name](variables.tf#L242) | Short name used to identify the tenant. | <code>string</code> | ✓ | | |
| [organization_policy_data_path](variables.tf#L214) | Path for the data folder used by the organization policies factory. | <code>string</code> | | <code>null</code> | |
| [outputs_location](variables.tf#L220) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | <code>string</code> | | <code>null</code> | |
| [team_folders](variables.tf#L265) | Team folders to be created. Format is described in a code comment. | <codetitle="map(object({ descriptive_name = string group_iam = map(list(string)) impersonation_groups = list(string) }))">map(object({…}))</code> | | <code>null</code> | |
| [test_skip_data_sources](variables.tf#L275) | Used when testing to bypass data sources. | <code>bool</code> | | <code>false</code> | |