diff --git a/.github/actions/build-website/action.yml b/.github/actions/build-website/action.yml
index c95ae1a79..f8d5a3207 100644
--- a/.github/actions/build-website/action.yml
+++ b/.github/actions/build-website/action.yml
@@ -59,6 +59,13 @@ runs:
make init
pip install -r scripts/docs-collator/requirements.txt
+ - name: "Install terraform-docs"
+ uses: jaxxstorm/action-install-gh-release@v1.12.0
+ with:
+ repo: terraform-docs/terraform-docs
+ tag: v0.18.0
+ cache: enable
+
- name: "Render Documentation for Terraform Components"
shell: bash
run: |
diff --git a/.gitignore b/.gitignore
index 619ab5c0d..12f1a3c6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,12 @@
/resources
/themes
/tmp
+/docs/generated/components/library
+/docs/generated/modules/library
+/docs/generated/github-actions/library
+/docs/components/library
+/docs/modules/library
+/docs/github-actions/library
/static/css
/static/js
diff --git a/docs/generated/components/index.mdx b/docs/components/index.mdx
similarity index 100%
rename from docs/generated/components/index.mdx
rename to docs/components/index.mdx
diff --git a/docs/generated/components/library/aws/_category_.json b/docs/generated/components/library/aws/_category_.json
deleted file mode 100644
index 6936f441c..000000000
--- a/docs/generated/components/library/aws/_category_.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "label": "aws",
- "position": 100,
- "collapsible": true,
- "collapsed": false,
- "link": {
- "type": "generated-index",
- "description": "aws"
- }
-}
diff --git a/docs/generated/components/library/aws/account/README.mdx b/docs/generated/components/library/aws/account/README.mdx
deleted file mode 100644
index 63876a9d0..000000000
--- a/docs/generated/components/library/aws/account/README.mdx
+++ /dev/null
@@ -1,498 +0,0 @@
----
-title: account
-sidebar_label: account
-sidebar_class_name: command
-custom_edit_url: https://github.com/cloudposse/terraform-aws-components/blob/master/modules/account/README.md
-tags: [terraform, aws, account]
----
-
-# Component: `account`
-
-This component is responsible for provisioning the full account hierarchy along with Organizational Units (OUs). It
-includes the ability to associate Service Control Policies (SCPs) to the Organization, each Organizational Unit and
-account.
-
-:::info Part of a
-[cold start](https://docs.cloudposse.com/reference-architecture/how-to-guides/implementation/enterprise/implement-aws-cold-start)
-so it has to be initially run with `SuperAdmin` role.
-
-:::
-
-In addition, it enables
-[AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html), which helps
-you identify the resources in your organization and accounts, such as Amazon S3 buckets or IAM roles, that are shared
-with an external entity. This lets you identify unintended access to your resources and data, which is a security risk.
-Access Analyzer identifies resources that are shared with external principals by using logic-based reasoning to analyze
-the resource-based policies in your AWS environment. For each instance of a resource that is shared outside of your
-account, Access Analyzer generates a finding. Findings include information about the access and the external principal
-that it is granted to. You can review findings to determine whether the access is intended and safe, or the access is
-unintended and a security risk.
-
-## Usage
-
-**Stack Level**: Global
-
-**IMPORTANT**: Account Name building blocks (such as tenant, stage, environment) must not contain dashes. Doing so will
-lead to unpredictable resource names as a `-` is the default delimiter. Additionally, account names must be lower case
-alpha-numeric with no special characters. For example:
-
-| Key | Value | Correctness |
-| ---------------- | --------------- | ----------- |
-| **Tenant** | foo | ✅ |
-| **Tenant** | foo-bar | ❌ |
-| **Environment** | use1 | ✅ |
-| **Environment** | us-east-1 | ❌ |
-| **Account Name** | `core-identity` | ✅ |
-
-Here is an example snippet for how to use this component. Include this snippet in the stack configuration for the
-management account (typically `root`) in the management tenant/OU (usually something like `mgmt` or `core`) in the
-global region (`gbl`). You can insert the content directly, or create a `stacks/catalog/account.yaml` file and import it
-from there.
-
-```yaml
-components:
- terraform:
- account:
- settings:
- spacelift:
- workspace_enabled: false
- backend:
- s3:
- role_arn: null
- vars:
- enabled: true
- account_email_format: aws+%s@example.net
- account_iam_user_access_to_billing: ALLOW
- organization_enabled: true
- aws_service_access_principals:
- - cloudtrail.amazonaws.com
- - guardduty.amazonaws.com
- - ipam.amazonaws.com
- - ram.amazonaws.com
- - securityhub.amazonaws.com
- - servicequotas.amazonaws.com
- - sso.amazonaws.com
- - securityhub.amazonaws.com
- - auditmanager.amazonaws.com
- enabled_policy_types:
- - SERVICE_CONTROL_POLICY
- - TAG_POLICY
- organization_config:
- root_account:
- name: core-root
- stage: root
- tenant: core
- tags:
- eks: false
- accounts: []
- organization:
- service_control_policies:
- - DenyEC2InstancesWithoutEncryptionInTransit
- organizational_units:
- - name: core
- accounts:
- - name: core-artifacts
- tenant: core
- stage: artifacts
- tags:
- eks: false
- - name: core-audit
- tenant: core
- stage: audit
- tags:
- eks: false
- - name: core-auto
- tenant: core
- stage: auto
- tags:
- eks: true
- - name: core-corp
- tenant: core
- stage: corp
- tags:
- eks: true
- - name: core-dns
- tenant: core
- stage: dns
- tags:
- eks: false
- - name: core-identity
- tenant: core
- stage: identity
- tags:
- eks: false
- - name: core-network
- tenant: core
- stage: network
- tags:
- eks: false
- - name: core-security
- tenant: core
- stage: security
- tags:
- eks: false
- service_control_policies:
- - DenyLeavingOrganization
- - name: plat
- accounts:
- - name: plat-dev
- tenant: plat
- stage: dev
- tags:
- eks: true
- - name: plat-sandbox
- tenant: plat
- stage: sandbox
- tags:
- eks: true
- - name: plat-staging
- tenant: plat
- stage: staging
- tags:
- eks: true
- - name: plat-prod
- tenant: plat
- stage: prod
- tags:
- eks: true
- service_control_policies:
- - DenyLeavingOrganization
- service_control_policies_config_paths:
- # These paths specify where to find the service control policies identified by SID in the service_control_policies sections above.
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/cloudwatch-logs-policies.yaml"
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/deny-all-policies.yaml"
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/iam-policies.yaml"
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/kms-policies.yaml"
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/organization-policies.yaml"
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/route53-policies.yaml"
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/s3-policies.yaml"
- - "https://raw.githubusercontent.com/cloudposse/terraform-aws-service-control-policies/0.12.0/catalog/ec2-policies.yaml"
-```
-
-## First Time Organization Setup
-
-Your AWS Organization is managed by the `account` component, along with accounts and organizational units.
-
-However, because the AWS defaults for an Organization and its accounts are not exactly what we want, and there is no way
-to change them via Terraform, we have to first provision the AWS Organization, then take some steps on the AWS console,
-and then we can provision the rest.
-
-### Use AWS Console to create and set up the Organization
-
-Unfortunately, there are some tasks that need to be done via the console. Log into the AWS Console with the root (not
-SuperAdmin) credentials you have saved in 1Password.
-
-#### Request an increase in the maximum number of accounts allowed
-
-:::caution Make sure your support plan for the _root_ account was upgraded to the "Business" level (or Higher). This is
-necessary to expedite the quota increase requests, which could take several days on a basic support plan. Without it,
-AWS support will claim that since we’re not currently utilizing any of the resources, so they do not want to approve the
-requests. AWS support is not aware of your other organization. If AWS still gives you problems, please escalate to your
-AWS TAM. See [AWS](https://docs.cloudposse.com/reference-architecture/reference/aws).
-
-:::
-
-1. From the region list, select "US East (N. Virginia) us-east-1".
-
-2. From the account dropdown menu, select "My Service Quotas".
-
-3. From the Sidebar, select "AWS Services".
-
-4. Type "org" in the search field under "AWS services"
-
-5. Click on "AWS Organizations" in the "Service" list
-
-6. Click on "Default maximum number of accounts", which should take you to a new view
-
-7. Click on "Request quota increase" on the right side of the view, which should pop us a request form
-
-8. At the bottom of the form, under "Change quota value", enter the number you decided on in the previous step (probably
- "20") and click "Request"
-
-#### (Optional) Create templates to request other quota increases
-
-New accounts start with a low limit on the number of instances you can create. However, as you add accounts, and use
-more instances, the numbers automatically adjust up. So you may or may not want to create a template to generate
-automatic quota increase requests, depending on how many instances per account you expect to want to provision right
-away.
-
-Create a
-[Quota request template](https://docs.aws.amazon.com/servicequotas/latest/userguide/organization-templates.html) for the
-organization. From the Sidebar, click "Quota request template"
-
-Add each EC2 quota increase request you want to make:
-
-1. Click "Add Quota" on the right side of the view
-
-2. Under "Region", select your default region (repeat with the backup region if you are using one)
-
-3. Under "Service", type "EC2" and select "Amazon Elastic Compute Cloud (Amazon EC2)"
-
-4. Under "Quota", find the quota you want to increase. The likely candidates are:
-
-5. type "stand" and select "Running On-Demand Standard (A, C, D, H, I, M, R, T, Z) Instances"
-
-6. type "stand" and select "All Standard (A, C, D, H, I, M, R, T, Z) Spot Instance Request"
-
-7. type "g i" and select "Running On-Demand G Instances"
-
-8. type "all g" and select "All G Spot Instance Requests"
-
-9. Under "Desired quota value" enter your desired default quota
-
-10. Click "Add"
-
-After you have added all the templates, click "Enable" on the Quota request template screen to enable the templates.
-
-#### Enable resource sharing with AWS Organization
-
-[AWS Resource Access Manager (RAM)](https://docs.aws.amazon.com/ram/latest/userguide/what-is.html) lets you share your
-resources with any AWS account or through AWS Organizations.
-
-
-
-If you have multiple AWS accounts, you can create resources centrally and use AWS RAM to share those resources with
-other accounts.
-
-Resource sharing through AWS Organization will be used to share the Transit Gateway deployed in the `network` account
-with other accounts to connect their VPCs to the shared Transit Gateway.
-
-This is a one-time manual step in the AWS Resource Access Manager console. When you share resources within your
-organization, AWS RAM does not send invitations to principals. Principals in your organization get access to shared
-resources without exchanging invitations.
-
-To enable resource sharing with AWS Organization via AWS Management Console
-
-- Open the Settings page of AWS Resource Access Manager console at
- [https://console.aws.amazon.com/ram/home#Settings](https://console.aws.amazon.com/ram/home#Settings)
-
-- Choose "Enable sharing with AWS Organizations"
-
-To enable resource sharing with AWS Organization via AWS CLI
-
-```
- √ . [xamp-SuperAdmin] (HOST) infra ⨠ aws ram enable-sharing-with-aws-organization
-{
- "returnValue": true
-}
-```
-
-For more information, see:
-
-- [https://docs.aws.amazon.com/ram/latest/userguide/what-is.html](https://docs.aws.amazon.com/ram/latest/userguide/what-is.html)
-
-- [https://docs.aws.amazon.com/ram/latest/userguide/getting-started-sharing.html](https://docs.aws.amazon.com/ram/latest/userguide/getting-started-sharing.html)
-
-- [https://docs.aws.amazon.com/organizations/latest/userguide/services-that-can-integrate-ram.html](https://docs.aws.amazon.com/organizations/latest/userguide/services-that-can-integrate-ram.html)
-
-### Import the organization into Terraform using the `account` component
-
-After we are done with the above ClickOps and the Service Quota Increase for maximum number of accounts has been
-granted, we can then do the rest via Terraform.
-
-In the Geodesic shell, as SuperAdmin, execute the following command to get the AWS Organization ID that will be used to
-import the organization:
-
-```
-aws organizations describe-organization
-```
-
-From the output, identify the _organization-id_:
-
-```
-{
- "Organization": {
- "Id": "o-7qcakq6zxw",
- "Arn": "arn:aws:organizations::
- ...
-```
-
-Using the example above, the _organization-id_ is o-7qcakq6zxw.
-
-In the Geodesic shell, as SuperAdmin, execute the following command to import the AWS Organization, changing the stack
-name `core-gbl-root` if needed, to reflect the stack where the organization management account is defined, and changing
-the last argument to reflect the _organization-id_ from the output of the previous command.
-
-```
-atmos terraform import account --stack core-gbl-root 'aws_organizations_organization.this[0]' 'o-7qcakq6zxw'
-```
-
-### Provision AWS OUs and Accounts using the `account` component
-
-AWS accounts and organizational units are generated dynamically by the `terraform/account` component using the
-configuration in the `gbl-root` stack.
-
-:::info _**Special note:**_ \*\*\*\* In the rare case where you will need to be enabling non-default AWS Regions,
-temporarily comment out the `DenyRootAccountAccess` service control policy setting in `gbl-root.yaml`. You will restore
-it later, after enabling the optional Regions. See related:
-[Decide on Opting Into Non-default Regions](https://docs.cloudposse.com/reference-architecture/design-decisions/cold-start/decide-on-opting-into-non-default-regions)
-
-:::
-
-:::caution **You must wait until your quota increase request has been granted.** If you try to create the accounts
-before the quota increase is granted, you can expect to see failures like `ACCOUNT_NUMBER_LIMIT_EXCEEDED`.
-
-:::
-
-In the Geodesic shell, execute the following commands to provision AWS Organizational Units and AWS accounts:
-
-```
-atmos terraform apply account --stack gbl-root
-```
-
-Review the Terraform plan, _**ensure that no new organization will be created**_ (look for
-`aws_organizations_organization.this[0]`), type "yes" to approve and apply. This creates the AWS organizational units
-and AWS accounts.
-
-### Configure root account credentials for each account
-
-Note: unless you need to enable non-default AWS regions (see next step), this step can be done later or in parallel with
-other steps, for example while waiting for Terraform to create resources.
-
-**For** _**each**_ **new account:**
-
-1. Perform a password reset by attempting to [log in to the AWS console](https://signin.aws.amazon.com/signin) as a
- "root user", using that account's email address, and then clicking the "Forgot password?" link. You will receive a
- password reset link via email, which should be forwarded to the shared Slack channel for automated messages. Click
- the link and enter a new password. (Use 1Password or [Random.org](https://www.random.org/passwords) to create a
- password 26-38 characters long, including at least 3 of each class of character: lower case, uppercase, digit, and
- symbol. You may need to manually combine or add to the generated password to ensure 3 symbols and digits are
- present.) Save the email address and generated password as web login credentials in 1Password. While you are at it,
- save the account number in a separate field.
-
-2. Log in using the new password, choose "My Security Credentials" from the account dropdown menu and set up
- Multi-Factor Authentication (MFA) to use a Virutal MFA device. Save the MFA TOTP key in 1Password by using
- 1Password's TOTP field and built-in screen scanner. Also, save the Virutal MFA ARN (sometimes shown as "serial
- number").
-
-3. While logged in, enable optional regions as described in the next step, if needed.
-
-4. (Optional, but highly recommended): [Unsubscribe](https://pages.awscloud.com/communication-preferences.html) the
- account's email address from all marketing emails.
-
-### (Optional) Enable regions
-
-Most AWS regions are enabled by default. If you are using a region that is not enabled by default (such as Middle
-East/Bahrain), you need to take extra steps.
-
-1. While logged in using root credentials (see the previous step), in the account dropdown menu, select "My Account" to
- get to the [Billing home page](https://console.aws.amazon.com/billing/home?#/account).
-
-2. In the "AWS Regions" section, enable the regions you want to enable.
-
-3. Go to the IAM [account settings page](https://console.aws.amazon.com/iam/home?#/account_settings) and edit the STS
- Global endpoint to create session tokens valid in all AWS regions.
-
-You will need to wait a few minutes for the regions to be enabled before you can proceed to the next step. Until they
-are enabled, you may get what look like AWS authentication or permissions errors.
-
-After enabling the regions in all accounts, re-enable the `DenyRootAccountAccess` service control policy setting in
-`gbl-root.yaml` and rerun
-
-```
-atmos terraform apply account --stack gbl-root
-```
-
-
-
-## Requirements
-
-| Name | Version |
-|------|---------|
-| [terraform](#requirement\_terraform) | >= 1.0.0 |
-| [aws](#requirement\_aws) | >= 4.9.0 |
-
-## Providers
-
-| Name | Version |
-|------|---------|
-| [aws](#provider\_aws) | >= 4.9.0 |
-
-## Modules
-
-| Name | Source | Version |
-|------|--------|---------|
-| [accounts\_service\_control\_policies](#module\_accounts\_service\_control\_policies) | cloudposse/service-control-policies/aws | 0.9.2 |
-| [organization\_service\_control\_policies](#module\_organization\_service\_control\_policies) | cloudposse/service-control-policies/aws | 0.9.2 |
-| [organizational\_units\_service\_control\_policies](#module\_organizational\_units\_service\_control\_policies) | cloudposse/service-control-policies/aws | 0.9.2 |
-| [service\_control\_policy\_statements\_yaml\_config](#module\_service\_control\_policy\_statements\_yaml\_config) | cloudposse/config/yaml | 1.0.2 |
-| [this](#module\_this) | cloudposse/label/null | 0.25.0 |
-
-## Resources
-
-| Name | Type |
-|------|------|
-| [aws_organizations_account.organization_accounts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_account) | resource |
-| [aws_organizations_account.organizational_units_accounts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_account) | resource |
-| [aws_organizations_organization.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_organization) | resource |
-| [aws_organizations_organizational_unit.child](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_organizational_unit) | resource |
-| [aws_organizations_organizational_unit.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/organizations_organizational_unit) | resource |
-| [aws_organizations_organization.existing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/organizations_organization) | data source |
-
-## Inputs
-
-| Name | Description | Type | Default | Required |
-|------|-------------|------|---------|:--------:|
-| [account\_email\_format](#input\_account\_email\_format) | Email address format for the accounts (e.g. `aws+%s@example.com`) | `string` | n/a | yes |
-| [account\_iam\_user\_access\_to\_billing](#input\_account\_iam\_user\_access\_to\_billing) | If set to `ALLOW`, the new account enables IAM users to access account billing information if they have the required permissions. If set to `DENY`, then only the root user of the new account can access account billing information | `string` | `"DENY"` | no |
-| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no |
-| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no |
-| [aws\_service\_access\_principals](#input\_aws\_service\_access\_principals) | List of AWS service principal names for which you want to enable integration with your organization. This is typically in the form of a URL, such as service-abbreviation.amazonaws.com. Organization must have `feature_set` set to ALL. For additional information, see the [AWS Organizations User Guide](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services.html) | `list(string)` | n/a | yes |
-
-| [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
-| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
-| [enabled\_policy\_types](#input\_enabled\_policy\_types) | List of Organizations policy types to enable in the Organization Root. Organization must have feature\_set set to ALL. For additional information about valid policy types (e.g. SERVICE\_CONTROL\_POLICY and TAG\_POLICY), see the [AWS Organizations API Reference](https://docs.aws.amazon.com/organizations/latest/APIReference/API_EnablePolicyType.html) | `list(string)` | n/a | yes |
-| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
-| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no |
-| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no |
-| [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no |
-| [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no |
-| [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` |
[
"default"
]
| no |
-| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no |
-| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no |
-| [organization\_config](#input\_organization\_config) | Organization, Organizational Units and Accounts configuration | `any` | n/a | yes |
-| [organization\_enabled](#input\_organization\_enabled) | A boolean flag indicating whether to create an Organization or use the existing one | `bool` | `true` | no |
-| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
-| [region](#input\_region) | AWS Region | `string` | n/a | yes |
-| [service\_control\_policies\_config\_paths](#input\_service\_control\_policies\_config\_paths) | List of paths to Service Control Policy configurations | `list(string)` | n/a | yes |
-| [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
-| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no |
-| [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no |
-
-## Outputs
-
-| Name | Description |
-|------|-------------|
-| [account\_arns](#output\_account\_arns) | List of account ARNs (excluding root account) |
-| [account\_ids](#output\_account\_ids) | List of account IDs (excluding root account) |
-| [account\_info\_map](#output\_account\_info\_map) | Map of account names to
eks: boolean, account hosts at least one EKS cluster
id: account id (number)
stage: (optional) the account "stage"
tenant: (optional) the account "tenant" |
-| [account\_names\_account\_arns](#output\_account\_names\_account\_arns) | Map of account names to account ARNs (excluding root account) |
-| [account\_names\_account\_ids](#output\_account\_names\_account\_ids) | Map of account names to account IDs (excluding root account) |
-| [account\_names\_account\_scp\_arns](#output\_account\_names\_account\_scp\_arns) | Map of account names to SCP ARNs for accounts with SCPs |
-| [account\_names\_account\_scp\_ids](#output\_account\_names\_account\_scp\_ids) | Map of account names to SCP IDs for accounts with SCPs |
-| [eks\_accounts](#output\_eks\_accounts) | List of EKS accounts |
-| [non\_eks\_accounts](#output\_non\_eks\_accounts) | List of non EKS accounts |
-| [organization\_arn](#output\_organization\_arn) | Organization ARN |
-| [organization\_id](#output\_organization\_id) | Organization ID |
-| [organization\_master\_account\_arn](#output\_organization\_master\_account\_arn) | Organization master account ARN |
-| [organization\_master\_account\_email](#output\_organization\_master\_account\_email) | Organization master account email |
-| [organization\_master\_account\_id](#output\_organization\_master\_account\_id) | Organization master account ID |
-| [organization\_scp\_arn](#output\_organization\_scp\_arn) | Organization Service Control Policy ARN |
-| [organization\_scp\_id](#output\_organization\_scp\_id) | Organization Service Control Policy ID |
-| [organizational\_unit\_arns](#output\_organizational\_unit\_arns) | List of Organizational Unit ARNs |
-| [organizational\_unit\_ids](#output\_organizational\_unit\_ids) | List of Organizational Unit IDs |
-| [organizational\_unit\_names\_organizational\_unit\_arns](#output\_organizational\_unit\_names\_organizational\_unit\_arns) | Map of Organizational Unit names to Organizational Unit ARNs |
-| [organizational\_unit\_names\_organizational\_unit\_ids](#output\_organizational\_unit\_names\_organizational\_unit\_ids) | Map of Organizational Unit names to Organizational Unit IDs |
-| [organizational\_unit\_names\_organizational\_unit\_scp\_arns](#output\_organizational\_unit\_names\_organizational\_unit\_scp\_arns) | Map of OU names to SCP ARNs |
-| [organizational\_unit\_names\_organizational\_unit\_scp\_ids](#output\_organizational\_unit\_names\_organizational\_unit\_scp\_ids) | Map of OU names to SCP IDs |
-
-
-
-## References
-
-- [cloudposse/terraform-aws-components](https://github.com/cloudposse/terraform-aws-components/tree/main/modules/account) -
- Cloud Posse's upstream component
-
-
-
-
diff --git a/docs/generated/github-actions/library/actions/_category_.json b/docs/generated/github-actions/library/actions/_category_.json
deleted file mode 100644
index b318ed08a..000000000
--- a/docs/generated/github-actions/library/actions/_category_.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "label": "actions",
- "collapsible": true,
- "collapsed": false,
- "className": "command",
- "link": {
- "type": "generated-index",
- "title": "GitHub Actions"
- }
-}
diff --git a/docs/generated/github-actions/library/actions/docker-build-push/README.mdx b/docs/generated/github-actions/library/actions/docker-build-push/README.mdx
deleted file mode 100644
index 2c058e0cd..000000000
--- a/docs/generated/github-actions/library/actions/docker-build-push/README.mdx
+++ /dev/null
@@ -1,111 +0,0 @@
----
-title: docker-build-push
-sidebar_label: docker-build-push
-sidebar_class_name: command
-description: |-
- Build Docker image and push it
-tags:
- - github-action
-
-custom_edit_url: https://github.com/cloudposse/github-action-docker-build-push/blob/main/README.yaml
----
-
-# GitHub Action: `docker-build-push`
-Build Docker image and push it
-
-
-
-
-## Introduction
-
-Build Docker image and push it.
-
-
-
-## Usage
-
-```yaml
- name: github-action-docker-build-push
- on:
- push:
- branches: [ master ]
-
- jobs:
- context:
- runs-on: ubuntu-latest
- steps:
- - name: github-action-docker-build-push
- uses: actions/checkout@v4
-
- - name: github-action-docker-build-push
- id: build
- uses: cloudposse/github-action-docker-build-push@main
- with:
- registry: registry.hub.docker.com
- organization: "${{ github.event.repository.owner.login }}"
- repository: "${{ github.event.repository.name }}"
- login: "${{ secrets.DOCKERHUB_USERNAME }}"
- password: "${{ secrets.DOCKERHUB_PASSWORD }}"
- platforms: linux/amd64,linux/arm64
-
- outputs:
- image: ${{ steps.build.outputs.image }}
- tag: ${{ steps.build.outputs.tag }}
-```
-> [!TIP]
-> If omitted, `cache-from` and `cache-to` will default to `gha`.
-> In an AWS environment, we recommend using [ECR as a remote cache](https://aws.amazon.com/blogs/containers/announcing-remote-cache-support-in-amazon-ecr-for-buildkit-clients/).
-
-```diff
- - name: github-action-docker-build-push
- id: build
- uses: cloudposse/github-action-docker-build-push@main
- with:
- registry: registry.hub.docker.com
- organization: "${{ github.event.repository.owner.login }}"
- repository: "${{ github.event.repository.name }}"
-+ cache-from: "type=registry,ref=registry.hub.docker.com/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}:cache"
-+ cache-to: "mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=registry.hub.docker.com/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}:cache"
-```
-
-
-
-
-
-
-
-
-## Inputs
-
-| Name | Description | Default | Required |
-|------|-------------|---------|----------|
-| build-args | List of build-time variables | N/A | false |
-| cache-from | List of external cache sources for buildx (e.g., user/app:cache, type=local,src=path/to/dir) | type=gha | false |
-| cache-to | List of cache export destinations for buildx (e.g., user/app:cache, type=local,dest=path/to/dir) | type=gha,mode=max | false |
-| docker-metadata-pr-head-sha | Set to `true` to tag images with the PR HEAD SHA instead of the merge commit SHA within pull requests. | false | false |
-| file | Dockerfile name | Dockerfile | false |
-| login | Docker login | | false |
-| no-cache | Send the --no-cache flag to the docker build process | false | false |
-| organization | Organization | N/A | true |
-| password | Docker password | | false |
-| platforms | List of target platforms for build (e.g. linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,etc) | linux/amd64 | false |
-| provenance | Generate provenance attestation for the build | N/A | false |
-| registry | Docker registry | N/A | true |
-| repository | Repository | N/A | true |
-| secret-files | List of secret files to expose to the build (e.g., key=filename, MY\_SECRET=./secret.txt) | N/A | false |
-| secrets | List of secrets to expose to the build (e.g., key=string, GIT\_AUTH\_TOKEN=mytoken) | N/A | false |
-| ssh | List of SSH agent socket or keys to expose to the build | N/A | false |
-| tags | List of tags (supports https://github.com/docker/metadata-action#tags-input) | N/A | false |
-| target | Sets the target stage to build | | false |
-| workdir | Working directory | ./ | false |
-
-
-## Outputs
-
-| Name | Description |
-|------|-------------|
-| image | Docker image name |
-| metadata | Docker image metadata |
-| tag | Docker image tag |
-
-
diff --git a/docs/generated/modules/library/aws/_category_.json b/docs/generated/modules/library/aws/_category_.json
deleted file mode 100644
index 51a02423f..000000000
--- a/docs/generated/modules/library/aws/_category_.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "label": "aws",
- "collapsible": true,
- "collapsed": true,
- "className": "command",
- "link": {
- "type": "generated-index",
- "title": "Provider: aws"
- }
-}
diff --git a/docs/generated/modules/library/aws/dms/README.mdx b/docs/generated/modules/library/aws/dms/README.mdx
deleted file mode 100644
index 457969c9a..000000000
--- a/docs/generated/modules/library/aws/dms/README.mdx
+++ /dev/null
@@ -1,404 +0,0 @@
----
-title: dms
-sidebar_label: dms
-sidebar_class_name: command
-description: |-
- Terraform modules for provisioning and managing AWS [DMS](https://aws.amazon.com/dms/) resources.
-
- The following DMS resources are supported:
-
- - [IAM Roles for DMS](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-iam)
- - [DMS Endpoints](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-endpoint)
- - [DMS Replication Instances](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-replication-instance)
- - [DMS Replication Tasks](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-replication-task)
- - [DMS Event Subscriptions](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-event-subscription)
-
- Refer to [modules](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules) for more details.
-custom_edit_url: https://github.com/cloudposse/terraform-aws-dms/blob/main/README.yaml
----
-
-# Module: `dms`
-Terraform modules for provisioning and managing AWS [DMS](https://aws.amazon.com/dms/) resources.
-
-The following DMS resources are supported:
-
- - [IAM Roles for DMS](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-iam)
- - [DMS Endpoints](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-endpoint)
- - [DMS Replication Instances](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-replication-instance)
- - [DMS Replication Tasks](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-replication-task)
- - [DMS Event Subscriptions](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules/dms-event-subscription)
-
-Refer to [modules](https://github.com/cloudposse/terraform-aws-dms/tree/main/modules) for more details.
-
-
-
-
-
-
-## Usage
-
-
-For a complete example, see [examples/complete](https://github.com/cloudposse/terraform-aws-dms/tree/main/examples/complete).
-
-For automated tests of the example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest)
-(which tests and deploys the example on AWS), see [test](https://github.com/cloudposse/terraform-aws-dms/tree/main/test).
-
-
-
-
-## Examples
-
-
-```hcl
- module "dms_iam" {
- source = "cloudposse/dms/aws//modules/dms-iam"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- context = module.this.context
- }
-
- module "vpc" {
- source = "cloudposse/vpc/aws"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- ipv4_primary_cidr_block = "172.19.0.0/16"
-
- context = module.this.context
- }
-
- module "subnets" {
- source = "cloudposse/dynamic-subnets/aws"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- availability_zones = ["us-east-2a", "us-east-2b"]
- vpc_id = local.vpc_id
- igw_id = [module.vpc.igw_id]
- ipv4_cidr_block = [module.vpc.vpc_cidr_block]
- nat_gateway_enabled = false
- nat_instance_enabled = false
-
- context = module.this.context
- }
-
- module "dms_replication_instance" {
- source = "cloudposse/dms/aws//modules/dms-replication-instance"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- engine_version = "3.4"
- replication_instance_class = "dms.t2.small"
- allocated_storage = 50
- apply_immediately = true
- auto_minor_version_upgrade = true
- allow_major_version_upgrade = false
- multi_az = false
- publicly_accessible = false
- preferred_maintenance_window = "sun:10:30-sun:14:30"
- vpc_security_group_ids = [module.vpc.vpc_default_security_group_id, module.aurora_postgres_cluster.security_group_id]
- subnet_ids = module.subnets.private_subnet_ids
-
- context = module.this.context
-
- depends_on = [
- # The required DMS roles must be present before replication instances can be provisioned
- module.dms_iam,
- aws_vpc_endpoint.s3
- ]
- }
-
- module "aurora_postgres_cluster" {
- source = "cloudposse/rds-cluster/aws"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- engine = "aurora-postgresql"
- engine_mode = "provisioned"
- engine_version = "13.4"
- cluster_family = "aurora-postgresql13"
- cluster_size = 1
- admin_user = "admin_user"
- admin_password = "admin_password"
- db_name = "postgres"
- db_port = 5432
- instance_type = "db.t3.medium"
- vpc_id = module.vpc.vpc_id
- subnets = module.subnets.private_subnet_ids
- security_groups = [module.vpc.vpc_default_security_group_id]
- deletion_protection = false
- autoscaling_enabled = false
- storage_encrypted = false
- intra_security_group_traffic_enabled = false
- skip_final_snapshot = true
- enhanced_monitoring_role_enabled = false
- iam_database_authentication_enabled = false
-
- cluster_parameters = [
- {
- name = "rds.logical_replication"
- value = "1"
- apply_method = "pending-reboot"
- },
- {
- name = "max_replication_slots"
- value = "10"
- apply_method = "pending-reboot"
- },
- {
- name = "wal_sender_timeout"
- value = "0"
- apply_method = "pending-reboot"
- },
- {
- name = "max_worker_processes"
- value = "8"
- apply_method = "pending-reboot"
- },
- {
- name = "max_logical_replication_workers"
- value = "10"
- apply_method = "pending-reboot"
- },
- {
- name = "max_parallel_workers"
- value = "8"
- apply_method = "pending-reboot"
- },
- {
- name = "max_parallel_workers"
- value = "8"
- apply_method = "pending-reboot"
- }
- ]
-
- context = module.this.context
- }
-
- module "dms_endpoint_aurora_postgres" {
- source = "cloudposse/dms/aws//modules/dms-endpoint"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- endpoint_type = "source"
- engine_name = "aurora-postgresql"
- server_name = module.aurora_postgres_cluster.reader_endpoint
- database_name = "postgres"
- port = 5432
- username = "admin_user"
- password = "admin_password"
- extra_connection_attributes = ""
- secrets_manager_access_role_arn = null
- secrets_manager_arn = null
- ssl_mode = "none"
-
- attributes = ["source"]
- context = module.this.context
- }
-
- resource "aws_vpc_endpoint" "s3" {
- vpc_endpoint_type = "Gateway"
- vpc_id = module.vpc.vpc_id
- service_name = "com.amazonaws.${var.region}.s3"
- route_table_ids = module.subnets.private_route_table_ids
-
- tags = module.this.tags
- }
-
- module "s3_bucket" {
- source = "cloudposse/s3-bucket/aws"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- acl = "private"
- versioning_enabled = false
- allow_encrypted_uploads_only = false
- allow_ssl_requests_only = false
- force_destroy = true
- block_public_acls = true
- block_public_policy = true
- ignore_public_acls = true
- restrict_public_buckets = true
-
- context = module.this.context
- }
-
- module "dms_endpoint_s3_bucket" {
- source = "cloudposse/dms/aws//modules/dms-endpoint"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- endpoint_type = "target"
- engine_name = "s3"
-
- s3_settings = {
- bucket_name = module.s3_bucket.bucket_id
- bucket_folder = null
- cdc_inserts_only = false
- csv_row_delimiter = " "
- csv_delimiter = ","
- data_format = "parquet"
- compression_type = "GZIP"
- date_partition_delimiter = "NONE"
- date_partition_enabled = true
- date_partition_sequence = "YYYYMMDD"
- include_op_for_full_load = true
- parquet_timestamp_in_millisecond = true
- timestamp_column_name = "timestamp"
- service_access_role_arn = aws_iam_role.s3.arn
- }
-
- extra_connection_attributes = ""
-
- attributes = ["target"]
- context = module.this.context
- }
-
- module "dms_replication_task" {
- source = "cloudposse/dms/aws//modules/dms-replication-task"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- replication_instance_arn = module.dms_replication_instance.replication_instance_arn
- start_replication_task = true
- migration_type = "full-load-and-cdc"
- source_endpoint_arn = module.dms_endpoint_aurora_postgres.endpoint_arn
- target_endpoint_arn = module.dms_endpoint_s3_bucket.endpoint_arn
-
- replication_task_settings = file("${path.module}/config/replication-task-settings.json")
- table_mappings = file("${path.module}/config/replication-task-table-mappings.json")
-
- context = module.this.context
- }
-
- module "sns_topic" {
- source = "cloudposse/sns-topic/aws"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- sqs_dlq_enabled = false
- fifo_topic = false
- fifo_queue_enabled = false
- encryption_enabled = false
-
- allowed_aws_services_for_sns_published = [
- "cloudwatch.amazonaws.com",
- "dms.amazonaws.com"
- ]
-
- context = module.this.context
- }
-
- module "dms_replication_instance_event_subscription" {
- source = "cloudposse/dms/aws//modules/dms-event-subscription"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- event_subscription_enabled = true
- source_type = "replication-instance"
- source_ids = [module.dms_replication_instance.replication_instance_id]
- sns_topic_arn = module.sns_topic.sns_topic_arn
-
- # https://awscli.amazonaws.com/v2/documentation/api/latest/reference/dms/describe-event-categories.html
- event_categories = [
- "low storage",
- "configuration change",
- "maintenance",
- "deletion",
- "creation",
- "failover",
- "failure"
- ]
-
- attributes = ["instance"]
- context = module.this.context
- }
-
- module "dms_replication_task_event_subscription" {
- source = "cloudposse/dms/aws//modules/dms-event-subscription"
- # Cloud Posse recommends pinning every module to a specific version
- # version = "x.x.x"
-
- event_subscription_enabled = true
- source_type = "replication-task"
- source_ids = [module.dms_replication_task.replication_task_id]
- sns_topic_arn = module.sns_topic.sns_topic_arn
-
- # https://awscli.amazonaws.com/v2/documentation/api/latest/reference/dms/describe-event-categories.html
- event_categories = [
- "configuration change",
- "state change",
- "deletion",
- "creation",
- "failure"
- ]
-
- attributes = ["task"]
- context = module.this.context
- }
-```
-
-__NOTE:__ If a replication task is in "Failed" state (for any reason, e.g. network connectivity issues, database table issues, configuration issues),
-it can't be destroyed with Terraform (but can be updated).
-The task needs to be updated/fixed and moved to any other state like "Running", "Stopped", "Starting", "Ready", etc.
-
-You can monitor the progress of your task by checking the task status and by monitoring the task's control table.
-The task status indicates the condition of an AWS DMS task and its associated resources.
-It includes such indications as if the task is being created, starting, running, stopped, or failed.
-It also includes the current state of the tables that the task is migrating, such as if a full load of a table has begun
-or is in progress and details such as the number of inserts, deletes, and updates have occurred for the table.
-
-Refer to [Monitoring DMS Task Status](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Monitoring.html#CHAP_Tasks.Status) for more information.
-
-
-
-
-## Requirements
-
-| Name | Version |
-|------|---------|
-| [terraform](#requirement\_terraform) | >= 1.0 |
-| [aws](#requirement\_aws) | >= 5.0 |
-
-## Providers
-
-No providers.
-
-## Modules
-
-| Name | Source | Version |
-|------|--------|---------|
-| [this](#module\_this) | cloudposse/label/null | 0.25.0 |
-
-## Resources
-
-No resources.
-
-## Inputs
-
-| Name | Description | Type | Default | Required |
-|------|-------------|------|---------|:--------:|
-| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no |
-| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no |
-| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
-| [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
-| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
-| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
-| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no |
-| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no |
-| [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no |
-| [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no |
-| [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` | [
"default"
]
| no |
-| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no |
-| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no |
-| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
-| [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
-| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no |
-| [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no |
-
-## Outputs
-
-No outputs.
-
-
diff --git a/docs/generated/github-actions/_category_.json b/docs/github-actions/_category_.json
similarity index 100%
rename from docs/generated/github-actions/_category_.json
rename to docs/github-actions/_category_.json
diff --git a/docs/generated/github-actions/index.mdx b/docs/github-actions/index.mdx
similarity index 100%
rename from docs/generated/github-actions/index.mdx
rename to docs/github-actions/index.mdx
diff --git a/docs/generated/modules/_category_.json b/docs/modules/_category_.json
similarity index 100%
rename from docs/generated/modules/_category_.json
rename to docs/modules/_category_.json
diff --git a/docs/generated/modules/index.mdx b/docs/modules/index.mdx
similarity index 100%
rename from docs/generated/modules/index.mdx
rename to docs/modules/index.mdx
diff --git a/package-lock.json b/package-lock.json
index d2dcc2ee0..898f4f0d8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6874,8 +6874,8 @@
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
"node_modules/custom-loaders": {
- "resolved": "plugins/custom-loaders",
- "link": true
+ "version": "0.0.0",
+ "resolved": "file:plugins/custom-loaders"
},
"node_modules/cytoscape": {
"version": "3.30.0",
@@ -22543,9 +22543,6 @@
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
- },
- "plugins/custom-loaders": {
- "version": "0.0.0"
}
}
}
diff --git a/scripts/docs-collator/AbstractFetcher.py b/scripts/docs-collator/AbstractFetcher.py
index 0729b64d3..bb4045db7 100644
--- a/scripts/docs-collator/AbstractFetcher.py
+++ b/scripts/docs-collator/AbstractFetcher.py
@@ -1,8 +1,8 @@
import os
-DOCS_DIR = 'docs'
-TARGETS_MD = 'targets.md'
-README_YAML = 'README.yaml'
+DOCS_DIR = "docs"
+TARGETS_MD = "targets.md"
+README_YAML = "README.yaml"
class MissingReadmeYamlException(Exception):
@@ -20,7 +20,9 @@ def _fetch_readme_yaml(self, repo, module_download_dir):
self.github_provider.fetch_file(repo, README_YAML, module_download_dir)
def _fetch_docs(self, repo, module_download_dir, submodule_dir=""):
- remote_files = self.github_provider.list_repo_dir(repo, os.path.join(submodule_dir, DOCS_DIR))
+ remote_files = self.github_provider.list_repo_dir(
+ repo, os.path.join(submodule_dir, DOCS_DIR)
+ )
for remote_file in remote_files:
if os.path.basename(remote_file) == TARGETS_MD: # skip targets.md
diff --git a/scripts/docs-collator/AbstractRenderer.py b/scripts/docs-collator/AbstractRenderer.py
index c30fa7e7e..73f772eb5 100644
--- a/scripts/docs-collator/AbstractRenderer.py
+++ b/scripts/docs-collator/AbstractRenderer.py
@@ -4,8 +4,8 @@
from utils import io
from utils import rendering
-README_YAML = 'README.yaml'
-DOCS_DIR = 'docs'
+README_YAML = "README.yaml"
+DOCS_DIR = "docs"
class TerraformDocsRenderingError(Exception):
@@ -22,7 +22,9 @@ def _pre_rendering_fixes(self, repo, module_download_dir, submodule_dir=""):
if submodule_dir == "":
content = rendering.rename_name(repo.name, content)
else:
- content = rendering.rename_name("pre-fix-" + os.path.basename(submodule_dir), content)
+ content = rendering.rename_name(
+ "pre-fix-" + os.path.basename(submodule_dir), content
+ )
io.save_string_to_file(readme_yaml_file, content)
def _post_rendering_fixes(self, repo, readme_md_file, submodule_dir=""):
@@ -30,19 +32,25 @@ def _post_rendering_fixes(self, repo, readme_md_file, submodule_dir=""):
content = rendering.fix_self_non_closing_br_tags(content)
content = rendering.fix_custom_non_self_closing_tags_in_pre(content)
content = rendering.fix_github_edit_url(content, repo, submodule_dir)
- content = rendering.fix_sidebar_label(content, repo, os.path.basename(submodule_dir))
- content = rendering.replace_relative_links_with_github_links(repo, content, submodule_dir)
+ content = rendering.fix_sidebar_label(
+ content, repo, os.path.basename(submodule_dir)
+ )
+ content = rendering.replace_relative_links_with_github_links(
+ repo, content, submodule_dir
+ )
io.save_string_to_file(readme_md_file, content)
def _copy_extra_resources_for_docs(self, module_download_dir, module_docs_dir):
extra_resources_dir = os.path.join(module_download_dir, DOCS_DIR)
- files = io.get_filenames_in_dir(extra_resources_dir, '*', True)
+ files = io.get_filenames_in_dir(extra_resources_dir, "*", True)
for file in files:
- if os.path.basename(file).lower().endswith('.md') or os.path.isdir(file):
+ if os.path.basename(file).lower().endswith(".md") or os.path.isdir(file):
continue
- dest_file = os.path.join(module_docs_dir, DOCS_DIR, os.path.relpath(file, extra_resources_dir))
+ dest_file = os.path.join(
+ module_docs_dir, DOCS_DIR, os.path.relpath(file, extra_resources_dir)
+ )
io.copy_file(file, dest_file)
logging.info(f"Copied extra file: {dest_file}")
diff --git a/scripts/docs-collator/ComponentRenderer.py b/scripts/docs-collator/ComponentRenderer.py
index 912442d17..196d75c82 100644
--- a/scripts/docs-collator/ComponentRenderer.py
+++ b/scripts/docs-collator/ComponentRenderer.py
@@ -2,17 +2,17 @@
from utils import io, rendering, templating
-README_MD = 'README.md'
-CHANGELOG_MD = 'CHANGELOG.md'
-GITHUB_REPO = 'cloudposse/terraform-aws-components'
-INDEX_CATEGORY_JSON = '_category_.json'
+README_MD = "README.md"
+CHANGELOG_MD = "CHANGELOG.md"
+GITHUB_REPO = "cloudposse/terraform-aws-components"
+INDEX_CATEGORY_JSON = "_category_.json"
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-TEMPLATES_DIR = os.path.join(SCRIPT_DIR, 'templates/components')
+TEMPLATES_DIR = os.path.join(SCRIPT_DIR, "templates/components")
jenv = templating.init_templating(TEMPLATES_DIR)
-DOC_TEMPLATE = jenv.get_template('readme.md')
-INDEX_CATEGORY_TEMPLATE = jenv.get_template('index_category.json')
+DOC_TEMPLATE = jenv.get_template("readme.md")
+INDEX_CATEGORY_TEMPLATE = jenv.get_template("index_category.json")
class ComponentRenderer:
@@ -21,12 +21,12 @@ def __init__(self, download_dir, docs_dir):
self.docs_dir = docs_dir
def render(self, component):
- module_download_dir = os.path.join(self.download_dir, 'modules', component)
+ module_download_dir = os.path.join(self.download_dir, "modules", component)
files = io.get_filenames_in_dir(module_download_dir, README_MD, True)
- files += io.get_filenames_in_dir(module_download_dir, '*.md', True)
+ files += io.get_filenames_in_dir(module_download_dir, "*.md", True)
- images = io.get_filenames_in_dir(module_download_dir, '*.png', True)
+ images = io.get_filenames_in_dir(module_download_dir, "*.png", True)
for file in files:
if file.endswith(CHANGELOG_MD):
@@ -34,48 +34,85 @@ def render(self, component):
self.__render_doc(component, file)
for image in images:
- io.copy_file(image, os.path.join(self.docs_dir, component, os.path.relpath(image, module_download_dir)))
+ io.copy_file(
+ image,
+ os.path.join(
+ self.docs_dir,
+ component,
+ os.path.relpath(image, module_download_dir),
+ ),
+ )
def __render_doc(self, component, file):
- module_download_dir = os.path.join(self.download_dir, 'modules')
+ module_download_dir = os.path.join(self.download_dir, "modules")
+ # Render Terraform docs using template for website doc format
+ # This will update the given README in place
+ module_path = os.path.join(module_download_dir, component)
+ rendering.render_terraform_docs(
+ module_path, os.path.join(TEMPLATES_DIR, "terraform-docs.yml")
+ )
+
+ # Static replacement and corrections for docusaurus
content = io.read_file_to_string(file)
content = rendering.fix_self_non_closing_br_tags(content)
content = rendering.fix_custom_non_self_closing_tags_in_pre(content)
content = rendering.remove_logo_from_the_bottom(content)
+ content = rendering.fix_mdx_format(content)
change_log_file = os.path.join(os.path.dirname(file), CHANGELOG_MD)
- change_log_content = io.read_file_to_string(change_log_file) if os.path.exists(change_log_file) else ''
+ change_log_content = (
+ io.read_file_to_string(change_log_file)
+ if os.path.exists(change_log_file)
+ else ""
+ )
change_log_content = rendering.shift_headings(change_log_content)
relative_path = os.path.relpath(file, module_download_dir)
- result_file = os.path.join(self.docs_dir, os.path.relpath(file, module_download_dir)) # /README.md
-
- name = component if os.path.basename(file) == "README.md" else os.path.basename(file).replace(".md", "")
+ result_file = os.path.join(
+ self.docs_dir, os.path.relpath(file, module_download_dir)
+ ) # /README.md
+
+ name = (
+ component
+ if os.path.basename(file) == "README.md"
+ else os.path.basename(file).replace(".md", "")
+ )
label = name
title = name
- github_edit_url = f"https://github.com/{GITHUB_REPO}/blob/master/modules/{relative_path}"
+ github_edit_url = (
+ f"https://github.com/{GITHUB_REPO}/blob/main/modules/{relative_path}"
+ )
- if len(relative_path.split('/')) > 2 and relative_path.split('/')[1] != 'docs' : # this is submodule
+ if (
+ len(relative_path.split("/")) > 2 and relative_path.split("/")[1] != "docs"
+ ): # this is submodule
submodule_name = os.path.basename(os.path.dirname(result_file))
label = submodule_name
title = submodule_name
- # renaming final file /.md
- result_file = os.path.join(os.path.dirname(result_file), f"{submodule_name}.md")
+ # renaming final file /.mdx
+ result_file = os.path.join(
+ os.path.dirname(result_file), f"{submodule_name}.mdx"
+ )
+ else:
+ # renaming final file /README.mdx
+ result_file = os.path.join(os.path.dirname(result_file), f"{name}.mdx")
io.create_dirs(os.path.dirname(result_file))
- tags = ['terraform', 'aws', component]
+ tags = ["terraform", "aws", component]
- doc_content = DOC_TEMPLATE.render(label=label,
- title=title,
- content=content,
- change_log_content=change_log_content,
- github_repository=GITHUB_REPO,
- github_edit_url=github_edit_url,
- tags=tags)
+ doc_content = DOC_TEMPLATE.render(
+ label=label,
+ title=title,
+ content=content,
+ change_log_content=change_log_content,
+ github_repository=GITHUB_REPO,
+ github_edit_url=github_edit_url,
+ tags=tags,
+ )
io.save_string_to_file(result_file, doc_content)
@@ -89,7 +126,6 @@ def __create_indexes_for_subfolder(self, component):
def __render_category_index(self, dir):
name = os.path.basename(dir)
- content = INDEX_CATEGORY_TEMPLATE.render(label=name,
- title=name)
+ content = INDEX_CATEGORY_TEMPLATE.render(label=name, title=name)
io.save_string_to_file(os.path.join(dir, INDEX_CATEGORY_JSON), content)
diff --git a/scripts/docs-collator/GitHubActionFetcher.py b/scripts/docs-collator/GitHubActionFetcher.py
index f730422f5..b30072686 100644
--- a/scripts/docs-collator/GitHubActionFetcher.py
+++ b/scripts/docs-collator/GitHubActionFetcher.py
@@ -2,10 +2,10 @@
from AbstractFetcher import AbstractFetcher, MissingReadmeYamlException
-DOCS_DIR = 'docs'
-ACTIONS_DIR = 'actions'
-README_YAML = 'README.yaml'
-README_MD = 'README.md'
+DOCS_DIR = "docs"
+ACTIONS_DIR = "actions"
+README_YAML = "README.yaml"
+README_MD = "README.md"
class GitHubActionFetcher(AbstractFetcher):
diff --git a/scripts/docs-collator/GitHubActionRenderer.py b/scripts/docs-collator/GitHubActionRenderer.py
index 1157e6c13..2a0a0e6ab 100644
--- a/scripts/docs-collator/GitHubActionRenderer.py
+++ b/scripts/docs-collator/GitHubActionRenderer.py
@@ -6,18 +6,18 @@
from utils import io
from utils import rendering, templating
-TARGETS_MD = 'targets.md'
-README_YAML = 'README.yaml'
-README_MD = 'README.md'
-INDEX_CATEGORY_JSON = '_category_.json'
-README_TEMPLATE = 'readme.md'
-DOC_SUBFOLDER = 'actions'
+TARGETS_MD = "targets.md"
+README_YAML = "README.yaml"
+README_MD = "README.md"
+INDEX_CATEGORY_JSON = "_category_.json"
+README_TEMPLATE = "readme.md"
+DOC_SUBFOLDER = "actions"
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-TEMPLATES_DIR = os.path.join(SCRIPT_DIR, 'templates/github-actions')
+TEMPLATES_DIR = os.path.join(SCRIPT_DIR, "templates/github-actions")
jenv = templating.init_templating(TEMPLATES_DIR)
-INDEX_CATEGORY_TEMPLATE = jenv.get_template('index_category.json')
+INDEX_CATEGORY_TEMPLATE = jenv.get_template("index_category.json")
class GitHubActionRenderer(AbstractRenderer):
@@ -51,12 +51,18 @@ def __render_readme(self, module_download_dir, module_docs_dir):
io.create_dirs(module_docs_dir)
- response = subprocess.run(["make", "readme",
- f"README_TEMPLATE_FILE={readme_tmpl_file}",
- f"README_FILE={readme_md_file}",
- f"README_YAML={readme_yaml_file}",
- f"README_TEMPLATE_YAML={readme_yaml_file}",
- f"README_INCLUDES={module_download_dir}"], capture_output=True)
+ response = subprocess.run(
+ [
+ "make",
+ "readme",
+ f"README_TEMPLATE_FILE={readme_tmpl_file}",
+ f"README_FILE={readme_md_file}",
+ f"README_YAML={readme_yaml_file}",
+ f"README_TEMPLATE_YAML={readme_yaml_file}",
+ f"README_INCLUDES={module_download_dir}",
+ ],
+ capture_output=True,
+ )
if response.returncode != 0:
error_message = response.stderr.decode("utf-8")
diff --git a/scripts/docs-collator/GitHubProvider.py b/scripts/docs-collator/GitHubProvider.py
index 5a8f74a37..3b09f43f6 100644
--- a/scripts/docs-collator/GitHubProvider.py
+++ b/scripts/docs-collator/GitHubProvider.py
@@ -7,9 +7,13 @@
from utils import io
-GITHUB_ORG = 'cloudposse'
-TERRAFORM_MODULE_NAME_PATTERN = re.compile("^terraform-[a-zA-Z0-9]+-.*") # convention is terraform--
-GITHUB_ACTION_NAME_PATTERN = re.compile("^github-action-.*") # convention is github-action-
+GITHUB_ORG = "cloudposse"
+TERRAFORM_MODULE_NAME_PATTERN = re.compile(
+ "^terraform-[a-zA-Z0-9]+-.*"
+) # convention is terraform--
+GITHUB_ACTION_NAME_PATTERN = re.compile(
+ "^github-action-.*"
+) # convention is github-action-
class GitHubProvider:
@@ -17,7 +21,9 @@ def __init__(self, github_api_token):
self.github = Github(github_api_token)
def get_terraform_repos(self, includes_csv, excludes_csv):
- return self.__get_repos(includes_csv, excludes_csv, TERRAFORM_MODULE_NAME_PATTERN)
+ return self.__get_repos(
+ includes_csv, excludes_csv, TERRAFORM_MODULE_NAME_PATTERN
+ )
def get_github_actions_repos(self, includes_csv, excludes_csv):
return self.__get_repos(includes_csv, excludes_csv, GITHUB_ACTION_NAME_PATTERN)
@@ -71,7 +77,9 @@ def list_repo_dir(self, repo, remote_dir, recursive=True):
def fetch_file(self, repo, remote_file, output_dir):
io.create_dirs(os.path.join(output_dir, os.path.dirname(remote_file)))
- content_encoded = repo.get_contents(remote_file, ref=repo.default_branch).content
+ content_encoded = repo.get_contents(
+ remote_file, ref=repo.default_branch
+ ).content
content = base64.b64decode(content_encoded)
output_file = os.path.join(output_dir, remote_file)
io.save_to_file(output_file, content)
diff --git a/scripts/docs-collator/ModuleFetcher.py b/scripts/docs-collator/ModuleFetcher.py
index 6f9f9fe71..06efeee75 100644
--- a/scripts/docs-collator/ModuleFetcher.py
+++ b/scripts/docs-collator/ModuleFetcher.py
@@ -2,11 +2,11 @@
from AbstractFetcher import AbstractFetcher, MissingReadmeYamlException
-DOCS_DIR = 'docs'
-IMAGES_DIR = 'images'
-SUBMODULES_DIR = 'modules'
-README_YAML = 'README.yaml'
-README_MD = 'README.md'
+DOCS_DIR = "docs"
+IMAGES_DIR = "images"
+SUBMODULES_DIR = "modules"
+README_YAML = "README.yaml"
+README_MD = "README.md"
class ModuleFetcher(AbstractFetcher):
@@ -54,4 +54,8 @@ def __fetch_submodules(self, repo, module_download_dir):
for readme_file in readme_files.values():
self.github_provider.fetch_file(repo, readme_file, module_download_dir)
if os.path.basename(readme_file) == README_YAML:
- self._fetch_docs(repo, module_download_dir, submodule_dir=os.path.dirname(readme_file))
+ self._fetch_docs(
+ repo,
+ module_download_dir,
+ submodule_dir=os.path.dirname(readme_file),
+ )
diff --git a/scripts/docs-collator/ModuleRenderer.py b/scripts/docs-collator/ModuleRenderer.py
index c4f525585..3f6ebaa31 100644
--- a/scripts/docs-collator/ModuleRenderer.py
+++ b/scripts/docs-collator/ModuleRenderer.py
@@ -6,22 +6,22 @@
from utils import io
from utils import rendering, templating
-DOCS_DIR = 'docs'
-IMAGES_DIR = 'images'
-SUBMODULES_DIR = 'modules'
-TARGETS_MD = 'targets.md'
-README_YAML = 'README.yaml'
-README_MD = 'README.md'
-INDEX_CATEGORY_JSON = '_category_.json'
-MODULES_README_TEMPLATE = 'readme.md'
+DOCS_DIR = "docs"
+IMAGES_DIR = "images"
+SUBMODULES_DIR = "modules"
+TARGETS_MD = "targets.md"
+README_YAML = "README.yaml"
+README_MD = "README.md"
+INDEX_CATEGORY_JSON = "_category_.json"
+MODULES_README_TEMPLATE = "readme.md"
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-TEMPLATES_DIR = os.path.join(SCRIPT_DIR, 'templates/modules')
+TEMPLATES_DIR = os.path.join(SCRIPT_DIR, "templates/modules")
jenv = templating.init_templating(TEMPLATES_DIR)
-PROVIDER_INDEX_CATEGORY_TEMPLATE = jenv.get_template('provider_index_category.json')
-INDEX_CATEGORY_TEMPLATE = jenv.get_template('index_category.json')
-SUBMODULE_TEMPLATE = jenv.get_template('submodule.readme.md')
+PROVIDER_INDEX_CATEGORY_TEMPLATE = jenv.get_template("provider_index_category.json")
+INDEX_CATEGORY_TEMPLATE = jenv.get_template("index_category.json")
+SUBMODULE_TEMPLATE = jenv.get_template("submodule.readme.md")
class ModuleRenderer(AbstractRenderer):
@@ -48,7 +48,9 @@ def render(self, repo):
self._copy_extra_resources_for_docs(module_download_dir, module_docs_dir)
self.__copy_extra_resources_for_images(module_download_dir, module_docs_dir)
- self.__copy_extra_resources_for_submodules(repo, module_download_dir, module_docs_dir)
+ self.__copy_extra_resources_for_submodules(
+ repo, module_download_dir, module_docs_dir
+ )
self.__create_index_for_provider(repo)
self.__create_indexes_for_subfolders(repo)
@@ -60,12 +62,18 @@ def __render_readme(self, module_download_dir, module_docs_dir):
io.create_dirs(module_docs_dir)
- response = subprocess.run(["make", "readme",
- f"README_TEMPLATE_FILE={readme_tmpl_file}",
- f"README_FILE={readme_md_file}",
- f"README_YAML={readme_yaml_file}",
- f"README_TEMPLATE_YAML={readme_yaml_file}",
- f"README_INCLUDES={module_download_dir}"], capture_output=True)
+ response = subprocess.run(
+ [
+ "make",
+ "readme",
+ f"README_TEMPLATE_FILE={readme_tmpl_file}",
+ f"README_FILE={readme_md_file}",
+ f"README_YAML={readme_yaml_file}",
+ f"README_TEMPLATE_YAML={readme_yaml_file}",
+ f"README_INCLUDES={module_download_dir}",
+ ],
+ capture_output=True,
+ )
if response.returncode != 0:
error_message = response.stderr.decode("utf-8")
@@ -75,19 +83,23 @@ def __render_readme(self, module_download_dir, module_docs_dir):
def __copy_extra_resources_for_images(self, module_download_dir, module_docs_dir):
extra_resources_dir = os.path.join(module_download_dir, IMAGES_DIR)
- files = io.get_filenames_in_dir(extra_resources_dir, '*', True)
+ files = io.get_filenames_in_dir(extra_resources_dir, "*", True)
for file in files:
if os.path.isdir(file):
continue
- dest_file = os.path.join(module_docs_dir, IMAGES_DIR, os.path.relpath(file, extra_resources_dir))
+ dest_file = os.path.join(
+ module_docs_dir, IMAGES_DIR, os.path.relpath(file, extra_resources_dir)
+ )
io.copy_file(file, dest_file)
logging.info(f"Copied extra file: {dest_file}")
- def __copy_extra_resources_for_submodules(self, repo, module_download_dir, module_docs_dir):
+ def __copy_extra_resources_for_submodules(
+ self, repo, module_download_dir, module_docs_dir
+ ):
extra_resources_dir = os.path.join(module_download_dir, SUBMODULES_DIR)
- files = io.get_filenames_in_dir(extra_resources_dir, '*', True)
+ files = io.get_filenames_in_dir(extra_resources_dir, "*", True)
readme_files = {}
for remote_file in files:
@@ -120,13 +132,19 @@ def __copy_extra_resources_for_submodules(self, repo, module_download_dir, modul
# Copy the README.md if we found one and no README.yaml
submodule_name = os.path.basename(os.path.dirname(dest_file))
submodule_readme_content = io.read_file_to_string(readme)
- submodule_readme_content = rendering.replace_relative_links_with_github_links(repo, submodule_readme_content, rel_dir)
-
- content = SUBMODULE_TEMPLATE.render(label=submodule_name,
- title=submodule_name,
- description=submodule_name,
- github_edit_url=f"https://github.com/{repo.full_name}/blob/{repo.default_branch}/{rel_path}",
- content=submodule_readme_content)
+ submodule_readme_content = (
+ rendering.replace_relative_links_with_github_links(
+ repo, submodule_readme_content, rel_dir
+ )
+ )
+
+ content = SUBMODULE_TEMPLATE.render(
+ label=submodule_name,
+ title=submodule_name,
+ description=submodule_name,
+ github_edit_url=f"https://github.com/{repo.full_name}/blob/{repo.default_branch}/{rel_path}",
+ content=submodule_readme_content,
+ )
io.create_dirs(os.path.dirname(dest_file))
io.save_string_to_file(dest_file, content)
@@ -139,15 +157,17 @@ def __create_index_for_provider(self, repo):
json_file = os.path.join(self.docs_dir, provider, INDEX_CATEGORY_JSON)
if not os.path.exists(json_file):
- content = PROVIDER_INDEX_CATEGORY_TEMPLATE.render(label=provider,
- title=provider,
- description=provider)
+ content = PROVIDER_INDEX_CATEGORY_TEMPLATE.render(
+ label=provider, title=provider, description=provider
+ )
io.save_string_to_file(json_file, content)
def __create_indexes_for_subfolders(self, repo):
# create category index files for dirs that doesn't have files because of docusaurus sidebar rendering issues
provider, module_name = rendering.parse_terraform_repo_name(repo.name)
- files = io.get_filenames_in_dir(os.path.join(self.docs_dir, provider, module_name), '*', True)
+ files = io.get_filenames_in_dir(
+ os.path.join(self.docs_dir, provider, module_name), "*", True
+ )
for file in files:
if os.path.isfile(file) or io.has_files(file):
continue
@@ -157,8 +177,7 @@ def __create_indexes_for_subfolders(self, repo):
def __render_category_index(self, dir):
name = os.path.basename(dir)
- content = INDEX_CATEGORY_TEMPLATE.render(label=name,
- title=name)
+ content = INDEX_CATEGORY_TEMPLATE.render(label=name, title=name)
io.save_string_to_file(os.path.join(dir, INDEX_CATEGORY_JSON), content)
diff --git a/scripts/docs-collator/render_docs_for_components.py b/scripts/docs-collator/render_docs_for_components.py
index 00c85c1ee..9dbd653df 100644
--- a/scripts/docs-collator/render_docs_for_components.py
+++ b/scripts/docs-collator/render_docs_for_components.py
@@ -6,12 +6,12 @@
from ComponentRenderer import ComponentRenderer
from utils import io
-OUTPUT_DOC_DIR = 'content/components/library/aws'
-CLONED_REPO_DIR = 'tmp/components/terraform-aws-components'
+OUTPUT_DOC_DIR = "content/components/library/aws"
+CLONED_REPO_DIR = "tmp/components/terraform-aws-components"
def main(input_dir, output_dir):
- modules_dir = os.path.join(input_dir, 'modules')
+ modules_dir = os.path.join(input_dir, "modules")
logging.info(f"Looking for modules in: {modules_dir}")
@@ -27,13 +27,30 @@ def main(input_dir, output_dir):
@click.command()
-@click.option('--input-dir', default=CLONED_REPO_DIR, required=True, help="Path to cloned repository")
-@click.option('--output-dir', default=OUTPUT_DOC_DIR, required=False, help="Rendered documentation output directory")
-@click.option('--log-level', default=False, required=False, help="Recursive lookup in sub folders of README.md files")
+@click.option(
+ "--input-dir",
+ default=CLONED_REPO_DIR,
+ required=True,
+ help="Path to cloned repository",
+)
+@click.option(
+ "--output-dir",
+ default=OUTPUT_DOC_DIR,
+ required=False,
+ help="Rendered documentation output directory",
+)
+@click.option(
+ "--log-level",
+ default=False,
+ required=False,
+ help="Recursive lookup in sub folders of README.md files",
+)
def cli_main(input_dir, output_dir, log_level):
- logging.basicConfig(format='[%(asctime)s] %(levelname)s %(message)s',
- datefmt='%d-%m-%Y %H:%M:%S',
- level=logging.getLevelName(log_level))
+ logging.basicConfig(
+ format="[%(asctime)s] %(levelname)s %(message)s",
+ datefmt="%d-%m-%Y %H:%M:%S",
+ level=logging.getLevelName(log_level),
+ )
main(input_dir, output_dir)
diff --git a/scripts/docs-collator/render_docs_for_github_actions.py b/scripts/docs-collator/render_docs_for_github_actions.py
index a9e767d19..6f9b36ed2 100644
--- a/scripts/docs-collator/render_docs_for_github_actions.py
+++ b/scripts/docs-collator/render_docs_for_github_actions.py
@@ -8,12 +8,19 @@
from GitHubActionRenderer import GitHubActionRenderer
from GitHubProvider import GitHubProvider
-DOWNLOAD_TMP_DIR = 'tmp/github-actions'
-OUTPUT_DOC_DIR = 'content/github-actions/library'
-REPOS_SKIP_LIST = {'terraform-aws-components'}
-
-
-def main(github_api_token, output_dir, download_dir, includes_csv, excludes_csv, fail_on_rendering_error):
+DOWNLOAD_TMP_DIR = "tmp/github-actions"
+OUTPUT_DOC_DIR = "content/github-actions/library"
+REPOS_SKIP_LIST = {"terraform-aws-components"}
+
+
+def main(
+ github_api_token,
+ output_dir,
+ download_dir,
+ includes_csv,
+ excludes_csv,
+ fail_on_rendering_error,
+):
github_provider = GitHubProvider(github_api_token)
fetcher = GitHubActionFetcher(github_provider, download_dir)
renderer = GitHubActionRenderer(download_dir, output_dir)
@@ -44,30 +51,72 @@ def main(github_api_token, output_dir, download_dir, includes_csv, excludes_csv,
@click.command()
-@click.option('--github-api-token',
- envvar='PUBLIC_REPO_ACCESS_TOKEN', required=True, help="GitHub API token")
-@click.option('--output-dir',
- default=OUTPUT_DOC_DIR, required=True, help="Rendered documentation output directory")
-@click.option('--download-dir',
- default=DOWNLOAD_TMP_DIR, required=True, help="Temporary download directory")
-@click.option('--includes',
- required=False,
- help="Comma separated list of repos to include. Conflicts with --excludes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'")
-@click.option('--excludes',
- required=False,
- help="Comma separated list of repos to exclude. Conflicts with --includes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'")
-@click.option('--fail-on-rendering-error',
- is_flag=True, show_default=True, default=False, required=False, help="Fail on rendering error")
-@click.option('--log-level',
- default='INFO', required=False, help="Log level. Available options")
-def cli_main(github_api_token, output_dir, download_dir, includes, excludes, fail_on_rendering_error, log_level):
- logging.basicConfig(format='[%(asctime)s] %(levelname)s %(message)s',
- datefmt='%d-%m-%Y %H:%M:%S',
- level=logging.getLevelName(log_level))
-
- logging.info(f"Download directory: {download_dir}, documentation output directory: {output_dir}")
-
- main(github_api_token, output_dir, download_dir, includes, excludes, fail_on_rendering_error)
+@click.option(
+ "--github-api-token",
+ envvar="PUBLIC_REPO_ACCESS_TOKEN",
+ required=True,
+ help="GitHub API token",
+)
+@click.option(
+ "--output-dir",
+ default=OUTPUT_DOC_DIR,
+ required=True,
+ help="Rendered documentation output directory",
+)
+@click.option(
+ "--download-dir",
+ default=DOWNLOAD_TMP_DIR,
+ required=True,
+ help="Temporary download directory",
+)
+@click.option(
+ "--includes",
+ required=False,
+ help="Comma separated list of repos to include. Conflicts with --excludes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'",
+)
+@click.option(
+ "--excludes",
+ required=False,
+ help="Comma separated list of repos to exclude. Conflicts with --includes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'",
+)
+@click.option(
+ "--fail-on-rendering-error",
+ is_flag=True,
+ show_default=True,
+ default=False,
+ required=False,
+ help="Fail on rendering error",
+)
+@click.option(
+ "--log-level", default="INFO", required=False, help="Log level. Available options"
+)
+def cli_main(
+ github_api_token,
+ output_dir,
+ download_dir,
+ includes,
+ excludes,
+ fail_on_rendering_error,
+ log_level,
+):
+ logging.basicConfig(
+ format="[%(asctime)s] %(levelname)s %(message)s",
+ datefmt="%d-%m-%Y %H:%M:%S",
+ level=logging.getLevelName(log_level),
+ )
+
+ logging.info(
+ f"Download directory: {download_dir}, documentation output directory: {output_dir}"
+ )
+
+ main(
+ github_api_token,
+ output_dir,
+ download_dir,
+ includes,
+ excludes,
+ fail_on_rendering_error,
+ )
if __name__ == "__main__":
diff --git a/scripts/docs-collator/render_docs_for_modules.py b/scripts/docs-collator/render_docs_for_modules.py
index 0682c57a9..5c3def28a 100644
--- a/scripts/docs-collator/render_docs_for_modules.py
+++ b/scripts/docs-collator/render_docs_for_modules.py
@@ -8,11 +8,18 @@
from ModuleFetcher import ModuleFetcher, MissingReadmeYamlException
from ModuleRenderer import ModuleRenderer
-DOWNLOAD_TMP_DIR = 'tmp/modules'
-OUTPUT_DOC_DIR = 'content/modules/library'
-
-
-def main(github_api_token, output_dir, download_dir, includes_csv, excludes_csv, fail_on_rendering_error):
+DOWNLOAD_TMP_DIR = "tmp/modules"
+OUTPUT_DOC_DIR = "content/modules/library"
+
+
+def main(
+ github_api_token,
+ output_dir,
+ download_dir,
+ includes_csv,
+ excludes_csv,
+ fail_on_rendering_error,
+):
github_provider = GitHubProvider(github_api_token)
fetcher = ModuleFetcher(github_provider, download_dir)
renderer = ModuleRenderer(download_dir, output_dir)
@@ -43,30 +50,72 @@ def main(github_api_token, output_dir, download_dir, includes_csv, excludes_csv,
@click.command()
-@click.option('--github-api-token',
- envvar='PUBLIC_REPO_ACCESS_TOKEN', required=True, help="GitHub API token")
-@click.option('--output-dir',
- default=OUTPUT_DOC_DIR, required=True, help="Rendered documentation output directory")
-@click.option('--download-dir',
- default=DOWNLOAD_TMP_DIR, required=True, help="Temporary download directory")
-@click.option('--includes',
- required=False,
- help="Comma separated list of repos to include. Conflicts with --excludes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'")
-@click.option('--excludes',
- required=False,
- help="Comma separated list of repos to exclude. Conflicts with --includes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'")
-@click.option('--fail-on-rendering-error',
- is_flag=True, show_default=True, default=False, required=False, help="Fail on rendering error")
-@click.option('--log-level',
- default='INFO', required=False, help="Log level. Available options")
-def cli_main(github_api_token, output_dir, download_dir, includes, excludes, fail_on_rendering_error, log_level):
- logging.basicConfig(format='[%(asctime)s] %(levelname)s %(message)s',
- datefmt='%d-%m-%Y %H:%M:%S',
- level=logging.getLevelName(log_level))
-
- logging.info(f"Download directory: {download_dir}, documentation output directory: {output_dir}")
-
- main(github_api_token, output_dir, download_dir, includes, excludes, fail_on_rendering_error)
+@click.option(
+ "--github-api-token",
+ envvar="PUBLIC_REPO_ACCESS_TOKEN",
+ required=True,
+ help="GitHub API token",
+)
+@click.option(
+ "--output-dir",
+ default=OUTPUT_DOC_DIR,
+ required=True,
+ help="Rendered documentation output directory",
+)
+@click.option(
+ "--download-dir",
+ default=DOWNLOAD_TMP_DIR,
+ required=True,
+ help="Temporary download directory",
+)
+@click.option(
+ "--includes",
+ required=False,
+ help="Comma separated list of repos to include. Conflicts with --excludes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'",
+)
+@click.option(
+ "--excludes",
+ required=False,
+ help="Comma separated list of repos to exclude. Conflicts with --includes. Example: 'terraform-aws-s3-log-storage,terraform-aws-network-firewall'",
+)
+@click.option(
+ "--fail-on-rendering-error",
+ is_flag=True,
+ show_default=True,
+ default=False,
+ required=False,
+ help="Fail on rendering error",
+)
+@click.option(
+ "--log-level", default="INFO", required=False, help="Log level. Available options"
+)
+def cli_main(
+ github_api_token,
+ output_dir,
+ download_dir,
+ includes,
+ excludes,
+ fail_on_rendering_error,
+ log_level,
+):
+ logging.basicConfig(
+ format="[%(asctime)s] %(levelname)s %(message)s",
+ datefmt="%d-%m-%Y %H:%M:%S",
+ level=logging.getLevelName(log_level),
+ )
+
+ logging.info(
+ f"Download directory: {download_dir}, documentation output directory: {output_dir}"
+ )
+
+ main(
+ github_api_token,
+ output_dir,
+ download_dir,
+ includes,
+ excludes,
+ fail_on_rendering_error,
+ )
if __name__ == "__main__":
diff --git a/scripts/docs-collator/templates/components/readme.md b/scripts/docs-collator/templates/components/readme.md
index 89cda4c88..838eb2555 100644
--- a/scripts/docs-collator/templates/components/readme.md
+++ b/scripts/docs-collator/templates/components/readme.md
@@ -9,7 +9,7 @@ tags: [{{ tags|join(', ') }}]
{{ content }}
{% if change_log_content|trim != "" %}
-## CHANGELOG
+## Changelog
{{ change_log_content }}
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/scripts/docs-collator/templates/components/terraform-docs.yml b/scripts/docs-collator/templates/components/terraform-docs.yml
new file mode 100644
index 000000000..08a076091
--- /dev/null
+++ b/scripts/docs-collator/templates/components/terraform-docs.yml
@@ -0,0 +1,225 @@
+# https://pkg.go.dev/github.com/terraform-docs/terraform-docs/terraform#Module
+content: |-
+ {{- $context_variables := list "context" "enabled" "namespace" "tenant" "environment" "stage" "name" "delimiter" "attributes" "tags" "additional_tag_map" "label_order" "regex_replace_chars" "id_length_limit" "label_key_case" "label_value_case" "descriptor_formats" "labels_as_tags" -}}
+
+ {{ .Header }}
+
+ ## Contents
+
+ {{ if ne (len .Module.Requirements) 0 -}}
+ ### Version Requirements
+ {{ range .Module.Providers }}
+ - `{{ .Name }}`{{ if .Version }}, version: `{{ .Version }}`{{ end }}
+ {{- end }}
+ {{- end }}
+
+ {{ if ne (len .Module.Providers) 0 -}}
+ ### Providers
+ {{ range .Module.Providers }}
+ - `{{ .Name }}`{{ if .Version }}, version: `{{ .Version }}`{{ end }}
+ {{- end }}
+ {{- end }}
+
+ {{ if ne (len .Module.ModuleCalls) 0 -}}
+ ### Modules
+
+ Name | Version | Source | Description
+ --- | --- | --- | ---
+ {{ range .Module.ModuleCalls }}
+ {{- $baseUrl := "https://registry.terraform.io/modules" -}}
+ {{ if contains "//" .Source -}}
+ {{- $moduleParts := regexSplit "//" .Source 2 -}}
+ {{- $moduleName := first $moduleParts -}}
+ {{- $submodulePath := last $moduleParts -}}
+ `{{ .Name }}` | {{ .Version | default "latest" }} | {{ printf "[`%s`](%s/%s/%s/%s)" .Source $baseUrl $moduleName $submodulePath .Version }} | {{ tostring .Description | default "n/a" }}
+ {{ else -}}
+ `{{ .Name }}` | {{ .Version | default "latest" }} | {{ printf "[`%s`](%s/%s/%s)" .Source $baseUrl .Source .Version }} | {{ tostring .Description | default "n/a" }}
+ {{ end }}
+ {{- end -}}
+ {{- end -}}
+
+ {{- if ne (len .Module.Resources) 0 }}
+
+ ### Resources
+
+ The following resources are used by this module:
+ {{ range .Module.Resources }}
+ {{- $isResource := and $.Config.Sections.Resources ( eq "resource" (printf "%s" .GetMode)) }}
+ {{- if $isResource }}
+ {{- $fullspec := ternary .URL (printf "[`%s`](%s)" .Spec .URL) .Spec }}
+ - {{ $fullspec }} {{ printf "(%s)" .GetMode -}}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+
+ {{ if ne (len .Module.Resources) 0 -}}
+ ### Data Sources
+
+ The following data sources are used by this module:
+ {{ range .Module.Resources }}
+ {{- $isDataResource := and $.Config.Sections.DataSources ( eq "data source" (printf "%s" .GetMode)) }}
+ {{- if $isDataResource }}
+ {{- $fullspec := ternary .URL (printf "[`%s`](%s)" .Spec .URL) .Spec }}
+ - {{ $fullspec }} {{ printf "(%s)" .GetMode -}}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+
+ ### Required Inputs
+
+
+ {{- range .Module.Inputs }}
+ {{- if and (not (has .Name $context_variables)) .Required }}
+ - `{{ .Name }}`{{ if lt (len (split "\n" (tostring .Type))) 2 }} (`{{ tostring .Type }}`){{end}} required{{ if contains "OBSOLETE: " (tostring .Description) }} OBSOLETE{{ end }}
+ -
+ {{- $lines := regexSplit "\n" (tostring .Description | replace "OBSOLETE: " "") -1 -}}
+ {{- range $lines }}
+ {{ . }}
+ {{- end }}
+
+ {{ if gt (len (split "\n" (tostring .Type))) 2 }}
+ **Type:**
+ ```hcl
+ {{ .Type.Raw }}
+ ```
+
+ {{ end }}
+
+
+ {{- end }}
+ {{- end }}
+
+
+ {{ $optional := false -}}
+ {{ range .Module.Inputs }}{{ if not .Required }}{{ $optional = true -}}{{ end -}}{{ end -}}
+
+ {{ if $optional -}}
+
+ ### Optional Inputs
+
+
+ {{- range .Module.Inputs }}
+ {{- if and (not (has .Name $context_variables)) (not .Required) }}
+ - `{{ .Name }}`{{ if lt (len (split "\n" (tostring .Type))) 2 }} (`{{ tostring .Type }}`){{end}} optional{{ if contains "OBSOLETE: " (tostring .Description) }} OBSOLETE{{ end }}
+ -
+ {{- $lines := regexSplit "\n" (tostring .Description | replace "OBSOLETE: " "") -1 -}}
+ {{- range $lines }}
+ {{ . }}
+ {{- end }}
+
+ {{ if gt (len (split "\n" (tostring .Type))) 2 }}
+ **Type:**
+ ```hcl
+ {{ tostring .Type }}
+ ```
+
+ {{ end }}
+ **Default value:** {{ if lt (len (split "\n" .GetValue)) 2 }}`{{ .GetValue }}`{{ else }}
+ ```hcl
+ {{- $lines := regexSplit "\n" .GetValue -1 -}}
+ {{- range $lines }}
+ {{ . }}
+ {{- end }}
+ ```
+ {{ end }}
+
+ {{- end -}}
+ {{ end -}}
+
+ {{ end }}
+
+ ### Context Variables
+
+
+
+ The following variables are defined in the `context.tf` file of this module and part of the [terraform-null-label](https://registry.terraform.io/modules/cloudposse/label/null) pattern.
+
+
+
+ {{- range .Module.Inputs }}
+ {{- if and (has .Name $context_variables) }}
+ - `{{ .Name }}`{{ if lt (len (split "\n" (tostring .Type))) 2 }} (`{{ tostring .Type }}`){{end}} {{ ternary .Required "required" "optional" }}{{ if contains "OBSOLETE: " (tostring .Description) }} OBSOLETE{{ end }}
+ -
+ {{- $lines := regexSplit "\n" (tostring .Description | replace "OBSOLETE: " "") -1 -}}
+ {{- range $lines }}
+ {{ . }}
+ {{- end }}
+ **Required:** {{ ternary .Required "Yes" "No" }}
+ {{ if gt (len (split "\n" (tostring .Type))) 2 }}
+ **Type:**
+ ```hcl
+ {{ .Type.Raw }}
+ ```
+
+ {{ end }}
+ **Default value:** {{ if lt (len (split "\n" .GetValue)) 2 }}`{{ .GetValue }}`{{ else }}
+ ```hcl
+ {{- $lines := regexSplit "\n" .GetValue -1 -}}
+ {{- range $lines }}
+ {{ . }}
+ {{- end }}
+ ```
+ {{ end }}
+
+ {{- end }}
+ {{- end }}
+
+
+
+ {{ if ne (len .Module.Outputs) 0 -}}
+ ### Outputs
+
+
+ {{- range .Module.Outputs }}
+ - `{{ .Name }}`{{ if contains "OBSOLETE: " (tostring .Description) }} OBSOLETE{{ end }}
+ -
+ {{- $lines := regexSplit "\n" (tostring .Description | replace "OBSOLETE: " "" | default "n/a" ) -1 -}}
+ {{- range $lines }}
+ {{ . }}
+ {{- end }}
+
+ {{- end }}
+
+ {{- end }}
+
+formatter: "markdown document" # this is required
+version: ""
+
+recursive:
+ enabled: false
+ path: modules
+
+sections:
+ hide: []
+ show: []
+
+sort:
+ enabled: true
+ by: required
+
+output-values:
+ enabled: false
+ from: ''
+
+output:
+ file: README.md
+ mode: inject
+ template: |-
+
+ {{ .Content }}
+
+
+settings:
+ anchor: true
+ color: true
+ default: true
+ description: true
+ escape: true
+ hide-empty: false
+ html: true
+ indent: 2
+ lockfile: false
+ read-comments: true
+ required: true
+ sensitive: true
+ type: true
diff --git a/scripts/docs-collator/utils/io.py b/scripts/docs-collator/utils/io.py
index 407a98685..e9d033f39 100644
--- a/scripts/docs-collator/utils/io.py
+++ b/scripts/docs-collator/utils/io.py
@@ -14,14 +14,14 @@ def save_to_file(file, content):
def read_file_to_string(file):
- with open(file, 'r') as file:
+ with open(file, "r") as file:
content = file.read()
return content
def read_file_to_list_of_strings(file):
- with open(file, 'r') as file:
+ with open(file, "r") as file:
result = file.read().splitlines()
return result
@@ -37,7 +37,7 @@ def remove_dir(dir):
def get_filenames_in_dir(dir, pattern, recursive=False):
- glob_pattern = f'**/{pattern}' if recursive else pattern
+ glob_pattern = f"**/{pattern}" if recursive else pattern
return glob.glob(os.path.join(dir, glob_pattern), recursive=recursive)
diff --git a/scripts/docs-collator/utils/rendering.py b/scripts/docs-collator/utils/rendering.py
index 73abfbc5a..2feedb6c1 100644
--- a/scripts/docs-collator/utils/rendering.py
+++ b/scripts/docs-collator/utils/rendering.py
@@ -1,15 +1,16 @@
import re
+import subprocess
-TAG_REGEX = re.compile('(<)([0-9a-zA-Z._-]+)(>)', re.IGNORECASE)
-BR_REGEX = re.compile(re.escape('
'), re.IGNORECASE)
-SIDEBAR_LABEL_REGEX = re.compile('sidebar_label: .*', re.IGNORECASE)
-CUSTOM_EDIT_URL_REGEX = re.compile('custom_edit_url: .*', re.IGNORECASE)
-NAME_REGEX = re.compile('name: .*', re.IGNORECASE)
+TAG_REGEX = re.compile("(<)([0-9a-zA-Z._-]+)(>)", re.IGNORECASE)
+BR_REGEX = re.compile(re.escape("
"), re.IGNORECASE)
+SIDEBAR_LABEL_REGEX = re.compile("sidebar_label: .*", re.IGNORECASE)
+CUSTOM_EDIT_URL_REGEX = re.compile("custom_edit_url: .*", re.IGNORECASE)
+NAME_REGEX = re.compile("name: .*", re.IGNORECASE)
RELATIVE_LINK_PATTERN = r"\]\((?!http[s]?://)([^)\s]+)\)"
def fix_self_non_closing_br_tags(content):
- return BR_REGEX.sub('
', content)
+ return BR_REGEX.sub("
", content)
def fix_custom_non_self_closing_tags_in_pre(content):
@@ -17,20 +18,20 @@ def fix_custom_non_self_closing_tags_in_pre(content):
fixed_lines = []
for line in lines:
- if not line.startswith('|'):
+ if not line.startswith("|"):
fixed_lines.append(line)
continue
- groups = re.findall(r'(.*?)
', line)
+ groups = re.findall(r"(.*?)
", line)
for group in groups:
before = group
after = TAG_REGEX.sub(r"<\2>", group)
- line = line.replace(f'{before}
', f'{after}
')
+ line = line.replace(f"{before}
", f"{after}
")
fixed_lines.append(line)
- return '\n'.join(fixed_lines)
+ return "\n".join(fixed_lines)
def shift_headings(content):
@@ -40,11 +41,11 @@ def shift_headings(content):
# figuring out how much to shift headings to the right so the biggest heading is H3
for line in lines:
- if re.match(r'^#\s+', line): # we have to shift all headings by 2
+ if re.match(r"^#\s+", line): # we have to shift all headings by 2
shift_by = 2
break
- if re.match(r'^##\s+', line): # we have to shift all headings by 1
+ if re.match(r"^##\s+", line): # we have to shift all headings by 1
shift_by = 1
break
@@ -52,7 +53,7 @@ def shift_headings(content):
return content
for line in lines:
- if not line.startswith('#'): # not a heading
+ if not line.startswith("#"): # not a heading
fixed_lines.append(line)
continue
@@ -61,26 +62,80 @@ def shift_headings(content):
elif shift_by == 2:
fixed_lines.append(f"##{line}")
- return '\n'.join(fixed_lines)
+ return "\n".join(fixed_lines)
def fix_sidebar_label(content, repo, submodule_name=""):
module_name = submodule_name
if not module_name:
provider, module_name = parse_terraform_repo_name(repo.name)
- return SIDEBAR_LABEL_REGEX.sub(f'sidebar_label: {module_name}', content)
+ return SIDEBAR_LABEL_REGEX.sub(f"sidebar_label: {module_name}", content)
def fix_github_edit_url(content, repo, submodule_dir=""):
- subdir = f"/{submodule_dir}" if submodule_dir else ''
+ subdir = f"/{submodule_dir}" if submodule_dir else ""
github_edit_url = f"custom_edit_url: https://github.com/{repo.full_name}/blob/{repo.default_branch}{subdir}/README.yaml"
return CUSTOM_EDIT_URL_REGEX.sub(github_edit_url, content)
+def fix_mdx_format(content):
+ """
+ Replace all special characters outside code blocks for MDX support
+
+ Even after we re-render all terraform-docs, there are still some issues in our markdown files.
+ This function cleans up the remaining issues.
+ """
+ replacements = {
+ r"{": r"\{", # Replace curly braces with literal
+ r"}": r"\}",
+ }
+
+ in_code_block = False
+ lines = content.splitlines()
+ result = []
+ for line in lines:
+ # Check if the line starts or ends a code block
+ if line.strip().startswith("```"):
+ in_code_block = not in_code_block
+ result.append(line)
+ continue
+
+ # Perform replacements only if not in a code block
+ if not in_code_block:
+ for pattern, replacement in replacements.items():
+ line = re.sub(pattern, replacement, line)
+
+ result.append(line)
+
+ return "\n".join(result)
+
+
+def render_terraform_docs(terraform_module_path, terraform_docs_configuration):
+ """
+ Renders Terraform module documentation using terraform-docs with a provided configuration.
+ """
+ try:
+ # Command to run terraform-docs
+ command = [
+ "terraform-docs",
+ "markdown",
+ terraform_module_path,
+ "--config",
+ terraform_docs_configuration,
+ ]
+
+ # Run the command and capture the output
+ return subprocess.run(command, check=True, capture_output=True, text=True)
+
+ except subprocess.CalledProcessError as e:
+ print(f"An error occurred while running terraform-docs: {e.stderr}")
+
+
def remove_logo_from_the_bottom(content):
return content.replace(
'[](https://cpco.io/component)',
- '')
+ "",
+ )
def remove_targets_md(content):
@@ -89,24 +144,24 @@ def remove_targets_md(content):
def remove_prefix(string, prefix):
if string.startswith(prefix):
- return string[len(prefix):]
+ return string[len(prefix) :]
def rename_name(name, content):
- return NAME_REGEX.sub(f'name: {name}', content)
+ return NAME_REGEX.sub(f"name: {name}", content)
def parse_terraform_repo_name(name):
- name_items = name.split('-')
+ name_items = name.split("-")
provider = name_items[1]
- module_name = '-'.join(name_items[2:])
+ module_name = "-".join(name_items[2:])
return provider, module_name
def parse_github_action_repo_name(name):
- name_items = name.split('-')
- action_name = '-'.join(name_items[2:])
+ name_items = name.split("-")
+ action_name = "-".join(name_items[2:])
return action_name
@@ -116,20 +171,27 @@ def replace_relative_links_with_github_links(repo, content, relative_path=None):
for link in links:
# ignore links to images, anchors and emails
- if link.startswith('images/') or link.startswith('#') or link.startswith('mailto:'):
+ if (
+ link.startswith("images/")
+ or link.startswith("#")
+ or link.startswith("mailto:")
+ ):
continue
updated_link = link
# remove leading './' or '/'
- if link.startswith('/'):
- updated_link = updated_link.replace('/', '', 1)
+ if link.startswith("/"):
+ updated_link = updated_link.replace("/", "", 1)
else:
- if link.startswith('./'):
- updated_link = updated_link.replace('./', '', 1)
+ if link.startswith("./"):
+ updated_link = updated_link.replace("./", "", 1)
if relative_path:
updated_link = f"{relative_path}/{updated_link}"
- content = content.replace(f"]({link})", f"](https://github.com/{repo.full_name}/tree/{repo.default_branch}/{updated_link})")
+ content = content.replace(
+ f"]({link})",
+ f"](https://github.com/{repo.full_name}/tree/{repo.default_branch}/{updated_link})",
+ )
return content
diff --git a/scripts/render-docs-for-components.sh b/scripts/render-docs-for-components.sh
index f2c5beb09..a0eb2d7b5 100755
--- a/scripts/render-docs-for-components.sh
+++ b/scripts/render-docs-for-components.sh
@@ -6,7 +6,7 @@ GITHUB_ORG=${GITHUB_ORG:-"cloudposse"}
GITHUB_REPO=${GITHUB_REPO:-"terraform-aws-components"}
GIT_BRANCH=${GIT_BRANCH:-"main"}
TMP_CLONE_DIR="${TMP_CLONE_DIR:-tmp/components/${GITHUB_REPO}}"
-RENDERED_DOCS_DIR="${RENDERED_DOCS_DIR:-content/reference/components/library/aws/}"
+RENDERED_DOCS_DIR="${RENDERED_DOCS_DIR:-docs/components/library/aws/}"
echo "Cloning repo '${GITHUB_ORG}/${GITHUB_REPO}'"
git clone --depth 1 --branch "${GIT_BRANCH}" https://github.com/${GITHUB_ORG}/${GITHUB_REPO}.git "${TMP_CLONE_DIR}" || true
diff --git a/sidebars.js b/sidebars.js
index defc7762c..5a545d367 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -339,12 +339,12 @@ module.exports = {
collapsed: false,
link: {
type: 'doc',
- id: 'generated/components/index'
+ id: 'components/index'
},
items: [
{
type: 'autogenerated',
- dirName: 'generated/components/library',
+ dirName: 'components/library',
}
]
},
@@ -356,12 +356,12 @@ module.exports = {
collapsed: false,
link: {
type: 'doc',
- id: 'generated/modules/index'
+ id: 'modules/index'
},
items: [
{
type: 'autogenerated',
- dirName: 'generated/modules/library',
+ dirName: 'modules/library',
}
]
},
@@ -373,12 +373,12 @@ module.exports = {
collapsed: true,
link: {
type: 'doc',
- id: 'generated/github-actions/index'
+ id: 'github-actions/index'
},
items: [
{
type: 'autogenerated',
- dirName: 'generated/github-actions/library/actions',
+ dirName: 'github-actions/library/actions',
}
]
},