From 5ddaefb6ab5e5af784c31e811ce3c4c2b2360c1c Mon Sep 17 00:00:00 2001 From: stewartshea Date: Thu, 2 Jul 2026 17:09:50 -0400 Subject: [PATCH] Enhance generation rules documentation and examples - Updated `generation-rules-guide.md` to clarify platform specifications and resource type matching, including the addition of `runwhen` as a supported platform. - Improved examples in `README.md` and `generation-rules/README.md` to reflect new structures and naming conventions for SLXs. - Refactored generation rule examples to utilize the new `matchRules` syntax and clarified the use of `resourceTypes`. - Enhanced documentation for indexed resources, including updates to the Azure resource catalog and the overall structure of indexed resource references. - Added new examples demonstrating multi-resource contexts and improved clarity on related resource handling in SLXs. This update aims to provide clearer guidance for authors creating generation rules and improve the overall usability of the documentation. --- .../skills/author-generation-rules/SKILL.md | 27 + .../workflows/publish-discovery-catalog.yaml | 57 + docs/authoring/README.md | 59 +- docs/authoring/generation-rules/README.md | 222 ++-- .../generation-rules/examples/README.md | 2 +- .../examples/azure-keyvault-slx.md | 123 +- .../examples/azure-vm-disk-runbook.md | 99 +- .../examples/kubernetes-deployment-slx.md | 106 +- .../examples/multi-resource-runbook.md | 130 +- docs/authoring/indexed-resources/README.md | 64 +- .../indexed-resources/aws-resource-catalog.md | 1133 +++++++++++++++++ .../azure-resource-catalog.md | 2 +- .../indexed-resources/gcp-resource-catalog.md | 418 ++++++ .../kubernetes-resource-catalog.md | 23 + .../runwhen-platform-resource-catalog.md | 19 + .../indexed-resources/runwhen-platform.md | 51 + generation-rules-guide.md | 153 +-- scripts/aws/dump_aws_resource_catalog.py | 97 ++ scripts/docs/sync_authoring_to_docs_site.py | 350 +++++ scripts/gcp/dump_gcp_resource_catalog.py | 96 ++ .../dump_kubernetes_resource_catalog.py | 49 + .../runwhen/dump_runwhen_resource_catalog.py | 49 + src/component.py | 2 +- src/enrichers/generation_rules.py | 2 + src/enrichers/runwhen_platform.py | 54 + src/indexers/runwhen_platform.py | 54 + src/indexers/test_runwhen_platform.py | 76 ++ src/run.sh | 4 +- 28 files changed, 3036 insertions(+), 485 deletions(-) create mode 100644 .cursor/skills/author-generation-rules/SKILL.md create mode 100644 .github/workflows/publish-discovery-catalog.yaml create mode 100644 docs/authoring/indexed-resources/aws-resource-catalog.md create mode 100644 docs/authoring/indexed-resources/gcp-resource-catalog.md create mode 100644 docs/authoring/indexed-resources/kubernetes-resource-catalog.md create mode 100644 docs/authoring/indexed-resources/runwhen-platform-resource-catalog.md create mode 100644 docs/authoring/indexed-resources/runwhen-platform.md create mode 100644 scripts/aws/dump_aws_resource_catalog.py create mode 100644 scripts/docs/sync_authoring_to_docs_site.py create mode 100644 scripts/gcp/dump_gcp_resource_catalog.py create mode 100644 scripts/kubernetes/dump_kubernetes_resource_catalog.py create mode 100644 scripts/runwhen/dump_runwhen_resource_catalog.py create mode 100644 src/enrichers/runwhen_platform.py create mode 100644 src/indexers/runwhen_platform.py create mode 100644 src/indexers/test_runwhen_platform.py diff --git a/.cursor/skills/author-generation-rules/SKILL.md b/.cursor/skills/author-generation-rules/SKILL.md new file mode 100644 index 000000000..a1cb032d7 --- /dev/null +++ b/.cursor/skills/author-generation-rules/SKILL.md @@ -0,0 +1,27 @@ +--- +name: author-generation-rules +description: "Write generation rules using bundled references in this repo (airgap). Full skill body lives in runwhen-platform-mcp." +--- + +# Author Generation Rules (runwhen-local) + +Canonical sources: `docs/authoring/` and generated catalogs in this repo. + +For **airgap MCP**, use the bundled copy in `runwhen-platform-mcp`: + +`skills/author-generation-rules/references/` + +Regenerate MCP bundle (maintainers): + +```bash +cd runwhen-platform-mcp +python scripts/sync_bundled_authoring.py --runwhen-local /path/to/runwhen-local +``` + +Regenerate catalogs here first: + +```bash +python scripts/*/dump_*_resource_catalog.py +``` + +See `runwhen-platform-mcp/skills/author-generation-rules/SKILL.md` for the full workflow. diff --git a/.github/workflows/publish-discovery-catalog.yaml b/.github/workflows/publish-discovery-catalog.yaml new file mode 100644 index 000000000..8bdbc7864 --- /dev/null +++ b/.github/workflows/publish-discovery-catalog.yaml @@ -0,0 +1,57 @@ +name: Publish discovery catalogs + +on: + workflow_dispatch: + pull_request: + paths: + - "src/indexers/**" + - "src/enrichers/runwhen_platform.py" + - "scripts/**/dump_*_resource_catalog.py" + - "scripts/**/sync_*_resource_type_registry.py" + push: + branches: [main] + paths: + - "src/indexers/**" + - "src/enrichers/runwhen_platform.py" + - "scripts/**/dump_*_resource_catalog.py" + - "scripts/**/sync_*_resource_type_registry.py" + +permissions: + contents: write + +jobs: + regenerate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref || github.ref_name }} + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install PyYAML + run: pip install pyyaml + + - name: Run catalog dumpers + run: | + python scripts/azure/dump_azure_resource_catalog.py + python scripts/aws/dump_aws_resource_catalog.py + python scripts/gcp/dump_gcp_resource_catalog.py + python scripts/kubernetes/dump_kubernetes_resource_catalog.py + python scripts/runwhen/dump_runwhen_resource_catalog.py + + - name: Commit and push regenerated catalogs + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add docs/authoring/indexed-resources/*-resource-catalog.md + if git diff --staged --quiet; then + echo "Catalogs already up to date" + exit 0 + fi + git commit -m "chore(docs): regenerate discovery resource catalogs" + git push diff --git a/docs/authoring/README.md b/docs/authoring/README.md index 055768533..5722f1933 100644 --- a/docs/authoring/README.md +++ b/docs/authoring/README.md @@ -3,43 +3,52 @@ Everything you need to extend RunWhen Local: write CodeBundles, ship Skills, and teach the workspace builder how to wire them up via generation rules. +**This directory is the canonical reference.** Catalogs are generated from indexer +registries (dump scripts + `publish-discovery-catalog` GHA). + +- **MCP (airgap):** `author-generation-rules` skill reads bundled copies in + `runwhen-platform-mcp/skills/author-generation-rules/references/` (CI-synced from here) +- **docs.runwhen.com:** use `publish-author-docs-from-runwhen-local` skill in the + docs repo when ready to replace legacy `/authors/generation-rules/` pages + If you only want to *use* RunWhen Local against your own infrastructure, see the [user guide](../user-guide/README.md) instead. ## Concepts -* [CodeBundle / Skill / SLX / Runbook terminology](./concepts.md) - read this - first; the rest of the authoring docs assume you know what these mean. +* [CodeBundle / Skill / SLX / Runbook terminology](./concepts.md) ## Indexed resources Generation rules match against resources discovered by RunWhen Local's -indexers. Before you can write a rule that targets, say, an Azure App Service -or a Kubernetes Deployment, you need to know: +indexers. Before you write a rule, confirm the resource type exists and +which fields are stable enough to match on. -* Whether the indexer actually discovers that resource type today. -* What the data looks like once it's been normalized. -* Which fields are stable enough to match against. +* [Indexed resources overview](./indexed-resources/README.md) +* [Azure](./indexed-resources/azure.md) — typed vs generic tiers, match properties +* [AWS](./indexed-resources/aws.md) +* [GCP](./indexed-resources/gcp.md) +* [Kubernetes](./indexed-resources/kubernetes.md) +* [RunWhen platform](./indexed-resources/runwhen-platform.md) — `platform: runwhen` for MCP tool-builder output -Reference docs per platform: +Machine-readable catalogs (regenerate with `scripts/*/dump_*_resource_catalog.py` +or the `publish-discovery-catalog` GitHub Action — do not hand-edit): -* [Indexed resources overview](./indexed-resources/README.md) -* [Azure indexer](./indexed-resources/azure.md) - 25 typed resource types, - with the data shape your generation rules will see for each. -* [Kubernetes indexer](./indexed-resources/kubernetes.md) -* [AWS indexer](./indexed-resources/aws.md) -* [GCP indexer](./indexed-resources/gcp.md) +* [Azure catalog](./indexed-resources/azure-resource-catalog.md) +* [AWS catalog](./indexed-resources/aws-resource-catalog.md) +* [GCP catalog](./indexed-resources/gcp-resource-catalog.md) +* [Kubernetes catalog](./indexed-resources/kubernetes-resource-catalog.md) +* [RunWhen catalog](./indexed-resources/runwhen-platform-resource-catalog.md) ## Generation rules -Generation rules are the bridge between an indexed resource and a rendered -SLX. They live in CodeBundles under `.runwhen/generation-rules/`. - -* [Generation rules: schema, lifecycle, and how-to](./generation-rules/README.md) -* [Tag-hierarchy contract](./generation-rules/tag-hierarchy-contract.md) - - how SLX names are composed from the resource graph. -* Worked examples: - * [Azure VM + disk runbook](./generation-rules/examples/azure-vm-disk-runbook.md) - * [Azure Key Vault SLX](./generation-rules/examples/azure-keyvault-slx.md) - * [Kubernetes Deployment SLX](./generation-rules/examples/kubernetes-deployment-slx.md) - * [Multi-resource runbook](./generation-rules/examples/multi-resource-runbook.md) +* [Schema reference](./generation-rules/README.md) +* [Syntax reference](../../generation-rules-guide.md) (repo root) — full `matchRules` / `slxs` / `outputItems` +* [Tag-hierarchy contract](./generation-rules/tag-hierarchy-contract.md) +* [Worked examples](./generation-rules/examples/) + +## Publishing to docs.runwhen.com (later) + +Use the **`publish-author-docs-from-runwhen-local`** skill in the `runwhen/docs` +repo (runs `scripts/publish-author-docs-from-runwhen-local.py` against this tree). +Replace legacy `/authors/generation-rules/*` — do not duplicate. diff --git a/docs/authoring/generation-rules/README.md b/docs/authoring/generation-rules/README.md index 6130d6f03..df191e62a 100644 --- a/docs/authoring/generation-rules/README.md +++ b/docs/authoring/generation-rules/README.md @@ -1,138 +1,156 @@ # Generation rules -Generation rules are the bridge between an indexed resource and a rendered -SLX. Each rule is a YAML document that lives inside a CodeBundle under -`.runwhen/generation-rules/.yaml` and tells RunWhen Local: +Generation rules are YAML documents inside a CodeCollection under +`.runwhen/generation-rules/*.yaml`. They tell RunWhen Local which indexed +resources to match and which SLX templates to render for each match. -1. Which resource type to match (e.g. `azure_keyvault_keyvaults`). -2. Which subset of those resources to match (predicates over their - attributes / tags / hierarchy). -3. Which template files to render into the SLX (runbook, SLI, SLO, etc.). -4. How to name the resulting SLX. +Each file uses the **`GenerationRules`** kind (note the plural): one platform +per file, with one or more rule blocks under `spec.generationRules`. -This page is the reference; for end-to-end examples see -[examples/](./examples/). +For the full reference with match-rule operators, qualifiers, and complete +examples, see [`generation-rules-guide.md`](../../../generation-rules-guide.md) +at the repo root. Worked narratives live under [examples/](./examples/). ## Schema ```yaml # .runwhen/generation-rules/.yaml apiVersion: runwhen.com/v1 -kind: GenerationRule +kind: GenerationRules spec: - match: - resource_type: azure_keyvault_keyvaults # required - predicates: # optional, ALL must pass - - jsonpath: $.tags.environment - in: ["prod", "staging"] - - jsonpath: $.properties.publicNetworkAccess - equals: "Disabled" - - slxName: - template: "azure-keyvault-{{ resource.name }}-rotation" - # or: - # tagHierarchy: env/region/{resource.name} - # see ./tag-hierarchy-contract.md for the full hierarchy contract. - - templates: - runbook: runbook.robot.j2 - sli: sli.yaml.j2 - slo: slo.yaml.j2 - skill: SKILL.md # optional, copied verbatim if present - - context: # values exposed to the templates as `{{ ... }}` - keyVaultId: "{{ resource.id }}" - keyVaultName: "{{ resource.name }}" - resourceGroup: "{{ resource.resource_group }}" - subscription: "{{ resource.subscription_id }}" - rotationDays: 90 + platform: azure # azure | aws | gcp | kubernetes | runwhen + generationRules: + - resourceTypes: + - azure_keyvault_vaults + - resource_group + matchRules: + - type: pattern + pattern: "prod" + properties: [name] + mode: substring + - type: exists + path: "resource/tags/environment" + matchEmpty: false + slxs: + - baseName: keyvault-health + qualifiers: ["resource", "resource_group", "subscription_id"] + baseTemplateName: azure-keyvault-health + levelOfDetail: detailed + outputItems: + - type: slx + - type: sli + - type: runbook + templateName: azure-keyvault-health-taskset.yaml ``` -### `match.resource_type` +### `spec.platform` + +Selects which indexer supplies matched resources. Supported values: + +| Platform | Indexer | Typical `resourceTypes` values | +| --- | --- | --- | +| `azure` | `azureapi` | CloudQuery table names (`azure_compute_virtual_machines`, aliases like `virtual_machine`) | +| `aws` | `awsapi` | CloudQuery table names (`aws_ec2_instances`, aliases like `ec2_instance`) | +| `gcp` | `gcpapi` | CloudQuery table names (`gcp_compute_instances`, aliases like `compute_instance`) | +| `kubernetes` | `kubeapi` | Built-in kinds (`pod`, `deployment`) or CRD syntax (`buckets.storage.gcp.upbound.io`) | +| `runwhen` | `runwhen` | `workspace` (one instance per workspace-builder run; used by MCP tool-builder output) | -Must be the canonical name (or an alias) of an indexed resource type. See -[indexed-resources/](../indexed-resources/README.md) for the per-platform -catalog. Aliases are resolved by the registry, so all of -`virtual_machine`, `azure_compute_virtual_machines`, and -`azure_keyvault_vaults` resolve to the same underlying type. +See [indexed-resources/](../indexed-resources/README.md) for per-platform +narrative guides and machine-readable catalogs. -### `match.predicates` +### `resourceTypes` -Each predicate is a `(jsonpath, op, value)` triple. Supported ops: +List of resource type names to match. Names are resolved through each +platform's registry — canonical CloudQuery table names and legacy aliases +both work (for example `virtual_machine` and +`azure_compute_virtual_machines` resolve to the same Azure type). + +After discovery, confirm types and field paths in the **Workspace Explorer** +at [http://localhost:8000/explorer/](http://localhost:8000/explorer/) (not +legacy `resource-dump.yaml` on disk). + +For Kubernetes CRDs, use `plural.group[/version]` syntax as shown in +[examples/](./examples/). -| Op | Semantics | +### `matchRules` + +Predicates over matched resources. **All** rules in the list must pass +(logical AND). Supported rule types include: + +| Type | Purpose | | --- | --- | -| `equals` | Exact match (case-sensitive). | -| `not_equals` | Negation of `equals`. | -| `in` | Value is in a list. | -| `not_in` | Value is not in a list. | -| `matches` | Regex match (Python `re.search`). | -| `exists` | The path resolves to a non-`None` value. | -| `greater_than` / `less_than` | Numeric comparison. | -| `present` / `absent` | Tag-shape predicate (`tags.` is/isn't set). | +| `pattern` | Regex match on built-in properties (`name`) or paths (`resource/tags/env`) | +| `exists` | Path resolves to a non-empty value | +| `custom-variable` | Match a workspace custom variable | +| `and` / `or` / `not` | Compound logic | + +See [`generation-rules-guide.md`](../../../generation-rules-guide.md#match-rules) +for operators (`exact`, `substring`), path notation, and compound examples. -All predicates must pass for the rule to fire (logical AND). For OR / -NOT logic, write multiple rules or combine with `not_in` etc. +### `slxs` -### `slxName` +Each entry describes one SLX (or SLX family when `qualifiers` expand names) +to render for every resource that passes `matchRules`. -The SLX name has to be globally unique per workspace. Two strategies: +| Field | Required | Description | +| --- | --- | --- | +| `baseName` | yes | Stable prefix for generated SLX names | +| `baseTemplateName` | yes | Template bundle under `.runwhen/templates/` | +| `qualifiers` | no | Extra name segments (`resource`, `namespace`, `region`, …) | +| `levelOfDetail` | no | `basic` or `detailed` (platform-dependent) | +| `outputItems` | no | Which artifacts to render (`slx`, `sli`, `runbook`, …) | -* `template` - a Jinja-style string referencing the matched - `resource`. Must produce a stable, DNS-friendly slug. -* `tagHierarchy` - delegate naming to the - [tag-hierarchy contract](./tag-hierarchy-contract.md). Useful when you - want SLXs grouped by `env/team/cluster/...`. +Template files live under `.runwhen/templates/-*.yaml` +(for example `azure-keyvault-health-sli.yaml`, +`azure-keyvault-health-taskset.yaml`). Runbooks historically use the +`*-taskset.yaml` suffix. -### `templates` +If a `SKILL.md` sits at the CodeCollection root, the workspace builder +copies it into each rendered SLX directory automatically. -Paths are resolved **relative to the CodeBundle root**, not the rule -file. `runbook` is required; `sli`, `slo`, `skill` are optional. Any -template marked here is rendered with the rule's `context` plus the -matched `resource` dict. +### `outputItems` -If a `SKILL.md` (any case) sits at the CodeBundle root, the workspace -builder copies it next to the rendered SLX even if you don't list it -under `templates`. This is what makes the AI-agent-readable Skill -overlay automatic. +Controls which template artifacts are emitted for an `slxs` entry. Common +types: -### `context` +```yaml +outputItems: + - type: slx + - type: sli + - type: runbook + templateName: my-runbook-taskset.yaml # optional override +``` -A flat dict of values made available to the rendered templates. Values -can reference the matched `resource` via `{{ resource. }}`. -Good practice is to expose every ID / name / region your runbook needs -via `context`, so the runbook itself stays free of resource-store-specific -plumbing. +You can also define top-level `outputItems` on a generation rule block for +direct template rendering without going through `slxs` — see the guide for +advanced cases. ## Lifecycle -1. The workspace builder runs the indexer for each configured platform. -2. For every `(CodeBundle, generation-rule)` pair it walks the matching - resources in the resource store. -3. For each match it renders the templates into - `output/slx//`, copies any `SKILL.md`, and emits an entry - in the SLX manifest. -4. The explorer UI reads the manifest at runtime; the platform upload - path can ship the same artifacts to the connected RunWhen Platform. +1. RunWhen Local runs each configured platform indexer and stores resources. +2. For each CodeCollection, the workspace builder loads every + `.runwhen/generation-rules/*.yaml` file for the matching `platform`. +3. For each `(rule, resource)` pair where `resourceTypes` and `matchRules` + pass, it renders templates into the workspace output tree. +4. The explorer UI and platform upload path consume the resulting SLXs. ## Authoring tips -* **Match against stable fields.** ARM IDs and `resource_type` don't - change; tags and statuses do. Predicates over `properties.*` are fine, - but expect occasional flakiness if the cloud provider mutates a - status field unexpectedly. -* **Keep `context` flat.** Templates rendered with deeply nested - contexts are harder to debug than ones that read a flat keyspace. -* **Test with dry-run.** Run the workspace builder with - `--verbose` and inspect `output/` before shipping the CodeBundle. -* **One rule per "shape" of SLX.** If an SLX template only makes sense - for production resources, write a `prod-only` rule rather than a - `template if env == prod`. It's easier to read and easier to disable. +* **Pick types from the catalog.** Use the + [indexed resource catalogs](../indexed-resources/README.md) instead of + guessing CloudQuery table names. +* **Match on stable fields.** IDs and type names change less often than + status properties. +* **One rule per SLX shape.** Prefer separate rules for prod vs. non-prod + rather than conditional logic inside templates. +* **Dry-run locally.** Run the workspace builder with verbose logging and + inspect `output/` before publishing the CodeCollection. ## See also -* [Worked examples](./examples/) - four end-to-end rules. -* [Tag-hierarchy contract](./tag-hierarchy-contract.md). -* [Indexed resources](../indexed-resources/README.md) - the catalog of - matchable types. -* [Concepts](../concepts.md) - CodeBundle / Skill / SLX terminology. +* [`generation-rules-guide.md`](../../../generation-rules-guide.md) — full + syntax reference +* [Worked examples](./examples/) — end-to-end narratives +* [Tag-hierarchy contract](./tag-hierarchy-contract.md) +* [Indexed resources](../indexed-resources/README.md) — matchable type catalogs +* [Concepts](../concepts.md) — CodeCollection / Skill / SLX terminology diff --git a/docs/authoring/generation-rules/examples/README.md b/docs/authoring/generation-rules/examples/README.md index 53c161a77..4ef1a1c91 100644 --- a/docs/authoring/generation-rules/examples/README.md +++ b/docs/authoring/generation-rules/examples/README.md @@ -9,6 +9,6 @@ output. Use them as starting points for your own CodeBundles. | [Azure VM + disk runbook](./azure-vm-disk-runbook.md) | Single resource type, predicate over tags. | | [Azure Key Vault SLX](./azure-keyvault-slx.md) | Single resource type with a `SKILL.md` overlay. | | [Kubernetes Deployment SLX](./kubernetes-deployment-slx.md) | Predicates over `metadata` + `spec`, namespace-scoped. | -| [Multi-resource runbook](./multi-resource-runbook.md) | A rule that bundles several related resources into one SLX. | +| [Multi-resource context](./multi-resource-runbook.md) | Pass related ARM IDs from one matched resource into templates. | For the schema reference, see [../README.md](../README.md). diff --git a/docs/authoring/generation-rules/examples/azure-keyvault-slx.md b/docs/authoring/generation-rules/examples/azure-keyvault-slx.md index ed0b91ed5..ce330de83 100644 --- a/docs/authoring/generation-rules/examples/azure-keyvault-slx.md +++ b/docs/authoring/generation-rules/examples/azure-keyvault-slx.md @@ -6,13 +6,13 @@ AI agent. ## Matched resource -`azure_keyvault_keyvaults` with `properties.publicNetworkAccess == -"Disabled"`: +`azure_keyvault_vaults` (alias: `azure_keyvault_keyvaults`) with +`properties.publicNetworkAccess == "Disabled"`: ```yaml id: /subscriptions/abc/resourceGroups/rg-prod/providers/Microsoft.KeyVault/vaults/kv-prod-001 name: kv-prod-001 -resource_type: azure_keyvault_keyvaults +resource_type: azure_keyvault_vaults resource_group: rg-prod subscription_id: abc location: eastus @@ -31,87 +31,82 @@ properties: ``` codebundles/azure-keyvault-rotation/ -├── SKILL.md # AI-agent-readable Skill description -├── runbook.robot.j2 # rendered into each SLX -├── sli.yaml.j2 -├── slo.yaml.j2 -└── .runwhen/generation-rules/ - └── private-keyvault-rotation.yaml # the rule below +├── SKILL.md +└── .runwhen/ + ├── generation-rules/ + │ └── private-keyvault-rotation.yaml + └── templates/ + ├── azure-keyvault-rotation-slx.yaml + ├── azure-keyvault-rotation-sli.yaml + └── azure-keyvault-rotation-taskset.yaml ``` ## Generation rule ```yaml apiVersion: runwhen.com/v1 -kind: GenerationRule +kind: GenerationRules spec: - match: - resource_type: azure_keyvault_keyvaults - predicates: - - jsonpath: $.properties.publicNetworkAccess - equals: "Disabled" - - slxName: - template: "azure-keyvault-{{ resource.name }}-rotation" - - templates: - runbook: runbook.robot.j2 - sli: sli.yaml.j2 - slo: slo.yaml.j2 - # No 'skill:' line is needed - the workspace builder auto-copies - # SKILL.md from the CodeBundle root into every rendered SLX. - - context: - keyVaultName: "{{ resource.name }}" - keyVaultId: "{{ resource.id }}" - vaultUri: "{{ resource.properties.vaultUri }}" - resourceGroup: "{{ resource.resource_group }}" - subscription: "{{ resource.subscription_id }}" - rotationDays: 90 + platform: azure + generationRules: + - resourceTypes: + - azure_keyvault_vaults + matchRules: + - type: pattern + pattern: "Disabled" + properties: ["resource/properties/publicNetworkAccess"] + mode: exact + slxs: + - baseName: az-kv-rotation + qualifiers: ["resource", "resource_group", "subscription_id"] + baseTemplateName: azure-keyvault-rotation + levelOfDetail: detailed + outputItems: + - type: slx + - type: sli + - type: runbook + templateName: azure-keyvault-rotation-taskset.yaml ``` -## SKILL.md (excerpt) +Place `SKILL.md` at the CodeBundle root — the workspace builder copies it +into every rendered SLX directory automatically (no `outputItems` entry +required). -```markdown -# Azure Key Vault rotation +## Template variables -This Skill rotates secrets older than the configured threshold in a -single Azure Key Vault. It assumes the running identity has -`Microsoft.KeyVault/vaults/secrets/setSecret/action` permission on the -target vault. +In Jinja2 templates under `.runwhen/templates/`, use `match_resource` for +resource fields: -## Inputs -- `keyVaultName` (string, required) -- `vaultUri` (URL, required) -- `rotationDays` (int, default 90) - -## Side effects -- Generates new secret versions for any secret whose current version is - older than `rotationDays`. -- Old versions are kept (not purged) so a rollback path remains. +```yaml +# excerpt from azure-keyvault-rotation-taskset.yaml +spec: + configProvided: + - name: KEY_VAULT_NAME + value: {{ match_resource.name }} + - name: VAULT_URI + value: {{ match_resource.resource.properties.vaultUri }} + - name: RESOURCE_GROUP + value: {{ resource_group.name }} ``` -When the workspace builder fires this rule for `kv-prod-001` it -renders: +## Rendered output + +For `kv-prod-001` in resource group `rg-prod`: ``` -output/slx/azure-keyvault-kv-prod-001-rotation/ +output/slx/az-kv-rotation--rg-prod--kv-prod-001--/ ├── SKILL.md # auto-copied from CodeBundle root -├── runbook.robot +├── slx.yaml ├── sli.yaml -└── slo.yaml +└── taskset.yaml ``` -The explorer UI shows the `SKILL.md` next to the runbook; an MCP-aware -agent can read it as the canonical description of what the SLX *does*. +The explorer UI shows `SKILL.md` next to the runbook; MCP agents can read +it as the canonical description of what the SLX does. ## Notes -* The `publicNetworkAccess` predicate scopes the rule to private vaults - only; vaults that allow public network access get a different rule (or - no SLX at all). -* `vaultUri` is exposed in the context because the runbook uses the - data-plane URL, not the ARM ID, when calling the Key Vault REST API. -* If you also want a separate SLX for *public* vaults, write a sibling - rule with `predicates: - jsonpath: $.properties.publicNetworkAccess - not_equals: "Disabled"`. +* The `publicNetworkAccess` match scopes the rule to private vaults only. +* Use path notation (`resource/properties/...`) to match nested ARM fields. +* For public vaults, add a sibling rule with a complementary pattern or + omit the property match entirely. diff --git a/docs/authoring/generation-rules/examples/azure-vm-disk-runbook.md b/docs/authoring/generation-rules/examples/azure-vm-disk-runbook.md index 13d7f76a6..aa9e4dbe6 100644 --- a/docs/authoring/generation-rules/examples/azure-vm-disk-runbook.md +++ b/docs/authoring/generation-rules/examples/azure-vm-disk-runbook.md @@ -5,7 +5,7 @@ slow disk" runbook against its OS disk. ## Matched resource -A `azure_compute_virtual_machines` resource with `tags.environment == +An `azure_compute_virtual_machines` resource with `tags.environment == "prod"`. Example payload (trimmed): ```yaml @@ -28,72 +28,65 @@ properties: ## Generation rule -`.runwhen/generation-rules/azure-vm-disk-diagnose.yaml` inside your -CodeBundle: +`.runwhen/generation-rules/azure-vm-disk-diagnose.yaml`: ```yaml apiVersion: runwhen.com/v1 -kind: GenerationRule +kind: GenerationRules spec: - match: - resource_type: azure_compute_virtual_machines - predicates: - - jsonpath: $.tags.environment - equals: "prod" - - jsonpath: $.properties.storageProfile.osDisk.managedDisk.id - exists: true - - slxName: - template: "azure-vm-{{ resource.name }}-disk-health" - - templates: - runbook: runbook.robot.j2 - sli: sli.yaml.j2 - skill: SKILL.md - - context: - vmName: "{{ resource.name }}" - vmId: "{{ resource.id }}" - osDiskId: "{{ resource.properties.storageProfile.osDisk.managedDisk.id }}" - osDiskName: "{{ resource.properties.storageProfile.osDisk.name }}" - resourceGroup: "{{ resource.resource_group }}" - subscription: "{{ resource.subscription_id }}" + platform: azure + generationRules: + - resourceTypes: + - azure_compute_virtual_machines + matchRules: + - type: pattern + pattern: "prod" + properties: [tags] + mode: substring + - type: exists + properties: ["resource/properties/storageProfile/osDisk/managedDisk/id"] + slxs: + - baseName: az-vm-disk-hlth + qualifiers: ["resource", "resource_group", "subscription_id"] + baseTemplateName: azure-vm-disk-diagnose + levelOfDetail: detailed + outputItems: + - type: slx + - type: sli + - type: runbook + templateName: azure-vm-disk-diagnose-taskset.yaml ``` +Add `SKILL.md` at the CodeBundle root if you want MCP-readable metadata; +the workspace builder copies it into each rendered SLX directory. + ## Rendered output -For each matching VM the workspace builder produces a directory like: +For each matching VM: ``` -output/slx/azure-vm-web-01-disk-health/ -├── SKILL.md # copied verbatim from the CodeBundle root -├── runbook.robot # rendered with vmName="web-01", osDiskName="web-01-os", ... -└── sli.yaml +output/slx/az-vm-disk-hlth--rg-prod--web-01--/ +├── SKILL.md # optional, from CodeBundle root +├── slx.yaml +├── sli.yaml +└── taskset.yaml ``` -`runbook.robot.j2` can reference the context directly: +Reference disk fields in templates via `match_resource`: -```robot -*** Settings *** -Documentation Diagnose slow disk on Azure VM ${vmName}. - -*** Variables *** -${VM_ID} {{ vmId }} -${DISK_ID} {{ osDiskId }} -${RESOURCE_GROUP} {{ resourceGroup }} -${SUBSCRIPTION} {{ subscription }} - -*** Tasks *** -Check IOPS on ${osDiskName} - [Documentation] Pulls 24h of disk metrics from Azure Monitor. - ... +```yaml +spec: + configProvided: + - name: VM_NAME + value: {{ match_resource.name }} + - name: OS_DISK_ID + value: {{ match_resource.resource.properties.storageProfile.osDisk.managedDisk.id }} + - name: RESOURCE_GROUP + value: {{ resource_group.name }} ``` ## Notes -* `predicates` here include an `exists` check so we skip VMs that don't - expose a managed-disk OS disk (e.g. ephemeral OS disks). -* The `osDiskId` is enough on its own; we also expose `osDiskName` purely - for human-readable runbook headers. -* `tags.environment` is user-supplied data; if it's missing the predicate - evaluates to false and the SLX isn't generated. +* The `exists` match skips VMs without a managed OS disk (e.g. ephemeral OS). +* Tag predicates use the built-in `tags` property with `substring` mode. +* Missing `tags.environment` causes the rule not to fire for that VM. diff --git a/docs/authoring/generation-rules/examples/kubernetes-deployment-slx.md b/docs/authoring/generation-rules/examples/kubernetes-deployment-slx.md index 80ef5f4e6..cf10448a7 100644 --- a/docs/authoring/generation-rules/examples/kubernetes-deployment-slx.md +++ b/docs/authoring/generation-rules/examples/kubernetes-deployment-slx.md @@ -1,7 +1,7 @@ # Example: Kubernetes Deployment SLX Generate a "diagnose Deployment rollout" SLX for every multi-replica -Deployment in namespaces tagged for production. +Deployment outside `kube-system`. ## Matched resource @@ -29,60 +29,82 @@ status: status: "True" ``` +## CodeBundle layout + +``` +codebundles/k8s-deployment-rollout/ +└── .runwhen/ + ├── generation-rules/ + │ └── k8s-deployment-rollout.yaml + └── templates/ + ├── k8s-deployment-rollout-slx.yaml + ├── k8s-deployment-rollout-sli.yaml + └── k8s-deployment-rollout-taskset.yaml +``` + ## Generation rule ```yaml apiVersion: runwhen.com/v1 -kind: GenerationRule +kind: GenerationRules spec: - match: - resource_type: deployment - predicates: - - jsonpath: $.spec.replicas - greater_than: 1 - - jsonpath: $.metadata.labels.team - exists: true - - jsonpath: $.metadata.namespace - not_equals: "kube-system" - - slxName: - template: >- - k8s-{{ resource.subscription_id }}-{{ resource.metadata.namespace }}-{{ resource.name }}-rollout - - templates: - runbook: runbook.robot.j2 - sli: sli.yaml.j2 - - context: - cluster: "{{ resource.subscription_id }}" - namespace: "{{ resource.metadata.namespace }}" - deployment: "{{ resource.name }}" - team: "{{ resource.metadata.labels.team }}" - replicas: "{{ resource.spec.replicas }}" + platform: kubernetes + generationRules: + - resourceTypes: + - deployment + matchRules: + - type: pattern + pattern: "^(?!kube-system$).*" + properties: [namespace] + mode: exact + - type: exists + properties: ["resource/metadata/labels/team"] + - type: pattern + pattern: "^[2-9][0-9]*$" + properties: ["resource/spec/replicas"] + mode: exact + slxs: + - baseName: k8s-deploy-rollout + qualifiers: ["cluster", "namespace", "resource"] + baseTemplateName: k8s-deployment-rollout + levelOfDetail: detailed + outputItems: + - type: slx + - type: sli + - type: runbook + templateName: k8s-deployment-rollout-taskset.yaml ``` ## Rendered output -For `checkout-api` in cluster `prod-west` you get: +For `checkout-api` in cluster `prod-west`, namespace `payments`: ``` -output/slx/k8s-prod-west-payments-checkout-api-rollout/ -├── runbook.robot -└── sli.yaml +output/slx/k8s-deploy-rollout--prod-west--payments--checkout-api/ +├── slx.yaml +├── sli.yaml +└── taskset.yaml ``` -`runbook.robot.j2` then has access to `${cluster}`, `${namespace}`, -`${deployment}`, `${team}`, `${replicas}` and can shell out to `kubectl` -or call the Kubernetes API directly. +Templates access `match_resource`, `namespace`, and `cluster` directly: + +```yaml +spec: + configProvided: + - name: DEPLOYMENT + value: {{ match_resource.name }} + - name: NAMESPACE + value: {{ namespace.name }} + - name: CLUSTER + value: {{ cluster.name }} + - name: REPLICAS + value: {{ match_resource.resource.spec.replicas }} +``` ## Notes -* The `subscription_id` field on Kubernetes resources is the cluster - name; the SLX naming template includes it so you don't get name - collisions across multiple clusters. -* The `metadata.labels.team` predicate uses `exists`, which is enough - to require *any* team label without pinning to a specific value. -* A namespace's effective Level of Detail must be `BASIC` or `DETAILED` - for its Deployments to even arrive at this rule. Configure that under - `cloudConfig.kubernetes.contexts[].namespaceLevelOfDetails` - - see [Kubernetes-LOD configuration](../../../architecture/kubernetes-lod/configuration.md). +* On Kubernetes resources, `subscription_id` is the cluster name; include + `cluster` in `qualifiers` to avoid collisions across clusters. +* Namespace Level of Detail must be `basic` or `detailed` for Deployments + to be indexed — configure under + `cloudConfig.kubernetes.contexts[].namespaceLevelOfDetails`. diff --git a/docs/authoring/generation-rules/examples/multi-resource-runbook.md b/docs/authoring/generation-rules/examples/multi-resource-runbook.md index c5fc057db..d55491f8f 100644 --- a/docs/authoring/generation-rules/examples/multi-resource-runbook.md +++ b/docs/authoring/generation-rules/examples/multi-resource-runbook.md @@ -1,17 +1,16 @@ -# Example: Multi-resource runbook +# Example: Azure web app with related resource IDs -Bundle related resources into a single SLX. This pattern is useful when -the natural unit of troubleshooting spans more than one resource type. +Pass multiple ARM resource identifiers into one runbook from a **single** +matched resource. This pattern covers the common case where troubleshooting +one resource requires IDs that are already present on its payload (here, the +App Service plan ID embedded in the web app). -The setup: an Azure App Service web app + its server farm (App Service -plan) + the Application Gateway in front of it. We want one SLX per web -app that pulls all three IDs into the runbook context. +For SLX-to-SLX graph relationships across separate generation rules, use +map customization rules in your workspace `workspaceInfo.yaml`. ## Matched resource -The "primary" resource for the rule is `azure_appservice_web_apps`. The -related App Service plan and Application Gateway are looked up via -`relatedResources` (resolved at generation time): +The primary resource is `azure_appservice_web_apps`: ```yaml id: /subscriptions/abc/resourceGroups/rg-prod/providers/Microsoft.Web/sites/checkout-api @@ -32,78 +31,67 @@ tags: ```yaml apiVersion: runwhen.com/v1 -kind: GenerationRule +kind: GenerationRules spec: - match: - resource_type: azure_appservice_web_apps - predicates: - - jsonpath: $.tags.environment - equals: "prod" - - relatedResources: - plan: - resource_type: azure_appservice_plans - where: - # Match the plan whose ARM ID equals this web app's serverFarmId. - idEquals: "{{ resource.properties.serverFarmId }}" - appGateway: - resource_type: azure_network_application_gateways - where: - # Match the appgw whose name matches the 'appgw' tag on the web app. - nameEquals: "{{ resource.tags.appgw }}" + platform: azure + generationRules: + - resourceTypes: + - azure_appservice_web_apps + matchRules: + - type: pattern + pattern: "prod" + properties: [tags] + mode: substring + slxs: + - baseName: az-web-e2e + qualifiers: ["resource", "resource_group", "subscription_id"] + baseTemplateName: azure-web-e2e + levelOfDetail: detailed + outputItems: + - type: slx + - type: sli + - type: runbook + templateName: azure-web-e2e-taskset.yaml +``` - slxName: - template: "azure-webapp-{{ resource.name }}-end-to-end" +## Template: expose related IDs from the primary resource - templates: - runbook: runbook.robot.j2 - sli: sli.yaml.j2 +The runbook receives plan and hostname data from `match_resource` — no +separate lookup step is required: - context: - webAppName: "{{ resource.name }}" - webAppId: "{{ resource.id }}" - hostName: "{{ resource.properties.hostNames[0] }}" - serverFarmId: "{{ resource.properties.serverFarmId }}" - serverFarmName: "{{ related.plan.name }}" - appGatewayId: "{{ related.appGateway.id }}" - appGatewayName: "{{ related.appGateway.name }}" - resourceGroup: "{{ resource.resource_group }}" - subscription: "{{ resource.subscription_id }}" +```yaml +# excerpt from azure-web-e2e-taskset.yaml +spec: + configProvided: + - name: WEB_APP_NAME + value: {{ match_resource.name }} + - name: HOST_NAME + value: {{ match_resource.resource.properties.hostNames[0] }} + - name: SERVER_FARM_ID + value: {{ match_resource.resource.properties.serverFarmId }} + - name: APPGW_TAG + value: {{ match_resource.resource.tags.appgw }} + - name: RESOURCE_GROUP + value: {{ resource_group.name }} ``` +The runbook can then call Azure CLI with `--ids ${SERVER_FARM_ID}`, curl +`${HOST_NAME}`, or look up an Application Gateway by name from +`${APPGW_TAG}`. + ## Rendered output ``` -output/slx/azure-webapp-checkout-api-end-to-end/ -├── runbook.robot -└── sli.yaml -``` - -The runbook can now perform multi-step diagnosis: - -```robot -*** Tasks *** -Check Application Gateway Health - Run az network application-gateway show-backend-health - ... --ids ${appGatewayId} - -Check Web App Availability - Run curl -sS https://${hostName}/health - -Check Server Farm Capacity - Run az appservice plan show --ids ${serverFarmId} +output/slx/az-web-e2e--rg-prod--checkout-api--/ +├── slx.yaml +├── sli.yaml +└── taskset.yaml ``` ## Notes -* `relatedResources` is a separate top-level field from `match`. The - rule fires once per *matched primary*, with each related resource - bound under `related.` for the templates. -* If a related resource isn't found (no matching plan, no matching - appgw), the rule still fires, but the corresponding `related.*` - values are empty. Templates should defensively handle missing related - resources or the rule should add a stricter `predicates` block. -* Cross-resource predicates (e.g. "fire only when *both* the web app - and its appgw have `environment: prod`") are best expressed by - predicates on the primary plus a `where` clause that filters the - related lookup. +* When you need **separate SLXs per resource type** (web app + plan + + gateway), write one generation rule per `resourceTypes` entry and link them + in the workspace map with customization rules. +* Tags like `appgw` are user-supplied; document expected tag shapes in your + CodeBundle README or `SKILL.md`. diff --git a/docs/authoring/indexed-resources/README.md b/docs/authoring/indexed-resources/README.md index 9868edc87..3fd26c889 100644 --- a/docs/authoring/indexed-resources/README.md +++ b/docs/authoring/indexed-resources/README.md @@ -1,55 +1,15 @@ -# Indexed resources +# Indexed resource catalogs -Generation rules can only match against resources that an indexer has -actually written to the resource store. This section is the authoritative -reference for what each indexer discovers and the data shape that arrives -in your generation rules. +Agent- and author-facing lookup tables for generation-rule `resourceTypes` and +`match_resource.*` properties. -## Per-platform reference +| Platform | Narrative guide | Machine catalog | +|---|---|---| +| Kubernetes | [kubernetes.md](./kubernetes.md) | [kubernetes-resource-catalog.md](./kubernetes-resource-catalog.md) | +| Azure | [azure.md](./azure.md) | [azure-resource-catalog.md](./azure-resource-catalog.md) | +| GCP | [gcp.md](./gcp.md) | [gcp-resource-catalog.md](./gcp-resource-catalog.md) | +| AWS | [aws.md](./aws.md) | [aws-resource-catalog.md](./aws-resource-catalog.md) | +| RunWhen | [runwhen-platform.md](./runwhen-platform.md) | [runwhen-platform-resource-catalog.md](./runwhen-platform-resource-catalog.md) | -* [Azure](./azure.md) - native `azure-mgmt-*` SDK indexer (`azureapi`). - Full parity with the legacy CloudQuery Azure plugin: 619 indexable - resource types, 25 typed (rich-payload) plus 594 generic (basic - envelope). Sortable catalog at - [azure-resource-catalog.md](./azure-resource-catalog.md). -* [Kubernetes](./kubernetes.md) - in-cluster scan via the Kubernetes Python - client, plus per-namespace LOD support. -* [AWS](./aws.md) - CloudQuery-backed indexer. -* [GCP](./gcp.md) - CloudQuery-backed indexer. - -## Common resource shape - -Every discovered resource lands in the resource store as a normalized dict -with at least: - -| Field | Type | Notes | -| --- | --- | --- | -| `id` | string | The platform's canonical resource ID (ARM ID for Azure, ARN for AWS, `/api/v1/.../` for Kubernetes, etc.). | -| `name` | string | Human-friendly name. | -| `resource_type` | string | RunWhen Local's canonical type name. Use this in generation rule `match.resource_type`. | -| `subscription_id` / `account_id` / `project_id` | string | Cloud account scope. Always set for cloud platforms. | -| `tags` | dict | Always a dict, may be empty. Cloud-platform user tags. | -| `properties` | dict | Platform-specific payload (preserved verbatim). | - -Indexer-specific fields layer on top of those common ones; per-platform -docs spell out the extras and give example payloads. - -## Selective vs unbounded discovery - -All indexers honor the `defaultLOD` / `resourceGroupLevelOfDetails` -contract from `workspaceInfo.yaml`: - -* `defaultLOD: detailed` (and any non-`none` value) means **unbounded - discovery** - the indexer enumerates the whole subscription / account / - cluster. -* `defaultLOD: none` plus a finite list of "keep this" entries means - **selective discovery** - the indexer scopes its API calls to exactly - those resource groups / namespaces. - -When you're authoring generation rules in a CodeBundle, you don't usually -have to think about this; you just match resources. But it does affect -*which* resources show up at runtime. See the user-facing -[level-of-detail guide](../../user-guide/configuration/level-of-detail.md) -and the architecture-level -[Kubernetes-LOD internals](../../architecture/kubernetes-lod/README.md) for -the full mechanics. +Regenerate catalogs with the dump scripts under `scripts/` or via the +`publish-discovery-catalog` GitHub Action. diff --git a/docs/authoring/indexed-resources/aws-resource-catalog.md b/docs/authoring/indexed-resources/aws-resource-catalog.md new file mode 100644 index 000000000..15a8f9be7 --- /dev/null +++ b/docs/authoring/indexed-resources/aws-resource-catalog.md @@ -0,0 +1,1133 @@ +# AWS resource catalog + +Every AWS resource type the native `awsapi` indexer can discover. This page is the companion catalog for [`aws.md`](./aws.md); see that page for how to enable the indexer, what data each row carries, and the typed/generic distinction. + +_1119 resource types - 3 typed (rich-payload), 1116 generic (Cloud Control envelope). Generated 2026-07-02 from `src/indexers/aws_resource_type_registry.yaml`._ + +_Regenerate with `python scripts/aws/dump_aws_resource_catalog.py` after touching the registry or overrides; do not hand-edit this file._ + +* `typed` - hand-written `boto3` collector returns a richer payload. +* `generic` - covered by the Cloud Control API catch-all when a CloudFormation type exists; rows without a CFN type are registry-only and skipped by generic discovery. + +| Service | CloudQuery table name | CFN type | Tier | +| --- | --- | --- | --- | +| accessanalyzer | `aws_accessanalyzer_analyzer_archive_rules` | `AWS::AccessAnalyzer::AnalyzerArchiveRule` | generic | +| accessanalyzer | `aws_accessanalyzer_analyzer_findings` | `AWS::AccessAnalyzer::AnalyzerFinding` | generic | +| accessanalyzer | `aws_accessanalyzer_analyzer_findings_v2` | `AWS::AccessAnalyzer::AnalyzerFindingsV2` | generic | +| accessanalyzer | `aws_accessanalyzer_analyzers` | `AWS::AccessAnalyzer::Analyzer` | generic | +| account | `aws_account_alternate_contacts` | `AWS::Account::AlternateContact` | generic | +| account | `aws_account_contacts` | `AWS::Account::Contact` | generic | +| acm | `aws_acm_certificates` | `AWS::CertificateManager::Certificate` | generic | +| acmpca | `aws_acmpca_certificate_authorities` | `AWS::ACMPCA::CertificateAuthority` | generic | +| amp | `aws_amp_rule_groups_namespaces` | `AWS::APS::RuleGroupsNamespace` | generic | +| amp | `aws_amp_workspaces` | `AWS::APS::Workspace` | generic | +| amplify | `aws_amplify_apps` | `AWS::Amplify::App` | generic | +| apigateway | `aws_apigateway_accounts` | `AWS::ApiGateway::Account` | generic | +| apigateway | `aws_apigateway_api_keys` | `AWS::ApiGateway::ApiKey` | generic | +| apigateway | `aws_apigateway_client_certificates` | `AWS::ApiGateway::ClientCertificate` | generic | +| apigateway | `aws_apigateway_domain_name_base_path_mappings` | `AWS::ApiGateway::DomainNameBasePathMapping` | generic | +| apigateway | `aws_apigateway_domain_names` | `AWS::ApiGateway::DomainName` | generic | +| apigateway | `aws_apigateway_rest_api_authorizers` | `AWS::ApiGateway::RestApiAuthorizer` | generic | +| apigateway | `aws_apigateway_rest_api_deployments` | `AWS::ApiGateway::RestApiDeployment` | generic | +| apigateway | `aws_apigateway_rest_api_documentation_parts` | `AWS::ApiGateway::RestApiDocumentationPart` | generic | +| apigateway | `aws_apigateway_rest_api_documentation_versions` | `AWS::ApiGateway::RestApiDocumentationVersion` | generic | +| apigateway | `aws_apigateway_rest_api_gateway_responses` | `AWS::ApiGateway::RestApiGatewayRespons` | generic | +| apigateway | `aws_apigateway_rest_api_models` | `AWS::ApiGateway::RestApiModel` | generic | +| apigateway | `aws_apigateway_rest_api_request_validators` | `AWS::ApiGateway::RestApiRequestValidator` | generic | +| apigateway | `aws_apigateway_rest_api_resource_method_integrations` | `AWS::ApiGateway::RestApiResourceMethodIntegration` | generic | +| apigateway | `aws_apigateway_rest_api_resource_methods` | `AWS::ApiGateway::RestApiResourceMethod` | generic | +| apigateway | `aws_apigateway_rest_api_resources` | `AWS::ApiGateway::RestApiResource` | generic | +| apigateway | `aws_apigateway_rest_api_stages` | `AWS::ApiGateway::RestApiStage` | generic | +| apigateway | `aws_apigateway_rest_apis` | `AWS::ApiGateway::RestApi` | generic | +| apigateway | `aws_apigateway_usage_plan_keys` | `AWS::ApiGateway::UsagePlanKey` | generic | +| apigateway | `aws_apigateway_usage_plans` | `AWS::ApiGateway::UsagePlan` | generic | +| apigateway | `aws_apigateway_vpc_links` | `AWS::ApiGateway::VpcLink` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_authorizers` | `AWS::ApiGatewayV2::ApiAuthorizer` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_deployments` | `AWS::ApiGatewayV2::ApiDeployment` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_integration_responses` | `AWS::ApiGatewayV2::ApiIntegrationRespons` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_integrations` | `AWS::ApiGatewayV2::ApiIntegration` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_models` | `AWS::ApiGatewayV2::ApiModel` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_route_responses` | `AWS::ApiGatewayV2::ApiRouteRespons` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_routes` | `AWS::ApiGatewayV2::ApiRoute` | generic | +| apigatewayv2 | `aws_apigatewayv2_api_stages` | `AWS::ApiGatewayV2::ApiStage` | generic | +| apigatewayv2 | `aws_apigatewayv2_apis` | `AWS::ApiGatewayV2::Api` | generic | +| apigatewayv2 | `aws_apigatewayv2_domain_name_rest_api_mappings` | `AWS::ApiGatewayV2::DomainNameRestApiMapping` | generic | +| apigatewayv2 | `aws_apigatewayv2_domain_names` | `AWS::ApiGatewayV2::DomainName` | generic | +| apigatewayv2 | `aws_apigatewayv2_vpc_links` | `AWS::ApiGatewayV2::VpcLink` | generic | +| appconfig | `aws_appconfig_applications` | `AWS::AppConfig::Application` | generic | +| appconfig | `aws_appconfig_configuration_profiles` | `AWS::AppConfig::ConfigurationProfile` | generic | +| appconfig | `aws_appconfig_deployment_strategies` | `AWS::AppConfig::DeploymentStrategy` | generic | +| appconfig | `aws_appconfig_environments` | `AWS::AppConfig::Environment` | generic | +| appconfig | `aws_appconfig_hosted_configuration_versions` | `AWS::AppConfig::HostedConfigurationVersion` | generic | +| appflow | `aws_appflow_flows` | `AWS::AppFlow::Flow` | generic | +| applicationautoscaling | `aws_applicationautoscaling_policies` | `AWS::ApplicationAutoScaling::Policy` | generic | +| applicationautoscaling | `aws_applicationautoscaling_scalable_targets` | `AWS::ApplicationAutoScaling::ScalableTarget` | generic | +| applicationautoscaling | `aws_applicationautoscaling_scaling_activities` | `AWS::ApplicationAutoScaling::ScalingActivity` | generic | +| applicationautoscaling | `aws_applicationautoscaling_scheduled_actions` | `AWS::ApplicationAutoScaling::ScheduledAction` | generic | +| appmesh | `aws_appmesh_meshes` | `AWS::AppMesh::Mesh` | generic | +| appmesh | `aws_appmesh_virtual_gateways` | `AWS::AppMesh::VirtualGateway` | generic | +| appmesh | `aws_appmesh_virtual_nodes` | `AWS::AppMesh::VirtualNode` | generic | +| appmesh | `aws_appmesh_virtual_routers` | `AWS::AppMesh::VirtualRouter` | generic | +| appmesh | `aws_appmesh_virtual_services` | `AWS::AppMesh::VirtualService` | generic | +| apprunner | `aws_apprunner_auto_scaling_configurations` | `AWS::AppRunner::AutoScalingConfiguration` | generic | +| apprunner | `aws_apprunner_connections` | `AWS::AppRunner::Connection` | generic | +| apprunner | `aws_apprunner_custom_domains` | `AWS::AppRunner::CustomDomain` | generic | +| apprunner | `aws_apprunner_observability_configurations` | `AWS::AppRunner::ObservabilityConfiguration` | generic | +| apprunner | `aws_apprunner_operations` | `AWS::AppRunner::Operation` | generic | +| apprunner | `aws_apprunner_services` | `AWS::AppRunner::Service` | generic | +| apprunner | `aws_apprunner_vpc_connectors` | `AWS::AppRunner::VpcConnector` | generic | +| apprunner | `aws_apprunner_vpc_ingress_connections` | `AWS::AppRunner::VpcIngressConnection` | generic | +| appstream | `aws_appstream_app_blocks` | `AWS::AppStream::AppBlock` | generic | +| appstream | `aws_appstream_application_fleet_associations` | `AWS::AppStream::ApplicationFleetAssociation` | generic | +| appstream | `aws_appstream_applications` | `AWS::AppStream::Application` | generic | +| appstream | `aws_appstream_directory_configs` | `AWS::AppStream::DirectoryConfig` | generic | +| appstream | `aws_appstream_fleets` | `AWS::AppStream::Fleet` | generic | +| appstream | `aws_appstream_image_builders` | `AWS::AppStream::ImageBuilder` | generic | +| appstream | `aws_appstream_images` | `AWS::AppStream::Image` | generic | +| appstream | `aws_appstream_stack_entitlements` | `AWS::AppStream::StackEntitlement` | generic | +| appstream | `aws_appstream_stack_user_associations` | `AWS::AppStream::StackUserAssociation` | generic | +| appstream | `aws_appstream_stacks` | `AWS::AppStream::Stack` | generic | +| appstream | `aws_appstream_usage_report_subscriptions` | `AWS::AppStream::UsageReportSubscription` | generic | +| appstream | `aws_appstream_users` | `AWS::AppStream::User` | generic | +| appsync | `aws_appsync_graphql_apis` | `AWS::AppSync::GraphqlApi` | generic | +| athena | `aws_athena_data_catalog_database_tables` | `AWS::Athena::DataCatalogDatabaseTable` | generic | +| athena | `aws_athena_data_catalog_databases` | `AWS::Athena::DataCatalogDatabas` | generic | +| athena | `aws_athena_data_catalogs` | `AWS::Athena::DataCatalog` | generic | +| athena | `aws_athena_work_group_named_queries` | `AWS::Athena::WorkGroupNamedQuery` | generic | +| athena | `aws_athena_work_group_prepared_statements` | `AWS::Athena::WorkGroupPreparedStatement` | generic | +| athena | `aws_athena_work_group_query_executions` | `AWS::Athena::WorkGroupQueryExecution` | generic | +| athena | `aws_athena_work_groups` | `AWS::Athena::WorkGroup` | generic | +| auditmanager | `aws_auditmanager_assessments` | `AWS::AuditManager::Assessment` | generic | +| autoscaling | `aws_autoscaling_group_lifecycle_hooks` | `AWS::AutoScaling::GroupLifecycleHook` | generic | +| autoscaling | `aws_autoscaling_group_scaling_policies` | `AWS::AutoScaling::GroupScalingPolicy` | generic | +| autoscaling | `aws_autoscaling_groups` | `AWS::AutoScaling::AutoScalingGroup` | generic | +| autoscaling | `aws_autoscaling_launch_configurations` | `AWS::AutoScaling::LaunchConfiguration` | generic | +| autoscaling | `aws_autoscaling_plan_resources` | `AWS::AutoScaling::PlanResource` | generic | +| autoscaling | `aws_autoscaling_plans` | `AWS::AutoScaling::Plan` | generic | +| autoscaling | `aws_autoscaling_scheduled_actions` | `AWS::AutoScaling::ScheduledAction` | generic | +| autoscaling | `aws_autoscaling_warm_pools` | `AWS::AutoScaling::WarmPool` | generic | +| availability | `aws_availability_zones` | `-` | generic | +| backup | `aws_backup_frameworks` | `AWS::Backup::Framework` | generic | +| backup | `aws_backup_global_settings` | `AWS::Backup::GlobalSetting` | generic | +| backup | `aws_backup_jobs` | `AWS::Backup::Job` | generic | +| backup | `aws_backup_plan_selections` | `AWS::Backup::PlanSelection` | generic | +| backup | `aws_backup_plans` | `AWS::Backup::BackupPlan` | generic | +| backup | `aws_backup_protected_resources` | `AWS::Backup::ProtectedResource` | generic | +| backup | `aws_backup_region_settings` | `AWS::Backup::RegionSetting` | generic | +| backup | `aws_backup_report_plans` | `AWS::Backup::ReportPlan` | generic | +| backup | `aws_backup_restore_testing_plans` | `AWS::Backup::RestoreTestingPlan` | generic | +| backup | `aws_backup_restore_testing_selections` | `AWS::Backup::RestoreTestingSelection` | generic | +| backup | `aws_backup_tiering_configurations` | `AWS::Backup::TieringConfiguration` | generic | +| backup | `aws_backup_vault_recovery_points` | `AWS::Backup::VaultRecoveryPoint` | generic | +| backup | `aws_backup_vaults` | `AWS::Backup::BackupVault` | generic | +| backupgateway | `aws_backupgateway_gateways` | `AWS::BackupGateway::Gateway` | generic | +| batch | `aws_batch_compute_environments` | `AWS::Batch::ComputeEnvironment` | generic | +| batch | `aws_batch_job_definitions` | `AWS::Batch::JobDefinition` | generic | +| batch | `aws_batch_job_queues` | `AWS::Batch::JobQueue` | generic | +| batch | `aws_batch_jobs` | `AWS::Batch::Job` | generic | +| bedrock | `aws_bedrock_agent_versions` | `AWS::Bedrock::AgentVersion` | generic | +| bedrock | `aws_bedrock_agents` | `AWS::Bedrock::Agent` | generic | +| bedrock | `aws_bedrock_custom_models` | `AWS::Bedrock::CustomModel` | generic | +| bedrock | `aws_bedrock_evaluation_jobs` | `AWS::Bedrock::EvaluationJob` | generic | +| bedrock | `aws_bedrock_foundation_models` | `AWS::Bedrock::FoundationModel` | generic | +| bedrock | `aws_bedrock_guardrails` | `AWS::Bedrock::Guardrail` | generic | +| bedrock | `aws_bedrock_inference_profiles` | `AWS::Bedrock::InferenceProfile` | generic | +| bedrock | `aws_bedrock_model_copy_jobs` | `AWS::Bedrock::ModelCopyJob` | generic | +| bedrock | `aws_bedrock_model_customization_jobs` | `AWS::Bedrock::ModelCustomizationJob` | generic | +| bedrock | `aws_bedrock_provisioned_model_throughputs` | `AWS::Bedrock::ProvisionedModelThroughput` | generic | +| budgets | `aws_budgets_actions` | `AWS::Budgets::Action` | generic | +| budgets | `aws_budgets_budgets` | `AWS::Budgets::Budget` | generic | +| cloudformation | `aws_cloudformation_stack_instance_resource_drifts` | `AWS::CloudFormation::StackInstanceResourceDrift` | generic | +| cloudformation | `aws_cloudformation_stack_instance_summaries` | `AWS::CloudFormation::StackInstanceSummary` | generic | +| cloudformation | `aws_cloudformation_stack_resources` | `AWS::CloudFormation::StackResource` | generic | +| cloudformation | `aws_cloudformation_stack_set_operation_results` | `AWS::CloudFormation::StackSetOperationResult` | generic | +| cloudformation | `aws_cloudformation_stack_set_operations` | `AWS::CloudFormation::StackSetOperation` | generic | +| cloudformation | `aws_cloudformation_stack_sets` | `AWS::CloudFormation::StackSet` | generic | +| cloudformation | `aws_cloudformation_stack_templates` | `AWS::CloudFormation::StackTemplate` | generic | +| cloudformation | `aws_cloudformation_stacks` | `AWS::CloudFormation::Stack` | generic | +| cloudformation | `aws_cloudformation_template_summaries` | `AWS::CloudFormation::TemplateSummary` | generic | +| cloudfront | `aws_cloudfront_cache_policies` | `AWS::CloudFront::CachePolicy` | generic | +| cloudfront | `aws_cloudfront_distributions` | `AWS::CloudFront::Distribution` | generic | +| cloudfront | `aws_cloudfront_functions` | `AWS::CloudFront::Function` | generic | +| cloudfront | `aws_cloudfront_key_value_stores` | `AWS::CloudFront::KeyValueStore` | generic | +| cloudfront | `aws_cloudfront_origin_access_identities` | `AWS::CloudFront::OriginAccessIdentity` | generic | +| cloudfront | `aws_cloudfront_origin_request_policies` | `AWS::CloudFront::OriginRequestPolicy` | generic | +| cloudfront | `aws_cloudfront_response_headers_policies` | `AWS::CloudFront::ResponseHeadersPolicy` | generic | +| cloudhsmv2 | `aws_cloudhsmv2_backups` | `AWS::CloudHSM::Backup` | generic | +| cloudhsmv2 | `aws_cloudhsmv2_clusters` | `AWS::CloudHSM::Cluster` | generic | +| cloudtrail | `aws_cloudtrail_channels` | `AWS::CloudTrail::Channel` | generic | +| cloudtrail | `aws_cloudtrail_events` | `AWS::CloudTrail::Event` | generic | +| cloudtrail | `aws_cloudtrail_imports` | `AWS::CloudTrail::Import` | generic | +| cloudtrail | `aws_cloudtrail_trail_event_selectors` | `AWS::CloudTrail::TrailEventSelector` | generic | +| cloudtrail | `aws_cloudtrail_trails` | `AWS::CloudTrail::Trail` | generic | +| cloudwatch | `aws_cloudwatch_alarms` | `AWS::CloudWatch::Alarm` | generic | +| cloudwatch | `aws_cloudwatch_metric_data` | `-` | generic | +| cloudwatch | `aws_cloudwatch_metric_statistics` | `-` | generic | +| cloudwatch | `aws_cloudwatch_metric_streams` | `AWS::CloudWatch::MetricStream` | generic | +| cloudwatch | `aws_cloudwatch_metrics` | `-` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_deliveries` | `AWS::Logs::Delivery` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_delivery_destinations` | `AWS::Logs::DeliveryDestination` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_delivery_sources` | `AWS::Logs::DeliverySource` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_log_group_data_protection_policies` | `AWS::Logs::LogGroupDataProtectionPolicy` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_log_group_subscription_filters` | `AWS::Logs::LogGroupSubscriptionFilter` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_log_groups` | `AWS::Logs::LogGroup` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_log_streams` | `AWS::Logs::LogStream` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_metric_filters` | `AWS::Logs::MetricFilter` | generic | +| cloudwatchlogs | `aws_cloudwatchlogs_resource_policies` | `AWS::Logs::ResourcePolicy` | generic | +| codeartifact | `aws_codeartifact_domains` | `AWS::CodeArtifact::Domain` | generic | +| codeartifact | `aws_codeartifact_repositories` | `AWS::CodeArtifact::Repository` | generic | +| codebuild | `aws_codebuild_builds` | `AWS::CodeBuild::Build` | generic | +| codebuild | `aws_codebuild_projects` | `AWS::CodeBuild::Project` | generic | +| codebuild | `aws_codebuild_source_credentials` | `AWS::CodeBuild::SourceCredential` | generic | +| codecommit | `aws_codecommit_repositories` | `AWS::CodeCommit::Repository` | generic | +| codedeploy | `aws_codedeploy_applications` | `AWS::CodeDeploy::Application` | generic | +| codedeploy | `aws_codedeploy_deployment_configs` | `AWS::CodeDeploy::DeploymentConfig` | generic | +| codedeploy | `aws_codedeploy_deployment_groups` | `AWS::CodeDeploy::DeploymentGroup` | generic | +| codedeploy | `aws_codedeploy_deployments` | `AWS::CodeDeploy::Deployment` | generic | +| codegurureviewer | `aws_codegurureviewer_repository_associations` | `AWS::CodeGuruReviewer::RepositoryAssociation` | generic | +| codepipeline | `aws_codepipeline_pipelines` | `AWS::CodePipeline::Pipeline` | generic | +| codepipeline | `aws_codepipeline_webhooks` | `AWS::CodePipeline::Webhook` | generic | +| codestar | `aws_codestar_connections_managed` | `AWS::CodeStarConnections::ConnectionsManaged` | generic | +| cognito | `aws_cognito_identity_pools` | `AWS::Cognito::IdentityPool` | generic | +| cognito | `aws_cognito_user_pool_identity_providers` | `AWS::Cognito::UserPoolIdentityProvider` | generic | +| cognito | `aws_cognito_user_pools` | `AWS::Cognito::UserPool` | generic | +| comprehend | `aws_comprehend_document_classification_jobs` | `AWS::Comprehend::DocumentClassificationJob` | generic | +| comprehend | `aws_comprehend_document_classifiers` | `AWS::Comprehend::DocumentClassifier` | generic | +| comprehend | `aws_comprehend_dominant_language_detection_jobs` | `AWS::Comprehend::DominantLanguageDetectionJob` | generic | +| comprehend | `aws_comprehend_endpoints` | `AWS::Comprehend::Endpoint` | generic | +| comprehend | `aws_comprehend_entities_detection_jobs` | `AWS::Comprehend::EntitiesDetectionJob` | generic | +| comprehend | `aws_comprehend_entity_recognizers` | `AWS::Comprehend::EntityRecognizer` | generic | +| comprehend | `aws_comprehend_events_detection_jobs` | `AWS::Comprehend::EventsDetectionJob` | generic | +| comprehend | `aws_comprehend_flywheel_datasets` | `AWS::Comprehend::FlywheelDataset` | generic | +| comprehend | `aws_comprehend_flywheel_iteration_histories` | `AWS::Comprehend::FlywheelIterationHistory` | generic | +| comprehend | `aws_comprehend_flywheels` | `AWS::Comprehend::Flywheel` | generic | +| comprehend | `aws_comprehend_keyphrases_detection_jobs` | `AWS::Comprehend::KeyphrasesDetectionJob` | generic | +| comprehend | `aws_comprehend_pii_entities_etection_jobs` | `AWS::Comprehend::PiiEntitiesEtectionJob` | generic | +| comprehend | `aws_comprehend_sentiment_detection_jobs` | `AWS::Comprehend::SentimentDetectionJob` | generic | +| comprehend | `aws_comprehend_targeted_sentiment_detection_jobs` | `AWS::Comprehend::TargetedSentimentDetectionJob` | generic | +| comprehend | `aws_comprehend_topics_detection_jobs` | `AWS::Comprehend::TopicsDetectionJob` | generic | +| computeoptimizer | `aws_computeoptimizer_autoscaling_group_recommendations` | `AWS::Computeoptimizer::AutoscalingGroupRecommendation` | generic | +| computeoptimizer | `aws_computeoptimizer_ebs_volume_recommendations` | `AWS::Computeoptimizer::EbsVolumeRecommendation` | generic | +| computeoptimizer | `aws_computeoptimizer_ec2_instance_recommendations` | `AWS::Computeoptimizer::Ec2InstanceRecommendation` | generic | +| computeoptimizer | `aws_computeoptimizer_ecs_service_recommendations` | `AWS::Computeoptimizer::EcsServiceRecommendation` | generic | +| computeoptimizer | `aws_computeoptimizer_enrollment_statuses` | `AWS::Computeoptimizer::EnrollmentStatus` | generic | +| computeoptimizer | `aws_computeoptimizer_lambda_function_recommendations` | `AWS::Computeoptimizer::LambdaFunctionRecommendation` | generic | +| computeoptimizer | `aws_computeoptimizer_rds_database_recommendations` | `AWS::Computeoptimizer::RdsDatabaseRecommendation` | generic | +| computeoptimizerautomation | `aws_computeoptimizerautomation_accounts` | `AWS::Computeoptimizerautomation::Account` | generic | +| config | `aws_config_config_rule_compliance_details` | `AWS::Config::ConfigRuleComplianceDetail` | generic | +| config | `aws_config_config_rule_compliances` | `AWS::Config::ConfigRuleCompliance` | generic | +| config | `aws_config_config_rules` | `AWS::Config::ConfigRule` | generic | +| config | `aws_config_configuration_aggregators` | `AWS::Config::ConfigurationAggregator` | generic | +| config | `aws_config_configuration_recorders` | `AWS::Config::ConfigurationRecorder` | generic | +| config | `aws_config_conformance_pack_rule_compliances` | `AWS::Config::ConformancePackRuleCompliance` | generic | +| config | `aws_config_conformance_packs` | `AWS::Config::ConformancePack` | generic | +| config | `aws_config_delivery_channel_statuses` | `AWS::Config::DeliveryChannelStatus` | generic | +| config | `aws_config_delivery_channels` | `AWS::Config::DeliveryChannel` | generic | +| config | `aws_config_remediation_configurations` | `AWS::Config::RemediationConfiguration` | generic | +| config | `aws_config_retention_configurations` | `AWS::Config::RetentionConfiguration` | generic | +| connect | `aws_connect_agent_queues` | `AWS::Connect::AgentQueue` | generic | +| connect | `aws_connect_agent_statuses` | `AWS::Connect::AgentStatus` | generic | +| connect | `aws_connect_approved_origins` | `AWS::Connect::ApprovedOrigin` | generic | +| connect | `aws_connect_authentication_profiles` | `AWS::Connect::AuthenticationProfile` | generic | +| connect | `aws_connect_contact_evaluations` | `AWS::Connect::ContactEvaluation` | generic | +| connect | `aws_connect_contact_flow_modules` | `AWS::Connect::ContactFlowModule` | generic | +| connect | `aws_connect_contact_references` | `AWS::Connect::ContactReference` | generic | +| connect | `aws_connect_contacts` | `AWS::Connect::Contact` | generic | +| connect | `aws_connect_default_vocabularies` | `AWS::Connect::DefaultVocabulary` | generic | +| connect | `aws_connect_evaluation_form_versions` | `AWS::Connect::EvaluationFormVersion` | generic | +| connect | `aws_connect_evaluation_forms` | `AWS::Connect::EvaluationForm` | generic | +| connect | `aws_connect_flow_associations` | `AWS::Connect::FlowAssociation` | generic | +| connect | `aws_connect_hours_of_operations` | `AWS::Connect::HoursOfOperation` | generic | +| connect | `aws_connect_instance_storage_configs` | `AWS::Connect::InstanceStorageConfig` | generic | +| connect | `aws_connect_instances` | `AWS::Connect::Instance` | generic | +| connect | `aws_connect_integration_associations` | `AWS::Connect::IntegrationAssociation` | generic | +| connect | `aws_connect_lambda_functions` | `AWS::Connect::LambdaFunction` | generic | +| connect | `aws_connect_lex_bots` | `AWS::Connect::LexBot` | generic | +| connect | `aws_connect_lex_bots_v1` | `AWS::Connect::LexBotsV1` | generic | +| connect | `aws_connect_lex_bots_v2` | `AWS::Connect::LexBotsV2` | generic | +| connect | `aws_connect_lex_v1_bots` | `AWS::Connect::LexV1Bot` | generic | +| connect | `aws_connect_lex_v2_bots` | `AWS::Connect::LexV2Bot` | generic | +| connect | `aws_connect_phone_numbers` | `AWS::Connect::PhoneNumber` | generic | +| connect | `aws_connect_prompts` | `AWS::Connect::Prompt` | generic | +| connect | `aws_connect_queue_quick_connects` | `AWS::Connect::QueueQuickConnect` | generic | +| connect | `aws_connect_queues` | `AWS::Connect::Queue` | generic | +| connect | `aws_connect_quick_connects` | `AWS::Connect::QuickConnect` | generic | +| connect | `aws_connect_routing_profile_queues` | `AWS::Connect::RoutingProfileQueue` | generic | +| connect | `aws_connect_routing_profiles` | `AWS::Connect::RoutingProfile` | generic | +| connect | `aws_connect_rules` | `AWS::Connect::Rule` | generic | +| connect | `aws_connect_security_keys` | `AWS::Connect::SecurityKey` | generic | +| connect | `aws_connect_security_profiles` | `AWS::Connect::SecurityProfile` | generic | +| connect | `aws_connect_task_templates` | `AWS::Connect::TaskTemplate` | generic | +| connect | `aws_connect_traffic_distribution_group_users` | `AWS::Connect::TrafficDistributionGroupUser` | generic | +| connect | `aws_connect_traffic_distribution_groups` | `AWS::Connect::TrafficDistributionGroup` | generic | +| connect | `aws_connect_use_cases` | `AWS::Connect::UseCas` | generic | +| connect | `aws_connect_user_hierarchy_groups` | `AWS::Connect::UserHierarchyGroup` | generic | +| connect | `aws_connect_user_proficiencies` | `AWS::Connect::UserProficiency` | generic | +| connect | `aws_connect_users` | `AWS::Connect::User` | generic | +| connect | `aws_connect_view_versions` | `AWS::Connect::ViewVersion` | generic | +| connect | `aws_connect_views` | `AWS::Connect::View` | generic | +| costexplorer | `aws_costexplorer_cost_30d` | `-` | generic | +| costexplorer | `aws_costexplorer_cost_custom` | `-` | generic | +| costexplorer | `aws_costexplorer_cost_forecast_30d` | `-` | generic | +| costexplorer | `aws_costexplorer_reservation_coverages` | `-` | generic | +| costexplorer | `aws_costexplorer_reservation_utilizations` | `-` | generic | +| costoptimizationhub | `aws_costoptimizationhub_recommendations` | `-` | generic | +| datapipeline | `aws_datapipeline_pipelines` | `AWS::DataPipeline::Pipeline` | generic | +| datasync | `aws_datasync_agents` | `AWS::DataSync::Agent` | generic | +| datasync | `aws_datasync_azureblob_locations` | `AWS::DataSync::AzureblobLocation` | generic | +| datasync | `aws_datasync_efs_locations` | `AWS::DataSync::EfsLocation` | generic | +| datasync | `aws_datasync_fsxlustre_locations` | `AWS::DataSync::FsxlustreLocation` | generic | +| datasync | `aws_datasync_fsxontap_locations` | `AWS::DataSync::FsxontapLocation` | generic | +| datasync | `aws_datasync_fsxopenzfs_locations` | `AWS::DataSync::FsxopenzfsLocation` | generic | +| datasync | `aws_datasync_fsxwindows_locations` | `AWS::DataSync::FsxwindowsLocation` | generic | +| datasync | `aws_datasync_hdfs_locations` | `AWS::DataSync::HdfsLocation` | generic | +| datasync | `aws_datasync_locations` | `AWS::DataSync::Location` | generic | +| datasync | `aws_datasync_nfs_locations` | `AWS::DataSync::NfsLocation` | generic | +| datasync | `aws_datasync_objectstorage_locations` | `AWS::DataSync::ObjectstorageLocation` | generic | +| datasync | `aws_datasync_s3_locations` | `AWS::DataSync::S3Location` | generic | +| datasync | `aws_datasync_smb_locations` | `AWS::DataSync::SmbLocation` | generic | +| dax | `aws_dax_clusters` | `AWS::DAX::Cluster` | generic | +| detective | `aws_detective_graph_members` | `AWS::Detective::GraphMember` | generic | +| detective | `aws_detective_graphs` | `AWS::Detective::Graph` | generic | +| devopsguru | `aws_devopsguru_anomalies` | `AWS::DevOpsGuru::Anomaly` | generic | +| devopsguru | `aws_devopsguru_events` | `AWS::DevOpsGuru::Event` | generic | +| devopsguru | `aws_devopsguru_insights` | `AWS::DevOpsGuru::Insight` | generic | +| devopsguru | `aws_devopsguru_log_groups` | `AWS::DevOpsGuru::LogGroup` | generic | +| devopsguru | `aws_devopsguru_monitored_resources` | `AWS::DevOpsGuru::MonitoredResource` | generic | +| devopsguru | `aws_devopsguru_notification_channels` | `AWS::DevOpsGuru::NotificationChannel` | generic | +| devopsguru | `aws_devopsguru_recommendations` | `AWS::DevOpsGuru::Recommendation` | generic | +| directconnect | `aws_directconnect_connections` | `AWS::DirectConnect::Connection` | generic | +| directconnect | `aws_directconnect_gateway_associations` | `AWS::DirectConnect::GatewayAssociation` | generic | +| directconnect | `aws_directconnect_gateway_attachments` | `AWS::DirectConnect::GatewayAttachment` | generic | +| directconnect | `aws_directconnect_gateways` | `AWS::DirectConnect::Gateway` | generic | +| directconnect | `aws_directconnect_lags` | `AWS::DirectConnect::Lag` | generic | +| directconnect | `aws_directconnect_locations` | `AWS::DirectConnect::Location` | generic | +| directconnect | `aws_directconnect_virtual_gateways` | `AWS::DirectConnect::VirtualGateway` | generic | +| directconnect | `aws_directconnect_virtual_interfaces` | `AWS::DirectConnect::VirtualInterface` | generic | +| directoryservice | `aws_directoryservice_directories` | `AWS::DirectoryService::Directory` | generic | +| dlm | `aws_dlm_lifecycle_policies` | `AWS::DLM::LifecyclePolicy` | generic | +| dms | `aws_dms_certificates` | `AWS::DMS::Certificate` | generic | +| dms | `aws_dms_event_subscriptions` | `AWS::DMS::EventSubscription` | generic | +| dms | `aws_dms_replication_instances` | `AWS::DMS::ReplicationInstance` | generic | +| dms | `aws_dms_replication_subnet_groups` | `AWS::DMS::ReplicationSubnetGroup` | generic | +| dms | `aws_dms_replication_tasks` | `AWS::DMS::ReplicationTask` | generic | +| docdb | `aws_docdb_certificates` | `AWS::DocDB::Certificate` | generic | +| docdb | `aws_docdb_cluster_parameter_groups` | `AWS::DocDB::ClusterParameterGroup` | generic | +| docdb | `aws_docdb_cluster_parameters` | `AWS::DocDB::ClusterParameter` | generic | +| docdb | `aws_docdb_cluster_snapshots` | `AWS::DocDB::ClusterSnapshot` | generic | +| docdb | `aws_docdb_clusters` | `AWS::DocDB::DBCluster` | generic | +| docdb | `aws_docdb_engine_versions` | `AWS::DocDB::EngineVersion` | generic | +| docdb | `aws_docdb_event_categories` | `AWS::DocDB::EventCategory` | generic | +| docdb | `aws_docdb_event_subscriptions` | `AWS::DocDB::EventSubscription` | generic | +| docdb | `aws_docdb_events` | `AWS::DocDB::Event` | generic | +| docdb | `aws_docdb_global_clusters` | `AWS::DocDB::GlobalCluster` | generic | +| docdb | `aws_docdb_instances` | `AWS::DocDB::DBInstance` | generic | +| docdb | `aws_docdb_orderable_db_instance_options` | `AWS::DocDB::OrderableDbInstanceOption` | generic | +| docdb | `aws_docdb_pending_maintenance_actions` | `AWS::DocDB::PendingMaintenanceAction` | generic | +| docdb | `aws_docdb_subnet_groups` | `AWS::DocDB::SubnetGroup` | generic | +| dsql | `aws_dsql_cluster_policies` | `AWS::DSQL::ClusterPolicy` | generic | +| dsql | `aws_dsql_clusters` | `AWS::DSQL::Cluster` | generic | +| dynamodb | `aws_dynamodb_backups` | `AWS::DynamoDB::Backup` | generic | +| dynamodb | `aws_dynamodb_exports` | `AWS::DynamoDB::Export` | generic | +| dynamodb | `aws_dynamodb_global_tables` | `AWS::DynamoDB::GlobalTable` | generic | +| dynamodb | `aws_dynamodb_table_continuous_backups` | `AWS::DynamoDB::TableContinuousBackup` | generic | +| dynamodb | `aws_dynamodb_table_replica_auto_scalings` | `AWS::DynamoDB::TableReplicaAutoScaling` | generic | +| dynamodb | `aws_dynamodb_table_resource_policies` | `AWS::DynamoDB::TableResourcePolicy` | generic | +| dynamodb | `aws_dynamodb_table_stream_resource_policies` | `AWS::DynamoDB::TableStreamResourcePolicy` | generic | +| dynamodb | `aws_dynamodb_tables` | `AWS::DynamoDB::Table` | generic | +| dynamodbstreams | `aws_dynamodbstreams_streams` | `AWS::DynamoDB::Stream` | generic | +| ebs | `aws_ebs_default_kms_key_ids` | `AWS::EC2::DefaultKmsKeyId` | generic | +| ebs | `aws_ebs_encryption_by_defaults` | `AWS::EC2::EncryptionByDefault` | generic | +| ec2 | `aws_ec2_account_attributes` | `-` | generic | +| ec2 | `aws_ec2_byoip_cidrs` | `AWS::EC2::ByoipCidr` | generic | +| ec2 | `aws_ec2_capacity_reservation_topologies` | `AWS::EC2::CapacityReservationTopology` | generic | +| ec2 | `aws_ec2_capacity_reservations` | `AWS::EC2::CapacityReservation` | generic | +| ec2 | `aws_ec2_customer_gateways` | `AWS::EC2::CustomerGateway` | generic | +| ec2 | `aws_ec2_dhcp_options` | `AWS::EC2::DHCPOptions` | generic | +| ec2 | `aws_ec2_ebs_snapshot_attributes` | `AWS::EC2::EbsSnapshotAttribute` | generic | +| ec2 | `aws_ec2_ebs_snapshots` | `AWS::EC2::Snapshot` | generic | +| ec2 | `aws_ec2_ebs_volume_statuses` | `AWS::EC2::EbsVolumeStatus` | generic | +| ec2 | `aws_ec2_ebs_volumes` | `AWS::EC2::Volume` | generic | +| ec2 | `aws_ec2_egress_only_internet_gateways` | `AWS::EC2::EgressOnlyInternetGateway` | generic | +| ec2 | `aws_ec2_eips` | `AWS::EC2::EIP` | generic | +| ec2 | `aws_ec2_flow_logs` | `AWS::EC2::FlowLog` | generic | +| ec2 | `aws_ec2_hosts` | `AWS::EC2::Host` | generic | +| ec2 | `aws_ec2_image_block_public_access_states` | `AWS::EC2::ImageBlockPublicAccessState` | generic | +| ec2 | `aws_ec2_image_last_launched_times` | `AWS::EC2::ImageLastLaunchedTime` | generic | +| ec2 | `aws_ec2_image_launch_permissions` | `AWS::EC2::ImageLaunchPermission` | generic | +| ec2 | `aws_ec2_image_references` | `AWS::EC2::ImageReference` | generic | +| ec2 | `aws_ec2_images` | `AWS::EC2::Image` | generic | +| ec2 | `aws_ec2_instance_connect_endpoints` | `AWS::EC2::InstanceConnectEndpoint` | generic | +| ec2 | `aws_ec2_instance_credit_specifications` | `AWS::EC2::InstanceCreditSpecification` | generic | +| ec2 | `aws_ec2_instance_disable_api_stop` | `AWS::EC2::InstanceDisableApiStop` | generic | +| ec2 | `aws_ec2_instance_disable_api_termination` | `AWS::EC2::InstanceDisableApiTermination` | generic | +| ec2 | `aws_ec2_instance_statuses` | `-` | generic | +| ec2 | `aws_ec2_instance_topologies` | `AWS::EC2::InstanceTopology` | generic | +| ec2 | `aws_ec2_instance_types` | `-` | generic | +| ec2 | `aws_ec2_instance_user_data` | `AWS::EC2::InstanceUserData` | generic | +| ec2 | `aws_ec2_instances` | `AWS::EC2::Instance` | typed | +| ec2 | `aws_ec2_internet_gateways` | `AWS::EC2::InternetGateway` | generic | +| ec2 | `aws_ec2_ipam_address_history` | `AWS::EC2::IpamAddressHistory` | generic | +| ec2 | `aws_ec2_ipam_byoasns` | `AWS::EC2::IpamByoasn` | generic | +| ec2 | `aws_ec2_ipam_discovered_accounts` | `AWS::EC2::IpamDiscoveredAccount` | generic | +| ec2 | `aws_ec2_ipam_discovered_public_addresses` | `AWS::EC2::IpamDiscoveredPublicAddress` | generic | +| ec2 | `aws_ec2_ipam_discovered_resource_cidrs` | `AWS::EC2::IpamDiscoveredResourceCidr` | generic | +| ec2 | `aws_ec2_ipam_pool_allocations` | `AWS::EC2::IpamPoolAllocation` | generic | +| ec2 | `aws_ec2_ipam_pool_cidrs` | `AWS::EC2::IpamPoolCidr` | generic | +| ec2 | `aws_ec2_ipam_pools` | `AWS::EC2::IpamPool` | generic | +| ec2 | `aws_ec2_ipam_resource_cidrs` | `AWS::EC2::IpamResourceCidr` | generic | +| ec2 | `aws_ec2_ipam_resource_discoveries` | `AWS::EC2::IpamResourceDiscovery` | generic | +| ec2 | `aws_ec2_ipam_resource_discovery_associations` | `AWS::EC2::IpamResourceDiscoveryAssociation` | generic | +| ec2 | `aws_ec2_ipam_scopes` | `AWS::EC2::IpamScope` | generic | +| ec2 | `aws_ec2_ipams` | `AWS::EC2::Ipam` | generic | +| ec2 | `aws_ec2_key_pairs` | `AWS::EC2::KeyPair` | generic | +| ec2 | `aws_ec2_launch_template_versions` | `AWS::EC2::LaunchTemplateVersion` | generic | +| ec2 | `aws_ec2_launch_templates` | `AWS::EC2::LaunchTemplate` | generic | +| ec2 | `aws_ec2_managed_prefix_list_entries` | `AWS::EC2::ManagedPrefixListEntry` | generic | +| ec2 | `aws_ec2_managed_prefix_lists` | `AWS::EC2::ManagedPrefixList` | generic | +| ec2 | `aws_ec2_nat_gateways` | `AWS::EC2::NatGateway` | generic | +| ec2 | `aws_ec2_network_acls` | `AWS::EC2::NetworkAcl` | generic | +| ec2 | `aws_ec2_network_interfaces` | `AWS::EC2::NetworkInterface` | generic | +| ec2 | `aws_ec2_prefix_lists` | `AWS::EC2::PrefixList` | generic | +| ec2 | `aws_ec2_regional_configs` | `AWS::EC2::RegionalConfig` | generic | +| ec2 | `aws_ec2_replace_root_volume_tasks` | `AWS::EC2::ReplaceRootVolumeTask` | generic | +| ec2 | `aws_ec2_reserved_instances` | `AWS::EC2::ReservedInstance` | generic | +| ec2 | `aws_ec2_route_tables` | `AWS::EC2::RouteTable` | generic | +| ec2 | `aws_ec2_security_group_rules` | `AWS::EC2::SecurityGroupRule` | generic | +| ec2 | `aws_ec2_security_groups` | `AWS::EC2::SecurityGroup` | generic | +| ec2 | `aws_ec2_serial_console_access_statuses` | `AWS::EC2::SerialConsoleAccessStatus` | generic | +| ec2 | `aws_ec2_snapshot_block_public_access_states` | `AWS::EC2::SnapshotBlockPublicAccessState` | generic | +| ec2 | `aws_ec2_spot_fleet_instances` | `AWS::EC2::SpotFleetInstance` | generic | +| ec2 | `aws_ec2_spot_fleet_requests` | `AWS::EC2::SpotFleetRequest` | generic | +| ec2 | `aws_ec2_spot_instance_requests` | `AWS::EC2::SpotInstanceRequest` | generic | +| ec2 | `aws_ec2_subnets` | `AWS::EC2::Subnet` | generic | +| ec2 | `aws_ec2_traffic_mirror_filters` | `AWS::EC2::TrafficMirrorFilter` | generic | +| ec2 | `aws_ec2_traffic_mirror_sessions` | `AWS::EC2::TrafficMirrorSession` | generic | +| ec2 | `aws_ec2_traffic_mirror_targets` | `AWS::EC2::TrafficMirrorTarget` | generic | +| ec2 | `aws_ec2_transit_gateway_attachments` | `AWS::EC2::TransitGatewayAttachment` | generic | +| ec2 | `aws_ec2_transit_gateway_connect_peers` | `AWS::EC2::TransitGatewayConnectPeer` | generic | +| ec2 | `aws_ec2_transit_gateway_multicast_domains` | `AWS::EC2::TransitGatewayMulticastDomain` | generic | +| ec2 | `aws_ec2_transit_gateway_peering_attachments` | `AWS::EC2::TransitGatewayPeeringAttachment` | generic | +| ec2 | `aws_ec2_transit_gateway_route_tables` | `AWS::EC2::TransitGatewayRouteTable` | generic | +| ec2 | `aws_ec2_transit_gateway_routes` | `AWS::EC2::TransitGatewayRoute` | generic | +| ec2 | `aws_ec2_transit_gateway_vpc_attachments` | `AWS::EC2::TransitGatewayVpcAttachment` | generic | +| ec2 | `aws_ec2_transit_gateways` | `AWS::EC2::TransitGateway` | generic | +| ec2 | `aws_ec2_vpc_endpoint_connections` | `AWS::EC2::VpcEndpointConnection` | generic | +| ec2 | `aws_ec2_vpc_endpoint_service_configurations` | `AWS::EC2::VpcEndpointServiceConfiguration` | generic | +| ec2 | `aws_ec2_vpc_endpoint_service_permissions` | `AWS::EC2::VpcEndpointServicePermission` | generic | +| ec2 | `aws_ec2_vpc_endpoint_services` | `AWS::EC2::VpcEndpointService` | generic | +| ec2 | `aws_ec2_vpc_endpoints` | `AWS::EC2::VPCEndpoint` | generic | +| ec2 | `aws_ec2_vpc_peering_connections` | `AWS::EC2::VPCPeeringConnection` | generic | +| ec2 | `aws_ec2_vpcs` | `AWS::EC2::VPC` | generic | +| ec2 | `aws_ec2_vpn_connections` | `AWS::EC2::VPNConnection` | generic | +| ec2 | `aws_ec2_vpn_gateways` | `AWS::EC2::VPNGateway` | generic | +| ecr | `aws_ecr_pull_through_cache_rules` | `AWS::ECR::PullThroughCacheRule` | generic | +| ecr | `aws_ecr_registries` | `AWS::ECR::Registry` | generic | +| ecr | `aws_ecr_registry_policies` | `AWS::ECR::RegistryPolicy` | generic | +| ecr | `aws_ecr_repositories` | `AWS::ECR::Repository` | generic | +| ecr | `aws_ecr_repository_image_scan_findings` | `AWS::ECR::RepositoryImageScanFinding` | generic | +| ecr | `aws_ecr_repository_images` | `AWS::ECR::RepositoryImage` | generic | +| ecr | `aws_ecr_repository_lifecycle_policies` | `AWS::ECR::RepositoryLifecyclePolicy` | generic | +| ecr | `aws_ecr_repository_policies` | `AWS::ECR::RepositoryPolicy` | generic | +| ecrpublic | `aws_ecrpublic_repositories` | `AWS::Ecrpublic::Repository` | generic | +| ecrpublic | `aws_ecrpublic_repository_images` | `AWS::Ecrpublic::RepositoryImage` | generic | +| ecs | `aws_ecs_cluster_container_instances` | `AWS::ECS::ClusterContainerInstance` | generic | +| ecs | `aws_ecs_cluster_services` | `AWS::ECS::Service` | generic | +| ecs | `aws_ecs_cluster_task_sets` | `AWS::ECS::ClusterTaskSet` | generic | +| ecs | `aws_ecs_cluster_tasks` | `AWS::ECS::ClusterTask` | generic | +| ecs | `aws_ecs_clusters` | `AWS::ECS::Cluster` | generic | +| ecs | `aws_ecs_task_definitions` | `AWS::ECS::TaskDefinition` | generic | +| efs | `aws_efs_access_points` | `AWS::EFS::AccessPoint` | generic | +| efs | `aws_efs_filesystems` | `AWS::EFS::FileSystem` | generic | +| eks | `aws_eks_access_policies` | `AWS::EKS::AccessPolicy` | generic | +| eks | `aws_eks_cluster_access_entries` | `AWS::EKS::ClusterAccessEntry` | generic | +| eks | `aws_eks_cluster_addons` | `AWS::EKS::ClusterAddon` | generic | +| eks | `aws_eks_cluster_associated_access_policies` | `AWS::EKS::ClusterAssociatedAccessPolicy` | generic | +| eks | `aws_eks_cluster_node_groups` | `AWS::EKS::Nodegroup` | generic | +| eks | `aws_eks_cluster_oidc_identity_provider_configs` | `AWS::EKS::ClusterOidcIdentityProviderConfig` | generic | +| eks | `aws_eks_cluster_versions` | `AWS::EKS::ClusterVersion` | generic | +| eks | `aws_eks_clusters` | `AWS::EKS::Cluster` | generic | +| eks | `aws_eks_fargate_profiles` | `AWS::EKS::FargateProfile` | generic | +| elasticache | `aws_elasticache_clusters` | `AWS::ElastiCache::CacheCluster` | generic | +| elasticache | `aws_elasticache_engine_versions` | `AWS::ElastiCache::EngineVersion` | generic | +| elasticache | `aws_elasticache_events` | `AWS::ElastiCache::Event` | generic | +| elasticache | `aws_elasticache_global_replication_groups` | `AWS::ElastiCache::GlobalReplicationGroup` | generic | +| elasticache | `aws_elasticache_parameter_groups` | `AWS::ElastiCache::ParameterGroup` | generic | +| elasticache | `aws_elasticache_replication_groups` | `AWS::ElastiCache::ReplicationGroup` | generic | +| elasticache | `aws_elasticache_reserved_cache_nodes` | `AWS::ElastiCache::ReservedCacheNode` | generic | +| elasticache | `aws_elasticache_reserved_cache_nodes_offerings` | `AWS::ElastiCache::ReservedCacheNodesOffering` | generic | +| elasticache | `aws_elasticache_serverless_cache_snapshots` | `AWS::ElastiCache::ServerlessCacheSnapshot` | generic | +| elasticache | `aws_elasticache_serverless_caches` | `AWS::ElastiCache::ServerlessCach` | generic | +| elasticache | `aws_elasticache_service_updates` | `AWS::ElastiCache::ServiceUpdate` | generic | +| elasticache | `aws_elasticache_snapshots` | `AWS::ElastiCache::Snapshot` | generic | +| elasticache | `aws_elasticache_subnet_groups` | `AWS::ElastiCache::SubnetGroup` | generic | +| elasticache | `aws_elasticache_update_actions` | `AWS::ElastiCache::UpdateAction` | generic | +| elasticache | `aws_elasticache_user_groups` | `AWS::ElastiCache::UserGroup` | generic | +| elasticache | `aws_elasticache_users` | `AWS::ElastiCache::User` | generic | +| elasticbeanstalk | `aws_elasticbeanstalk_application_versions` | `AWS::ElasticBeanstalk::ApplicationVersion` | generic | +| elasticbeanstalk | `aws_elasticbeanstalk_applications` | `AWS::ElasticBeanstalk::Application` | generic | +| elasticbeanstalk | `aws_elasticbeanstalk_configuration_options` | `AWS::ElasticBeanstalk::ConfigurationOption` | generic | +| elasticbeanstalk | `aws_elasticbeanstalk_configuration_settings` | `AWS::ElasticBeanstalk::ConfigurationSetting` | generic | +| elasticbeanstalk | `aws_elasticbeanstalk_environments` | `AWS::ElasticBeanstalk::Environment` | generic | +| elasticbeanstalk | `aws_elasticbeanstalk_platform_versions` | `AWS::ElasticBeanstalk::PlatformVersion` | generic | +| elasticsearch | `aws_elasticsearch_domains` | `AWS::Elasticsearch::Domain` | generic | +| elasticsearch | `aws_elasticsearch_packages` | `AWS::Elasticsearch::Package` | generic | +| elasticsearch | `aws_elasticsearch_reserved_instances` | `AWS::Elasticsearch::ReservedInstance` | generic | +| elasticsearch | `aws_elasticsearch_versions` | `AWS::Elasticsearch::Version` | generic | +| elasticsearch | `aws_elasticsearch_vpc_endpoints` | `AWS::Elasticsearch::VpcEndpoint` | generic | +| elbv1 | `aws_elbv1_load_balancer_policies` | `AWS::ElasticLoadBalancing::LoadBalancerPolicy` | generic | +| elbv1 | `aws_elbv1_load_balancers` | `AWS::ElasticLoadBalancing::LoadBalancer` | generic | +| elbv2 | `aws_elbv2_listener_certificates` | `AWS::ElasticLoadBalancingV2::ListenerCertificate` | generic | +| elbv2 | `aws_elbv2_listener_rules` | `AWS::ElasticLoadBalancingV2::ListenerRule` | generic | +| elbv2 | `aws_elbv2_listeners` | `AWS::ElasticLoadBalancingV2::Listener` | generic | +| elbv2 | `aws_elbv2_load_balancer_attributes` | `AWS::ElasticLoadBalancingV2::LoadBalancerAttribute` | generic | +| elbv2 | `aws_elbv2_load_balancer_capacity_reservations` | `AWS::ElasticLoadBalancingV2::LoadBalancerCapacityReservation` | generic | +| elbv2 | `aws_elbv2_load_balancer_web_acls` | `AWS::ElasticLoadBalancingV2::LoadBalancerWebAcl` | generic | +| elbv2 | `aws_elbv2_load_balancers` | `AWS::ElasticLoadBalancingV2::LoadBalancer` | generic | +| elbv2 | `aws_elbv2_target_group_attributes` | `AWS::ElasticLoadBalancingV2::TargetGroupAttribute` | generic | +| elbv2 | `aws_elbv2_target_group_target_health_descriptions` | `AWS::ElasticLoadBalancingV2::TargetGroupTargetHealthDescription` | generic | +| elbv2 | `aws_elbv2_target_groups` | `AWS::ElasticLoadBalancingV2::TargetGroup` | generic | +| emr | `aws_emr_block_public_access_configs` | `AWS::EMR::BlockPublicAccessConfig` | generic | +| emr | `aws_emr_cluster_instance_fleets` | `AWS::EMR::ClusterInstanceFleet` | generic | +| emr | `aws_emr_cluster_instance_groups` | `AWS::EMR::ClusterInstanceGroup` | generic | +| emr | `aws_emr_cluster_instances` | `AWS::EMR::ClusterInstance` | generic | +| emr | `aws_emr_clusters` | `AWS::EMR::Cluster` | generic | +| emr | `aws_emr_notebook_executions` | `AWS::EMR::NotebookExecution` | generic | +| emr | `aws_emr_release_labels` | `AWS::EMR::ReleaseLabel` | generic | +| emr | `aws_emr_security_configurations` | `AWS::EMR::SecurityConfiguration` | generic | +| emr | `aws_emr_steps` | `AWS::EMR::Step` | generic | +| emr | `aws_emr_studio_session_mappings` | `AWS::EMR::StudioSessionMapping` | generic | +| emr | `aws_emr_studios` | `AWS::EMR::Studio` | generic | +| emr | `aws_emr_supported_instance_types` | `AWS::EMR::SupportedInstanceType` | generic | +| eventbridge | `aws_eventbridge_api_destinations` | `AWS::Events::ApiDestination` | generic | +| eventbridge | `aws_eventbridge_archives` | `AWS::Events::Archive` | generic | +| eventbridge | `aws_eventbridge_connections` | `AWS::Events::Connection` | generic | +| eventbridge | `aws_eventbridge_endpoints` | `AWS::Events::Endpoint` | generic | +| eventbridge | `aws_eventbridge_event_bus_rules` | `AWS::Events::EventBusRule` | generic | +| eventbridge | `aws_eventbridge_event_bus_targets` | `AWS::Events::EventBusTarget` | generic | +| eventbridge | `aws_eventbridge_event_buses` | `AWS::Events::EventBus` | generic | +| eventbridge | `aws_eventbridge_event_sources` | `AWS::Events::EventSource` | generic | +| eventbridge | `aws_eventbridge_replays` | `AWS::Events::Replay` | generic | +| firehose | `aws_firehose_delivery_streams` | `AWS::KinesisFirehose::DeliveryStream` | generic | +| fis | `aws_fis_actions` | `AWS::Fis::Action` | generic | +| fis | `aws_fis_experiment_resolved_targets` | `AWS::Fis::ExperimentResolvedTarget` | generic | +| fis | `aws_fis_experiment_templates` | `AWS::Fis::ExperimentTemplate` | generic | +| fis | `aws_fis_experiments` | `AWS::Fis::Experiment` | generic | +| fis | `aws_fis_target_account_configurations` | `AWS::Fis::TargetAccountConfiguration` | generic | +| fis | `aws_fis_target_resource_types` | `AWS::Fis::TargetResourceType` | generic | +| frauddetector | `aws_frauddetector_batch_imports` | `AWS::FraudDetector::BatchImport` | generic | +| frauddetector | `aws_frauddetector_batch_predictions` | `AWS::FraudDetector::BatchPrediction` | generic | +| frauddetector | `aws_frauddetector_detectors` | `AWS::FraudDetector::Detector` | generic | +| frauddetector | `aws_frauddetector_entity_types` | `AWS::FraudDetector::EntityType` | generic | +| frauddetector | `aws_frauddetector_event_types` | `AWS::FraudDetector::EventType` | generic | +| frauddetector | `aws_frauddetector_external_models` | `AWS::FraudDetector::ExternalModel` | generic | +| frauddetector | `aws_frauddetector_labels` | `AWS::FraudDetector::Label` | generic | +| frauddetector | `aws_frauddetector_model_versions` | `AWS::FraudDetector::ModelVersion` | generic | +| frauddetector | `aws_frauddetector_models` | `AWS::FraudDetector::Model` | generic | +| frauddetector | `aws_frauddetector_outcomes` | `AWS::FraudDetector::Outcome` | generic | +| frauddetector | `aws_frauddetector_rules` | `AWS::FraudDetector::Rule` | generic | +| frauddetector | `aws_frauddetector_variables` | `AWS::FraudDetector::Variable` | generic | +| freetier | `aws_freetier_usages` | `AWS::Freetier::Usage` | generic | +| fsx | `aws_fsx_backups` | `AWS::FSx::Backup` | generic | +| fsx | `aws_fsx_data_repository_associations` | `AWS::FSx::DataRepositoryAssociation` | generic | +| fsx | `aws_fsx_data_repository_tasks` | `AWS::FSx::DataRepositoryTask` | generic | +| fsx | `aws_fsx_file_caches` | `AWS::FSx::FileCach` | generic | +| fsx | `aws_fsx_file_systems` | `AWS::FSx::FileSystem` | generic | +| fsx | `aws_fsx_snapshots` | `AWS::FSx::Snapshot` | generic | +| fsx | `aws_fsx_storage_virtual_machines` | `AWS::FSx::StorageVirtualMachine` | generic | +| fsx | `aws_fsx_volumes` | `AWS::FSx::Volume` | generic | +| glacier | `aws_glacier_data_retrieval_policies` | `AWS::Glacier::DataRetrievalPolicy` | generic | +| glacier | `aws_glacier_vault_access_policies` | `AWS::Glacier::VaultAccessPolicy` | generic | +| glacier | `aws_glacier_vault_lock_policies` | `AWS::Glacier::VaultLockPolicy` | generic | +| glacier | `aws_glacier_vault_notifications` | `AWS::Glacier::VaultNotification` | generic | +| glacier | `aws_glacier_vaults` | `AWS::Glacier::Vault` | generic | +| globalaccelerator | `aws_globalaccelerator_accelerators` | `AWS::GlobalAccelerator::Accelerator` | generic | +| globalaccelerator | `aws_globalaccelerator_custom_routing_accelerators` | `AWS::GlobalAccelerator::CustomRoutingAccelerator` | generic | +| globalaccelerator | `aws_globalaccelerator_endpoint_groups` | `AWS::GlobalAccelerator::EndpointGroup` | generic | +| globalaccelerator | `aws_globalaccelerator_listeners` | `AWS::GlobalAccelerator::Listener` | generic | +| glue | `aws_glue_catalogs` | `AWS::Glue::Catalog` | generic | +| glue | `aws_glue_classifiers` | `AWS::Glue::Classifier` | generic | +| glue | `aws_glue_connections` | `AWS::Glue::Connection` | generic | +| glue | `aws_glue_crawlers` | `AWS::Glue::Crawler` | generic | +| glue | `aws_glue_database_table_indexes` | `AWS::Glue::DatabaseTableIndex` | generic | +| glue | `aws_glue_database_table_storage_optimizers` | `AWS::Glue::DatabaseTableStorageOptimizer` | generic | +| glue | `aws_glue_database_tables` | `AWS::Glue::DatabaseTable` | generic | +| glue | `aws_glue_databases` | `AWS::Glue::Databas` | generic | +| glue | `aws_glue_datacatalog_encryption_settings` | `AWS::Glue::DatacatalogEncryptionSetting` | generic | +| glue | `aws_glue_dev_endpoints` | `AWS::Glue::DevEndpoint` | generic | +| glue | `aws_glue_job_runs` | `AWS::Glue::JobRun` | generic | +| glue | `aws_glue_jobs` | `AWS::Glue::Job` | generic | +| glue | `aws_glue_ml_transform_task_runs` | `AWS::Glue::MlTransformTaskRun` | generic | +| glue | `aws_glue_ml_transforms` | `AWS::Glue::MlTransform` | generic | +| glue | `aws_glue_registries` | `AWS::Glue::Registry` | generic | +| glue | `aws_glue_registry_schema_versions` | `AWS::Glue::RegistrySchemaVersion` | generic | +| glue | `aws_glue_registry_schemas` | `AWS::Glue::RegistrySchema` | generic | +| glue | `aws_glue_security_configurations` | `AWS::Glue::SecurityConfiguration` | generic | +| glue | `aws_glue_triggers` | `AWS::Glue::Trigger` | generic | +| glue | `aws_glue_workflows` | `AWS::Glue::Workflow` | generic | +| grafana | `aws_grafana_permissions` | `AWS::Grafana::Permission` | generic | +| grafana | `aws_grafana_versions` | `AWS::Grafana::Version` | generic | +| grafana | `aws_grafana_workspace_service_account_tokens` | `AWS::Grafana::WorkspaceServiceAccountToken` | generic | +| grafana | `aws_grafana_workspace_service_accounts` | `AWS::Grafana::WorkspaceServiceAccount` | generic | +| grafana | `aws_grafana_workspaces` | `AWS::Grafana::Workspace` | generic | +| guardduty | `aws_guardduty_detector_coverages` | `AWS::GuardDuty::DetectorCoverage` | generic | +| guardduty | `aws_guardduty_detector_filters` | `AWS::GuardDuty::DetectorFilter` | generic | +| guardduty | `aws_guardduty_detector_findings` | `AWS::GuardDuty::DetectorFinding` | generic | +| guardduty | `aws_guardduty_detector_intel_sets` | `AWS::GuardDuty::DetectorIntelSet` | generic | +| guardduty | `aws_guardduty_detector_ip_sets` | `AWS::GuardDuty::DetectorIpSet` | generic | +| guardduty | `aws_guardduty_detector_members` | `AWS::GuardDuty::DetectorMember` | generic | +| guardduty | `aws_guardduty_detector_publishing_destinations` | `AWS::GuardDuty::DetectorPublishingDestination` | generic | +| guardduty | `aws_guardduty_detectors` | `AWS::GuardDuty::Detector` | generic | +| health | `aws_health_affected_entities` | `AWS::Health::AffectedEntity` | generic | +| health | `aws_health_event_details` | `AWS::Health::EventDetail` | generic | +| health | `aws_health_events` | `AWS::Health::Event` | generic | +| health | `aws_health_org_event_details` | `AWS::Health::OrgEventDetail` | generic | +| health | `aws_health_organization_affected_entities` | `AWS::Health::OrganizationAffectedEntity` | generic | +| health | `aws_health_organization_events` | `AWS::Health::OrganizationEvent` | generic | +| healthlake | `aws_healthlake_fhir_datastores` | `AWS::HealthLake::FhirDatastore` | generic | +| iam | `aws_iam_account_authorization_details` | `-` | generic | +| iam | `aws_iam_accounts` | `-` | typed | +| iam | `aws_iam_credential_reports` | `-` | generic | +| iam | `aws_iam_group_attached_policies` | `AWS::IAM::GroupAttachedPolicy` | generic | +| iam | `aws_iam_group_last_accessed_details` | `AWS::IAM::GroupLastAccessedDetail` | generic | +| iam | `aws_iam_group_policies` | `AWS::IAM::GroupPolicy` | generic | +| iam | `aws_iam_groups` | `AWS::IAM::Group` | generic | +| iam | `aws_iam_instance_profiles` | `AWS::IAM::InstanceProfile` | generic | +| iam | `aws_iam_mfa_devices` | `AWS::IAM::MfaDevice` | generic | +| iam | `aws_iam_openid_connect_identity_providers` | `AWS::IAM::OpenidConnectIdentityProvider` | generic | +| iam | `aws_iam_outbound_web_identity_federations` | `AWS::IAM::OutboundWebIdentityFederation` | generic | +| iam | `aws_iam_password_policies` | `AWS::IAM::PasswordPolicy` | generic | +| iam | `aws_iam_policies` | `AWS::IAM::ManagedPolicy` | generic | +| iam | `aws_iam_policy_default_versions` | `AWS::IAM::PolicyDefaultVersion` | generic | +| iam | `aws_iam_policy_last_accessed_details` | `AWS::IAM::PolicyLastAccessedDetail` | generic | +| iam | `aws_iam_policy_versions` | `AWS::IAM::PolicyVersion` | generic | +| iam | `aws_iam_role_attached_policies` | `AWS::IAM::RoleAttachedPolicy` | generic | +| iam | `aws_iam_role_last_accessed_details` | `AWS::IAM::RoleLastAccessedDetail` | generic | +| iam | `aws_iam_role_policies` | `AWS::IAM::RolePolicy` | generic | +| iam | `aws_iam_roles` | `AWS::IAM::Role` | generic | +| iam | `aws_iam_saml_identity_providers` | `AWS::IAM::SamlIdentityProvider` | generic | +| iam | `aws_iam_server_certificates` | `AWS::IAM::ServerCertificate` | generic | +| iam | `aws_iam_signing_certificates` | `AWS::IAM::SigningCertificate` | generic | +| iam | `aws_iam_ssh_public_keys` | `AWS::IAM::SshPublicKey` | generic | +| iam | `aws_iam_user_access_keys` | `AWS::IAM::UserAccessKey` | generic | +| iam | `aws_iam_user_attached_policies` | `AWS::IAM::UserAttachedPolicy` | generic | +| iam | `aws_iam_user_groups` | `AWS::IAM::UserGroup` | generic | +| iam | `aws_iam_user_last_accessed_details` | `AWS::IAM::UserLastAccessedDetail` | generic | +| iam | `aws_iam_user_policies` | `AWS::IAM::UserPolicy` | generic | +| iam | `aws_iam_users` | `AWS::IAM::User` | generic | +| iam | `aws_iam_virtual_mfa_devices` | `AWS::IAM::VirtualMfaDevice` | generic | +| identitystore | `aws_identitystore_group_memberships` | `AWS::IdentityStore::GroupMembership` | generic | +| identitystore | `aws_identitystore_groups` | `AWS::IdentityStore::Group` | generic | +| identitystore | `aws_identitystore_users` | `AWS::IdentityStore::User` | generic | +| imagebuilder | `aws_imagebuilder_distribution_configurations` | `AWS::ImageBuilder::DistributionConfiguration` | generic | +| imagebuilder | `aws_imagebuilder_images` | `AWS::ImageBuilder::Image` | generic | +| imagebuilder | `aws_imagebuilder_workflows` | `AWS::ImageBuilder::Workflow` | generic | +| inspector | `aws_inspector_findings` | `AWS::Inspector::Finding` | generic | +| inspector2 | `aws_inspector2_cis_scan_result_details` | `AWS::InspectorV2::CisScanResultDetail` | generic | +| inspector2 | `aws_inspector2_cis_scans` | `AWS::InspectorV2::CisScan` | generic | +| inspector2 | `aws_inspector2_cis_target_resource_aggregations` | `AWS::InspectorV2::CisTargetResourceAggregation` | generic | +| inspector2 | `aws_inspector2_covered_resources` | `AWS::InspectorV2::CoveredResource` | generic | +| inspector2 | `aws_inspector2_findings` | `AWS::InspectorV2::Finding` | generic | +| invoicing | `aws_invoicing_invoice_units` | `AWS::Invoicing::InvoiceUnit` | generic | +| iot | `aws_iot_billing_groups` | `AWS::IoT::BillingGroup` | generic | +| iot | `aws_iot_ca_certificates` | `AWS::IoT::CaCertificate` | generic | +| iot | `aws_iot_certificates` | `AWS::IoT::Certificate` | generic | +| iot | `aws_iot_jobs` | `AWS::IoT::Job` | generic | +| iot | `aws_iot_policies` | `AWS::IoT::Policy` | generic | +| iot | `aws_iot_security_profiles` | `AWS::IoT::SecurityProfile` | generic | +| iot | `aws_iot_streams` | `AWS::IoT::Stream` | generic | +| iot | `aws_iot_thing_groups` | `AWS::IoT::ThingGroup` | generic | +| iot | `aws_iot_thing_types` | `AWS::IoT::ThingType` | generic | +| iot | `aws_iot_things` | `AWS::IoT::Thing` | generic | +| iot | `aws_iot_topic_rules` | `AWS::IoT::TopicRule` | generic | +| kafka | `aws_kafka_cluster_operations` | `AWS::MSK::ClusterOperation` | generic | +| kafka | `aws_kafka_cluster_policies` | `AWS::MSK::ClusterPolicy` | generic | +| kafka | `aws_kafka_clusters` | `AWS::MSK::Cluster` | generic | +| kafka | `aws_kafka_configurations` | `AWS::MSK::Configuration` | generic | +| kafka | `aws_kafka_nodes` | `AWS::MSK::Node` | generic | +| kendra | `aws_kendra_access_control_configurations` | `AWS::Kendra::AccessControlConfiguration` | generic | +| kendra | `aws_kendra_data_source_sync_jobs` | `AWS::Kendra::DataSourceSyncJob` | generic | +| kendra | `aws_kendra_data_sources` | `AWS::Kendra::DataSource` | generic | +| kendra | `aws_kendra_experience_entities` | `AWS::Kendra::ExperienceEntity` | generic | +| kendra | `aws_kendra_experience_entity_personas` | `AWS::Kendra::ExperienceEntityPersona` | generic | +| kendra | `aws_kendra_experiences` | `AWS::Kendra::Experience` | generic | +| kendra | `aws_kendra_faqs` | `AWS::Kendra::Faq` | generic | +| kendra | `aws_kendra_featured_results_sets` | `AWS::Kendra::FeaturedResultsSet` | generic | +| kendra | `aws_kendra_indices` | `AWS::Kendra::Index` | generic | +| kendra | `aws_kendra_query_suggestions_block_lists` | `AWS::Kendra::QuerySuggestionsBlockList` | generic | +| kendra | `aws_kendra_query_suggestions_configs` | `AWS::Kendra::QuerySuggestionsConfig` | generic | +| kendra | `aws_kendra_thesauri` | `AWS::Kendra::Thesaurus` | generic | +| keyspaces | `aws_keyspaces_keyspaces` | `AWS::Cassandra::Keyspace` | generic | +| keyspaces | `aws_keyspaces_tables` | `AWS::Cassandra::Table` | generic | +| kinesis | `aws_kinesis_stream_consumers` | `AWS::Kinesis::StreamConsumer` | generic | +| kinesis | `aws_kinesis_stream_shards` | `AWS::Kinesis::StreamShard` | generic | +| kinesis | `aws_kinesis_streams` | `AWS::Kinesis::Stream` | generic | +| kinesisanalytics | `aws_kinesisanalytics_application_operations` | `AWS::KinesisAnalyticsV2::ApplicationOperation` | generic | +| kinesisanalytics | `aws_kinesisanalytics_application_snapshots` | `AWS::KinesisAnalyticsV2::ApplicationSnapshot` | generic | +| kinesisanalytics | `aws_kinesisanalytics_application_versions` | `AWS::KinesisAnalyticsV2::ApplicationVersion` | generic | +| kinesisanalytics | `aws_kinesisanalytics_applications` | `AWS::KinesisAnalyticsV2::Application` | generic | +| kinesisvideo | `aws_kinesisvideo_streams` | `AWS::KinesisVideo::Stream` | generic | +| kms | `aws_kms_aliases` | `AWS::KMS::Alias` | generic | +| kms | `aws_kms_key_grants` | `AWS::KMS::KeyGrant` | generic | +| kms | `aws_kms_key_policies` | `AWS::KMS::KeyPolicy` | generic | +| kms | `aws_kms_key_rotation_statuses` | `AWS::KMS::KeyRotationStatus` | generic | +| kms | `aws_kms_key_rotations` | `AWS::KMS::KeyRotation` | generic | +| kms | `aws_kms_keys` | `AWS::KMS::Key` | generic | +| lakeformation | `aws_lakeformation_data_cells_filters` | `AWS::LakeFormation::DataCellsFilter` | generic | +| lakeformation | `aws_lakeformation_opt_ins` | `AWS::LakeFormation::OptIn` | generic | +| lakeformation | `aws_lakeformation_permissions` | `AWS::LakeFormation::Permission` | generic | +| lakeformation | `aws_lakeformation_resource_tags` | `AWS::LakeFormation::ResourceTag` | generic | +| lakeformation | `aws_lakeformation_resources` | `AWS::LakeFormation::Resource` | generic | +| lakeformation | `aws_lakeformation_tags` | `AWS::LakeFormation::Tag` | generic | +| lakeformation | `aws_lakeformation_transactions` | `AWS::LakeFormation::Transaction` | generic | +| lambda | `aws_lambda_function_aliases` | `AWS::Lambda::FunctionAlias` | generic | +| lambda | `aws_lambda_function_concurrency_configs` | `AWS::Lambda::FunctionConcurrencyConfig` | generic | +| lambda | `aws_lambda_function_event_invoke_configs` | `AWS::Lambda::FunctionEventInvokeConfig` | generic | +| lambda | `aws_lambda_function_event_source_mappings` | `AWS::Lambda::FunctionEventSourceMapping` | generic | +| lambda | `aws_lambda_function_url_configs` | `AWS::Lambda::FunctionUrlConfig` | generic | +| lambda | `aws_lambda_function_versions` | `AWS::Lambda::FunctionVersion` | generic | +| lambda | `aws_lambda_functions` | `AWS::Lambda::Function` | generic | +| lambda | `aws_lambda_layer_version_policies` | `AWS::Lambda::LayerVersionPolicy` | generic | +| lambda | `aws_lambda_layer_versions` | `AWS::Lambda::LayerVersion` | generic | +| lambda | `aws_lambda_layers` | `AWS::Lambda::LayerVersion` | generic | +| lambda | `aws_lambda_runtimes` | `AWS::Lambda::Runtime` | generic | +| lex | `aws_lex_bot_aliases` | `AWS::Lex::BotAlias` | generic | +| lex | `aws_lex_bot_channel_associations` | `AWS::Lex::BotChannelAssociation` | generic | +| lex | `aws_lex_bot_version_utterances_views` | `AWS::Lex::BotVersionUtterancesView` | generic | +| lex | `aws_lex_bot_versions` | `AWS::Lex::BotVersion` | generic | +| lex | `aws_lex_bots` | `AWS::Lex::Bot` | generic | +| lex | `aws_lex_builtin_intents` | `AWS::Lex::BuiltinIntent` | generic | +| lex | `aws_lex_builtin_slot_types` | `AWS::Lex::BuiltinSlotType` | generic | +| lex | `aws_lex_intent_versions` | `AWS::Lex::IntentVersion` | generic | +| lex | `aws_lex_intents` | `AWS::Lex::Intent` | generic | +| lex | `aws_lex_migrations` | `AWS::Lex::Migration` | generic | +| lex | `aws_lex_slot_type_versions` | `AWS::Lex::SlotTypeVersion` | generic | +| lex | `aws_lex_slot_types` | `AWS::Lex::SlotType` | generic | +| lexv2 | `aws_lexv2_bot_aliases` | `AWS::LexV2::BotAlias` | generic | +| lexv2 | `aws_lexv2_bots` | `AWS::LexV2::Bot` | generic | +| lightsail | `aws_lightsail_alarms` | `AWS::Lightsail::Alarm` | generic | +| lightsail | `aws_lightsail_bucket_access_keys` | `AWS::Lightsail::BucketAccessKey` | generic | +| lightsail | `aws_lightsail_buckets` | `AWS::Lightsail::Bucket` | generic | +| lightsail | `aws_lightsail_certificates` | `AWS::Lightsail::Certificate` | generic | +| lightsail | `aws_lightsail_container_service_deployments` | `AWS::Lightsail::ContainerServiceDeployment` | generic | +| lightsail | `aws_lightsail_container_service_images` | `AWS::Lightsail::ContainerServiceImage` | generic | +| lightsail | `aws_lightsail_container_services` | `AWS::Lightsail::ContainerService` | generic | +| lightsail | `aws_lightsail_database_events` | `AWS::Lightsail::DatabaseEvent` | generic | +| lightsail | `aws_lightsail_database_log_events` | `AWS::Lightsail::DatabaseLogEvent` | generic | +| lightsail | `aws_lightsail_database_parameters` | `AWS::Lightsail::DatabaseParameter` | generic | +| lightsail | `aws_lightsail_database_snapshots` | `AWS::Lightsail::DatabaseSnapshot` | generic | +| lightsail | `aws_lightsail_databases` | `AWS::Lightsail::Databas` | generic | +| lightsail | `aws_lightsail_disk_snapshots` | `AWS::Lightsail::DiskSnapshot` | generic | +| lightsail | `aws_lightsail_disks` | `AWS::Lightsail::Disk` | generic | +| lightsail | `aws_lightsail_distributions` | `AWS::Lightsail::Distribution` | generic | +| lightsail | `aws_lightsail_instance_port_states` | `AWS::Lightsail::InstancePortState` | generic | +| lightsail | `aws_lightsail_instance_snapshots` | `AWS::Lightsail::InstanceSnapshot` | generic | +| lightsail | `aws_lightsail_instances` | `AWS::Lightsail::Instance` | generic | +| lightsail | `aws_lightsail_load_balancer_tls_certificates` | `AWS::Lightsail::LoadBalancerTlsCertificate` | generic | +| lightsail | `aws_lightsail_load_balancers` | `AWS::Lightsail::LoadBalancer` | generic | +| lightsail | `aws_lightsail_static_ips` | `AWS::Lightsail::StaticIp` | generic | +| location | `aws_location_keys` | `AWS::Location::Key` | generic | +| location | `aws_location_maps` | `AWS::Location::Map` | generic | +| macie2 | `aws_macie2_allow_lists` | `AWS::Macie::AllowList` | generic | +| macie2 | `aws_macie2_automated_discovery_accounts` | `AWS::Macie::AutomatedDiscoveryAccount` | generic | +| macie2 | `aws_macie2_classification_jobs` | `AWS::Macie::ClassificationJob` | generic | +| macie2 | `aws_macie2_classification_scopes` | `AWS::Macie::ClassificationScope` | generic | +| macie2 | `aws_macie2_custom_data_identifiers` | `AWS::Macie::CustomDataIdentifier` | generic | +| macie2 | `aws_macie2_findings` | `AWS::Macie::Finding` | generic | +| macie2 | `aws_macie2_invitations` | `AWS::Macie::Invitation` | generic | +| macie2 | `aws_macie2_managed_data_identifiers` | `AWS::Macie::ManagedDataIdentifier` | generic | +| macie2 | `aws_macie2_members` | `AWS::Macie::Member` | generic | +| macie2 | `aws_macie2_sensitivity_inspection_templates` | `AWS::Macie::SensitivityInspectionTemplate` | generic | +| macie2 | `aws_macie2_usage_totals` | `AWS::Macie::UsageTotal` | generic | +| memorydb | `aws_memorydb_reserved_nodes` | `AWS::MemoryDB::Cluster` | generic | +| mpa | `aws_mpa_teams` | `AWS::Mpa::Team` | generic | +| mq | `aws_mq_broker_configuration_revisions` | `AWS::AmazonMQ::BrokerConfigurationRevision` | generic | +| mq | `aws_mq_broker_configurations` | `AWS::AmazonMQ::BrokerConfiguration` | generic | +| mq | `aws_mq_broker_users` | `AWS::AmazonMQ::BrokerUser` | generic | +| mq | `aws_mq_brokers` | `AWS::AmazonMQ::Broker` | generic | +| mwaa | `aws_mwaa_environments` | `AWS::MWAA::Environment` | generic | +| neptune | `aws_neptune_cluster_parameter_group_parameters` | `AWS::Neptune::ClusterParameterGroupParameter` | generic | +| neptune | `aws_neptune_cluster_parameter_groups` | `AWS::Neptune::ClusterParameterGroup` | generic | +| neptune | `aws_neptune_cluster_snapshots` | `AWS::Neptune::ClusterSnapshot` | generic | +| neptune | `aws_neptune_clusters` | `AWS::Neptune::DBCluster` | generic | +| neptune | `aws_neptune_db_parameter_group_db_parameters` | `AWS::Neptune::DbParameterGroupDbParameter` | generic | +| neptune | `aws_neptune_db_parameter_groups` | `AWS::Neptune::DbParameterGroup` | generic | +| neptune | `aws_neptune_event_subscriptions` | `AWS::Neptune::EventSubscription` | generic | +| neptune | `aws_neptune_global_clusters` | `AWS::Neptune::GlobalCluster` | generic | +| neptune | `aws_neptune_instances` | `AWS::Neptune::DBInstance` | generic | +| neptune | `aws_neptune_subnet_groups` | `AWS::Neptune::SubnetGroup` | generic | +| networkfirewall | `aws_networkfirewall_firewall_policies` | `AWS::NetworkFirewall::FirewallPolicy` | generic | +| networkfirewall | `aws_networkfirewall_firewalls` | `AWS::NetworkFirewall::Firewall` | generic | +| networkfirewall | `aws_networkfirewall_rule_groups` | `AWS::NetworkFirewall::RuleGroup` | generic | +| networkfirewall | `aws_networkfirewall_tls_inspection_configurations` | `AWS::NetworkFirewall::TlsInspectionConfiguration` | generic | +| networkmanager | `aws_networkmanager_attachments` | `AWS::NetworkManager::Attachment` | generic | +| networkmanager | `aws_networkmanager_core_network_policy_versions` | `AWS::NetworkManager::CoreNetworkPolicyVersion` | generic | +| networkmanager | `aws_networkmanager_core_networks` | `AWS::NetworkManager::CoreNetwork` | generic | +| networkmanager | `aws_networkmanager_global_networks` | `AWS::NetworkManager::GlobalNetwork` | generic | +| networkmanager | `aws_networkmanager_links` | `AWS::NetworkManager::Link` | generic | +| networkmanager | `aws_networkmanager_sites` | `AWS::NetworkManager::Site` | generic | +| networkmanager | `aws_networkmanager_transit_gateway_registrations` | `AWS::NetworkManager::TransitGatewayRegistration` | generic | +| odb | `aws_odb_autonomous_virtual_machines` | `AWS::Odb::AutonomousVirtualMachine` | generic | +| odb | `aws_odb_cloud_autonomous_vm_clusters` | `AWS::Odb::CloudAutonomousVmCluster` | generic | +| odb | `aws_odb_cloud_exadata_infrastructures` | `AWS::Odb::CloudExadataInfrastructure` | generic | +| odb | `aws_odb_cloud_vm_clusters` | `AWS::Odb::CloudVmCluster` | generic | +| odb | `aws_odb_db_nodes` | `AWS::Odb::DbNode` | generic | +| odb | `aws_odb_db_servers` | `AWS::Odb::DbServer` | generic | +| odb | `aws_odb_db_system_shapes` | `AWS::Odb::DbSystemShape` | generic | +| odb | `aws_odb_gi_versions` | `AWS::Odb::GiVersion` | generic | +| odb | `aws_odb_networks` | `AWS::Odb::Network` | generic | +| odb | `aws_odb_peering_connections` | `AWS::Odb::PeeringConnection` | generic | +| odb | `aws_odb_system_versions` | `AWS::Odb::SystemVersion` | generic | +| opensearch | `aws_opensearch_domain_auto_tunes` | `AWS::OpenSearchService::DomainAutoTune` | generic | +| opensearch | `aws_opensearch_domain_configs` | `AWS::OpenSearchService::DomainConfig` | generic | +| opensearch | `aws_opensearch_domain_data_sources` | `AWS::OpenSearchService::DomainDataSource` | generic | +| opensearch | `aws_opensearch_domain_health` | `AWS::OpenSearchService::DomainHealth` | generic | +| opensearch | `aws_opensearch_domain_maintenances` | `AWS::OpenSearchService::DomainMaintenance` | generic | +| opensearch | `aws_opensearch_domain_nodes` | `AWS::OpenSearchService::DomainNode` | generic | +| opensearch | `aws_opensearch_domain_packages` | `AWS::OpenSearchService::DomainPackage` | generic | +| opensearch | `aws_opensearch_domain_scheduled_actions` | `AWS::OpenSearchService::DomainScheduledAction` | generic | +| opensearch | `aws_opensearch_domains` | `AWS::OpenSearchService::Domain` | generic | +| opensearch | `aws_opensearch_inbound_connections` | `AWS::OpenSearchService::InboundConnection` | generic | +| opensearch | `aws_opensearch_outbound_connections` | `AWS::OpenSearchService::OutboundConnection` | generic | +| opensearch | `aws_opensearch_reserved_instances` | `AWS::OpenSearchService::ReservedInstance` | generic | +| opensearch | `aws_opensearch_versions` | `AWS::OpenSearchService::Version` | generic | +| opensearch | `aws_opensearch_vpc_endpoints` | `AWS::OpenSearchService::VpcEndpoint` | generic | +| organization | `aws_organization_resource_policies` | `AWS::Organization::ResourcePolicy` | generic | +| organizations | `aws_organizations` | `AWS::Organizations::Organization` | generic | +| organizations | `aws_organizations_account_parents` | `AWS::Organizations::AccountParent` | generic | +| organizations | `aws_organizations_accounts` | `AWS::Organizations::Account` | generic | +| organizations | `aws_organizations_delegated_administrators` | `AWS::Organizations::DelegatedAdministrator` | generic | +| organizations | `aws_organizations_delegated_services` | `AWS::Organizations::DelegatedService` | generic | +| organizations | `aws_organizations_organizational_unit_parents` | `AWS::Organizations::OrganizationalUnitParent` | generic | +| organizations | `aws_organizations_organizational_units` | `AWS::Organizations::OrganizationalUnit` | generic | +| organizations | `aws_organizations_policies` | `AWS::Organizations::Policy` | generic | +| organizations | `aws_organizations_policy_targets` | `AWS::Organizations::PolicyTarget` | generic | +| organizations | `aws_organizations_roots` | `AWS::Organizations::Root` | generic | +| pinpoint | `aws_pinpoint_apps` | `AWS::Pinpoint::App` | generic | +| pinpoint | `aws_pinpoint_campaign_versions` | `AWS::Pinpoint::CampaignVersion` | generic | +| pinpoint | `aws_pinpoint_campaigns` | `AWS::Pinpoint::Campaign` | generic | +| pinpoint | `aws_pinpoint_export_jobs` | `AWS::Pinpoint::ExportJob` | generic | +| pinpoint | `aws_pinpoint_import_jobs` | `AWS::Pinpoint::ImportJob` | generic | +| pinpoint | `aws_pinpoint_recommender_configurations` | `AWS::Pinpoint::RecommenderConfiguration` | generic | +| pinpoint | `aws_pinpoint_segments` | `AWS::Pinpoint::Segment` | generic | +| pinpoint | `aws_pinpoint_template_versions` | `AWS::Pinpoint::TemplateVersion` | generic | +| pinpoint | `aws_pinpoint_templates` | `AWS::Pinpoint::Template` | generic | +| polly | `aws_polly_lexicons` | `AWS::Polly::Lexicon` | generic | +| polly | `aws_polly_speech_synthesis_tasks` | `AWS::Polly::SpeechSynthesisTask` | generic | +| polly | `aws_polly_voices` | `AWS::Polly::Voice` | generic | +| quicksight | `aws_quicksight_analyses` | `AWS::QuickSight::Analysis` | generic | +| quicksight | `aws_quicksight_dashboards` | `AWS::QuickSight::Dashboard` | generic | +| quicksight | `aws_quicksight_data_sets` | `AWS::QuickSight::DataSet` | generic | +| quicksight | `aws_quicksight_data_sources` | `AWS::QuickSight::DataSource` | generic | +| quicksight | `aws_quicksight_folders` | `AWS::QuickSight::Folder` | generic | +| quicksight | `aws_quicksight_group_members` | `AWS::QuickSight::GroupMember` | generic | +| quicksight | `aws_quicksight_groups` | `AWS::QuickSight::Group` | generic | +| quicksight | `aws_quicksight_ingestions` | `AWS::QuickSight::Ingestion` | generic | +| quicksight | `aws_quicksight_templates` | `AWS::QuickSight::Template` | generic | +| quicksight | `aws_quicksight_users` | `AWS::QuickSight::User` | generic | +| ram | `aws_ram_principals` | `AWS::Ram::Principal` | generic | +| ram | `aws_ram_resource_share_associations` | `AWS::Ram::ResourceShareAssociation` | generic | +| ram | `aws_ram_resource_share_invitations` | `AWS::Ram::ResourceShareInvitation` | generic | +| ram | `aws_ram_resource_share_permissions` | `AWS::Ram::ResourceSharePermission` | generic | +| ram | `aws_ram_resource_shares` | `AWS::Ram::ResourceShare` | generic | +| ram | `aws_ram_resource_types` | `AWS::Ram::ResourceType` | generic | +| ram | `aws_ram_resources` | `AWS::Ram::Resource` | generic | +| rds | `aws_rds_certificates` | `AWS::RDS::Certificate` | generic | +| rds | `aws_rds_cluster_backtracks` | `AWS::RDS::ClusterBacktrack` | generic | +| rds | `aws_rds_cluster_parameter_group_parameters` | `AWS::RDS::ClusterParameterGroupParameter` | generic | +| rds | `aws_rds_cluster_parameter_groups` | `AWS::RDS::ClusterParameterGroup` | generic | +| rds | `aws_rds_cluster_parameters` | `AWS::RDS::ClusterParameter` | generic | +| rds | `aws_rds_cluster_snapshots` | `AWS::RDS::ClusterSnapshot` | generic | +| rds | `aws_rds_clusters` | `AWS::RDS::DBCluster` | generic | +| rds | `aws_rds_db_parameter_group_db_parameters` | `AWS::RDS::DbParameterGroupDbParameter` | generic | +| rds | `aws_rds_db_parameter_groups` | `AWS::RDS::DbParameterGroup` | generic | +| rds | `aws_rds_db_proxies` | `AWS::RDS::DBProxy` | generic | +| rds | `aws_rds_db_proxy_endpoints` | `AWS::RDS::DbProxyEndpoint` | generic | +| rds | `aws_rds_db_proxy_target_groups` | `AWS::RDS::DbProxyTargetGroup` | generic | +| rds | `aws_rds_db_proxy_targets` | `AWS::RDS::DbProxyTarget` | generic | +| rds | `aws_rds_db_security_groups` | `AWS::RDS::DbSecurityGroup` | generic | +| rds | `aws_rds_db_snapshots` | `AWS::RDS::DbSnapshot` | generic | +| rds | `aws_rds_engine_versions` | `AWS::RDS::EngineVersion` | generic | +| rds | `aws_rds_event_subscriptions` | `AWS::RDS::EventSubscription` | generic | +| rds | `aws_rds_events` | `AWS::RDS::Event` | generic | +| rds | `aws_rds_global_clusters` | `AWS::RDS::GlobalCluster` | generic | +| rds | `aws_rds_instance_resource_metrics` | `AWS::RDS::InstanceResourceMetric` | generic | +| rds | `aws_rds_instances` | `AWS::RDS::DBInstance` | generic | +| rds | `aws_rds_major_engine_versions` | `AWS::RDS::MajorEngineVersion` | generic | +| rds | `aws_rds_option_groups` | `AWS::RDS::OptionGroup` | generic | +| rds | `aws_rds_pending_maintenance_actions` | `AWS::RDS::PendingMaintenanceAction` | generic | +| rds | `aws_rds_reserved_instances` | `AWS::RDS::ReservedInstance` | generic | +| rds | `aws_rds_subnet_groups` | `AWS::RDS::DBSubnetGroup` | generic | +| redshift | `aws_redshift_cluster_parameter_groups` | `AWS::Redshift::ClusterParameterGroup` | generic | +| redshift | `aws_redshift_cluster_parameters` | `AWS::Redshift::ClusterParameter` | generic | +| redshift | `aws_redshift_clusters` | `AWS::Redshift::Cluster` | generic | +| redshift | `aws_redshift_data_shares` | `AWS::Redshift::DataShare` | generic | +| redshift | `aws_redshift_endpoint_accesses` | `AWS::Redshift::EndpointAccess` | generic | +| redshift | `aws_redshift_endpoint_authorizations` | `AWS::Redshift::EndpointAuthorization` | generic | +| redshift | `aws_redshift_event_subscriptions` | `AWS::Redshift::EventSubscription` | generic | +| redshift | `aws_redshift_events` | `AWS::Redshift::Event` | generic | +| redshift | `aws_redshift_reserved_nodes` | `AWS::Redshift::ReservedNode` | generic | +| redshift | `aws_redshift_snapshots` | `AWS::Redshift::Snapshot` | generic | +| redshift | `aws_redshift_subnet_groups` | `AWS::Redshift::SubnetGroup` | generic | +| regions | `aws_regions` | `-` | generic | +| rekognition | `aws_rekognition_collection_faces` | `AWS::Rekognition::CollectionFace` | generic | +| rekognition | `aws_rekognition_collections` | `AWS::Rekognition::Collection` | generic | +| rekognition | `aws_rekognition_media_analysis_jobs` | `AWS::Rekognition::MediaAnalysisJob` | generic | +| rekognition | `aws_rekognition_project_versions` | `AWS::Rekognition::ProjectVersion` | generic | +| rekognition | `aws_rekognition_projects` | `AWS::Rekognition::Project` | generic | +| rekognition | `aws_rekognition_stream_processors` | `AWS::Rekognition::StreamProcessor` | generic | +| resiliencehub | `aws_resiliencehub_alarm_recommendations` | `AWS::ResilienceHub::AlarmRecommendation` | generic | +| resiliencehub | `aws_resiliencehub_app_assessments` | `AWS::ResilienceHub::AppAssessment` | generic | +| resiliencehub | `aws_resiliencehub_app_component_compliances` | `AWS::ResilienceHub::AppComponentCompliance` | generic | +| resiliencehub | `aws_resiliencehub_app_version_resource_mappings` | `AWS::ResilienceHub::AppVersionResourceMapping` | generic | +| resiliencehub | `aws_resiliencehub_app_version_resources` | `AWS::ResilienceHub::AppVersionResource` | generic | +| resiliencehub | `aws_resiliencehub_app_versions` | `AWS::ResilienceHub::AppVersion` | generic | +| resiliencehub | `aws_resiliencehub_apps` | `AWS::ResilienceHub::App` | generic | +| resiliencehub | `aws_resiliencehub_component_recommendations` | `AWS::ResilienceHub::ComponentRecommendation` | generic | +| resiliencehub | `aws_resiliencehub_recommendation_templates` | `AWS::ResilienceHub::RecommendationTemplate` | generic | +| resiliencehub | `aws_resiliencehub_resiliency_policies` | `AWS::ResilienceHub::ResiliencyPolicy` | generic | +| resiliencehub | `aws_resiliencehub_sop_recommendations` | `AWS::ResilienceHub::SopRecommendation` | generic | +| resiliencehub | `aws_resiliencehub_suggested_resiliency_policies` | `AWS::ResilienceHub::SuggestedResiliencyPolicy` | generic | +| resiliencehub | `aws_resiliencehub_test_recommendations` | `AWS::ResilienceHub::TestRecommendation` | generic | +| resourcegroups | `aws_resourcegroups_resource_groups` | `AWS::ResourceGroups::ResourceGroup` | generic | +| route53 | `aws_route53_delegation_sets` | `AWS::Route53::DelegationSet` | generic | +| route53 | `aws_route53_domains` | `AWS::Route53::Domain` | generic | +| route53 | `aws_route53_health_checks` | `AWS::Route53::HealthCheck` | generic | +| route53 | `aws_route53_hosted_zone_dnssecs` | `AWS::Route53::HostedZoneDnssec` | generic | +| route53 | `aws_route53_hosted_zone_query_logging_configs` | `AWS::Route53::HostedZoneQueryLoggingConfig` | generic | +| route53 | `aws_route53_hosted_zone_resource_record_sets` | `AWS::Route53::HostedZoneResourceRecordSet` | generic | +| route53 | `aws_route53_hosted_zone_traffic_policy_instances` | `AWS::Route53::HostedZoneTrafficPolicyInstance` | generic | +| route53 | `aws_route53_hosted_zones` | `AWS::Route53::HostedZone` | generic | +| route53 | `aws_route53_operations` | `AWS::Route53::Operation` | generic | +| route53 | `aws_route53_profiles` | `AWS::Route53::Profile` | generic | +| route53 | `aws_route53_traffic_policies` | `AWS::Route53::TrafficPolicy` | generic | +| route53 | `aws_route53_traffic_policy_versions` | `AWS::Route53::TrafficPolicyVersion` | generic | +| route53recoverycontrolconfig | `aws_route53recoverycontrolconfig_clusters` | `AWS::Route53RecoveryControl::Cluster` | generic | +| route53recoverycontrolconfig | `aws_route53recoverycontrolconfig_control_panels` | `AWS::Route53RecoveryControl::ControlPanel` | generic | +| route53recoverycontrolconfig | `aws_route53recoverycontrolconfig_routing_controls` | `AWS::Route53RecoveryControl::RoutingControl` | generic | +| route53recoverycontrolconfig | `aws_route53recoverycontrolconfig_safety_rules` | `AWS::Route53RecoveryControl::SafetyRule` | generic | +| route53recoveryreadiness | `aws_route53recoveryreadiness_cells` | `AWS::Route53RecoveryReadiness::Cell` | generic | +| route53recoveryreadiness | `aws_route53recoveryreadiness_readiness_checks` | `AWS::Route53RecoveryReadiness::ReadinessCheck` | generic | +| route53recoveryreadiness | `aws_route53recoveryreadiness_recovery_groups` | `AWS::Route53RecoveryReadiness::RecoveryGroup` | generic | +| route53recoveryreadiness | `aws_route53recoveryreadiness_resource_sets` | `AWS::Route53RecoveryReadiness::ResourceSet` | generic | +| route53resolver | `aws_route53resolver_firewall_configs` | `AWS::Route53Resolver::FirewallConfig` | generic | +| route53resolver | `aws_route53resolver_firewall_domain_lists` | `AWS::Route53Resolver::FirewallDomainList` | generic | +| route53resolver | `aws_route53resolver_firewall_rule_group_associations` | `AWS::Route53Resolver::FirewallRuleGroupAssociation` | generic | +| route53resolver | `aws_route53resolver_firewall_rule_groups` | `AWS::Route53Resolver::FirewallRuleGroup` | generic | +| route53resolver | `aws_route53resolver_resolver_endpoints` | `AWS::Route53Resolver::ResolverEndpoint` | generic | +| route53resolver | `aws_route53resolver_resolver_query_log_config_associations` | `AWS::Route53Resolver::ResolverQueryLogConfigAssociation` | generic | +| route53resolver | `aws_route53resolver_resolver_query_log_configs` | `AWS::Route53Resolver::ResolverQueryLogConfig` | generic | +| route53resolver | `aws_route53resolver_resolver_rule_associations` | `AWS::Route53Resolver::ResolverRuleAssociation` | generic | +| route53resolver | `aws_route53resolver_resolver_rules` | `AWS::Route53Resolver::ResolverRule` | generic | +| s3 | `aws_s3_access_grant_instances` | `AWS::S3::AccessGrantInstance` | generic | +| s3 | `aws_s3_access_grants` | `AWS::S3::AccessGrant` | generic | +| s3 | `aws_s3_access_points` | `AWS::S3::AccessPoint` | generic | +| s3 | `aws_s3_accounts` | `AWS::S3::Account` | generic | +| s3 | `aws_s3_bucket_cors_rules` | `AWS::S3::BucketCorsRule` | generic | +| s3 | `aws_s3_bucket_encryption_rules` | `AWS::S3::BucketEncryptionRule` | generic | +| s3 | `aws_s3_bucket_grants` | `AWS::S3::BucketGrant` | generic | +| s3 | `aws_s3_bucket_lifecycles` | `AWS::S3::BucketLifecycle` | generic | +| s3 | `aws_s3_bucket_loggings` | `AWS::S3::BucketLogging` | generic | +| s3 | `aws_s3_bucket_notification_configurations` | `AWS::S3::BucketNotificationConfiguration` | generic | +| s3 | `aws_s3_bucket_object_grants` | `AWS::S3::BucketObjectGrant` | generic | +| s3 | `aws_s3_bucket_object_heads` | `AWS::S3::BucketObjectHead` | generic | +| s3 | `aws_s3_bucket_object_lock_configurations` | `AWS::S3::BucketObjectLockConfiguration` | generic | +| s3 | `aws_s3_bucket_objects` | `AWS::S3::BucketObject` | generic | +| s3 | `aws_s3_bucket_ownership_controls` | `AWS::S3::BucketOwnershipControl` | generic | +| s3 | `aws_s3_bucket_policies` | `AWS::S3::BucketPolicy` | generic | +| s3 | `aws_s3_bucket_public_access_blocks` | `AWS::S3::BucketPublicAccessBlock` | generic | +| s3 | `aws_s3_bucket_replications` | `AWS::S3::BucketReplication` | generic | +| s3 | `aws_s3_bucket_versionings` | `AWS::S3::BucketVersioning` | generic | +| s3 | `aws_s3_bucket_websites` | `AWS::S3::BucketWebsite` | generic | +| s3 | `aws_s3_buckets` | `AWS::S3::Bucket` | typed | +| s3 | `aws_s3_directory_buckets` | `AWS::S3::DirectoryBucket` | generic | +| s3 | `aws_s3_multi_region_access_points` | `AWS::S3::MultiRegionAccessPoint` | generic | +| s3 | `aws_s3_storage_lens_configurations` | `AWS::S3::StorageLensConfiguration` | generic | +| s3 | `aws_s3_storage_lens_groups` | `AWS::S3::StorageLensGroup` | generic | +| s3tables | `aws_s3tables_bucket_policies` | `AWS::S3tables::BucketPolicy` | generic | +| s3tables | `aws_s3tables_buckets` | `AWS::S3tables::Bucket` | generic | +| s3tables | `aws_s3tables_namespaces` | `AWS::S3tables::Namespace` | generic | +| s3vectors | `aws_s3vectors_bucket_policies` | `AWS::S3vectors::BucketPolicy` | generic | +| s3vectors | `aws_s3vectors_buckets` | `AWS::S3vectors::Bucket` | generic | +| s3vectors | `aws_s3vectors_indexes` | `AWS::S3vectors::Index` | generic | +| sagemaker | `aws_sagemaker_apps` | `AWS::SageMaker::App` | generic | +| sagemaker | `aws_sagemaker_domains` | `AWS::SageMaker::Domain` | generic | +| sagemaker | `aws_sagemaker_endpoint_configurations` | `AWS::SageMaker::EndpointConfiguration` | generic | +| sagemaker | `aws_sagemaker_endpoints` | `AWS::SageMaker::Endpoint` | generic | +| sagemaker | `aws_sagemaker_hyperparameter_tuning_jobs` | `AWS::SageMaker::HyperparameterTuningJob` | generic | +| sagemaker | `aws_sagemaker_image_versions` | `AWS::SageMaker::ImageVersion` | generic | +| sagemaker | `aws_sagemaker_images` | `AWS::SageMaker::Image` | generic | +| sagemaker | `aws_sagemaker_mlflow_apps` | `AWS::SageMaker::MlflowApp` | generic | +| sagemaker | `aws_sagemaker_mlflow_tracking_servers` | `AWS::SageMaker::MlflowTrackingServer` | generic | +| sagemaker | `aws_sagemaker_models` | `AWS::SageMaker::Model` | generic | +| sagemaker | `aws_sagemaker_notebook_instance_lifecycle_configs` | `AWS::SageMaker::NotebookInstanceLifecycleConfig` | generic | +| sagemaker | `aws_sagemaker_notebook_instances` | `AWS::SageMaker::NotebookInstance` | generic | +| sagemaker | `aws_sagemaker_processing_jobs` | `AWS::SageMaker::ProcessingJob` | generic | +| sagemaker | `aws_sagemaker_spaces` | `AWS::SageMaker::Space` | generic | +| sagemaker | `aws_sagemaker_studio_lifecycle_configs` | `AWS::SageMaker::StudioLifecycleConfig` | generic | +| sagemaker | `aws_sagemaker_training_jobs` | `AWS::SageMaker::TrainingJob` | generic | +| sagemaker | `aws_sagemaker_transform_jobs` | `AWS::SageMaker::TransformJob` | generic | +| sagemaker | `aws_sagemaker_user_profiles` | `AWS::SageMaker::UserProfile` | generic | +| savingsplans | `aws_savingsplans_plans` | `AWS::SavingsPlans::Plan` | generic | +| scheduler | `aws_scheduler_schedule_groups` | `AWS::Scheduler::ScheduleGroup` | generic | +| scheduler | `aws_scheduler_schedules` | `AWS::Scheduler::Schedule` | generic | +| secretsmanager | `aws_secretsmanager_secret_versions` | `AWS::SecretsManager::SecretVersion` | generic | +| secretsmanager | `aws_secretsmanager_secrets` | `AWS::SecretsManager::Secret` | generic | +| securityhub | `aws_securityhub_enabled_standards` | `AWS::SecurityHub::EnabledStandard` | generic | +| securityhub | `aws_securityhub_findings` | `AWS::SecurityHub::Finding` | generic | +| securityhub | `aws_securityhub_hubs` | `AWS::SecurityHub::Hub` | generic | +| servicecatalog | `aws_servicecatalog_launch_paths` | `AWS::ServiceCatalog::LaunchPath` | generic | +| servicecatalog | `aws_servicecatalog_portfolios` | `AWS::ServiceCatalog::Portfolio` | generic | +| servicecatalog | `aws_servicecatalog_products` | `AWS::ServiceCatalog::Product` | generic | +| servicecatalog | `aws_servicecatalog_provisioned_products` | `AWS::ServiceCatalog::ProvisionedProduct` | generic | +| servicecatalog | `aws_servicecatalog_provisioning_artifacts` | `AWS::ServiceCatalog::ProvisioningArtifact` | generic | +| servicecatalog | `aws_servicecatalog_provisioning_parameters` | `AWS::ServiceCatalog::ProvisioningParameter` | generic | +| servicediscovery | `aws_servicediscovery_instances` | `AWS::ServiceDiscovery::Instance` | generic | +| servicediscovery | `aws_servicediscovery_namespaces` | `AWS::ServiceDiscovery::Namespace` | generic | +| servicediscovery | `aws_servicediscovery_services` | `AWS::ServiceDiscovery::Service` | generic | +| servicequotas | `aws_servicequotas_awsdefaultservicequotas` | `AWS::ServiceQuotas::Awsdefaultservicequota` | generic | +| servicequotas | `aws_servicequotas_quota_utilizations` | `AWS::ServiceQuotas::QuotaUtilization` | generic | +| servicequotas | `aws_servicequotas_quotas` | `AWS::ServiceQuotas::Quota` | generic | +| servicequotas | `aws_servicequotas_services` | `AWS::ServiceQuotas::Service` | generic | +| ses | `aws_ses_active_receipt_rule_sets` | `AWS::SES::ActiveReceiptRuleSet` | generic | +| ses | `aws_ses_configuration_set_event_destinations` | `AWS::SES::ConfigurationSetEventDestination` | generic | +| ses | `aws_ses_configuration_sets` | `AWS::SES::ConfigurationSet` | generic | +| ses | `aws_ses_contact_lists` | `AWS::SES::ContactList` | generic | +| ses | `aws_ses_custom_verification_email_templates` | `AWS::SES::CustomVerificationEmailTemplate` | generic | +| ses | `aws_ses_identities` | `AWS::SES::Identity` | generic | +| ses | `aws_ses_suppressed_destinations` | `AWS::SES::SuppressedDestination` | generic | +| ses | `aws_ses_templates` | `AWS::SES::Template` | generic | +| shield | `aws_shield_attacks` | `AWS::Shield::Attack` | generic | +| shield | `aws_shield_protection_groups` | `AWS::Shield::ProtectionGroup` | generic | +| shield | `aws_shield_protections` | `AWS::Shield::Protection` | generic | +| shield | `aws_shield_subscriptions` | `AWS::Shield::Subscription` | generic | +| signer | `aws_signer_signing_profiles` | `AWS::Signer::SigningProfile` | generic | +| snowball | `aws_snowball_addresses` | `AWS::Snowball::Address` | generic | +| snowball | `aws_snowball_cluster_jobs` | `AWS::Snowball::ClusterJob` | generic | +| snowball | `aws_snowball_clusters` | `AWS::Snowball::Cluster` | generic | +| snowball | `aws_snowball_compatible_images` | `AWS::Snowball::CompatibleImage` | generic | +| snowball | `aws_snowball_jobs` | `AWS::Snowball::Job` | generic | +| snowball | `aws_snowball_long_term_pricing` | `AWS::Snowball::LongTermPricing` | generic | +| snowball | `aws_snowball_pickup_locations` | `AWS::Snowball::PickupLocation` | generic | +| sns | `aws_sns_subscriptions` | `AWS::SNS::Subscription` | generic | +| sns | `aws_sns_topic_data_protection_policies` | `AWS::SNS::TopicDataProtectionPolicy` | generic | +| sns | `aws_sns_topics` | `AWS::SNS::Topic` | generic | +| sqs | `aws_sqs_queues` | `AWS::SQS::Queue` | generic | +| ssm | `aws_ssm_associations` | `AWS::SSM::Association` | generic | +| ssm | `aws_ssm_command_invocations` | `AWS::SSM::CommandInvocation` | generic | +| ssm | `aws_ssm_compliance_summary_items` | `AWS::SSM::ComplianceSummaryItem` | generic | +| ssm | `aws_ssm_document_contents` | `AWS::SSM::DocumentContent` | generic | +| ssm | `aws_ssm_document_versions` | `AWS::SSM::DocumentVersion` | generic | +| ssm | `aws_ssm_documents` | `AWS::SSM::Document` | generic | +| ssm | `aws_ssm_instance_compliance_items` | `AWS::SSM::InstanceComplianceItem` | generic | +| ssm | `aws_ssm_instance_patch_states` | `AWS::SSM::InstancePatchState` | generic | +| ssm | `aws_ssm_instance_patches` | `AWS::SSM::InstancePatch` | generic | +| ssm | `aws_ssm_instances` | `AWS::SSM::Instance` | generic | +| ssm | `aws_ssm_inventories` | `AWS::SSM::Inventory` | generic | +| ssm | `aws_ssm_inventory_entries` | `AWS::SSM::InventoryEntry` | generic | +| ssm | `aws_ssm_inventory_schemas` | `AWS::SSM::InventorySchema` | generic | +| ssm | `aws_ssm_maintenance_window_executions` | `AWS::SSM::MaintenanceWindowExecution` | generic | +| ssm | `aws_ssm_maintenance_window_schedules` | `AWS::SSM::MaintenanceWindowSchedule` | generic | +| ssm | `aws_ssm_maintenance_window_targets` | `AWS::SSM::MaintenanceWindowTarget` | generic | +| ssm | `aws_ssm_maintenance_window_tasks` | `AWS::SSM::MaintenanceWindowTask` | generic | +| ssm | `aws_ssm_maintenance_windows` | `AWS::SSM::MaintenanceWindow` | generic | +| ssm | `aws_ssm_parameters` | `AWS::SSM::Parameter` | generic | +| ssm | `aws_ssm_patch_baselines` | `AWS::SSM::PatchBaseline` | generic | +| ssm | `aws_ssm_sessions` | `AWS::SSM::Session` | generic | +| ssmincidents | `aws_ssmincidents_incident_findings` | `AWS::SSMIncidents::IncidentFinding` | generic | +| ssmincidents | `aws_ssmincidents_incident_related_items` | `AWS::SSMIncidents::IncidentRelatedItem` | generic | +| ssmincidents | `aws_ssmincidents_incident_timeline_events` | `AWS::SSMIncidents::IncidentTimelineEvent` | generic | +| ssmincidents | `aws_ssmincidents_incidents` | `AWS::SSMIncidents::Incident` | generic | +| ssmincidents | `aws_ssmincidents_response_plans` | `AWS::SSMIncidents::ResponsePlan` | generic | +| ssoadmin | `aws_ssoadmin_instances` | `AWS::SSO::Instance` | generic | +| ssoadmin | `aws_ssoadmin_permission_set_account_assignments` | `AWS::SSO::PermissionSetAccountAssignment` | generic | +| ssoadmin | `aws_ssoadmin_permission_set_customer_managed_policies` | `AWS::SSO::PermissionSetCustomerManagedPolicy` | generic | +| ssoadmin | `aws_ssoadmin_permission_set_inline_policies` | `AWS::SSO::PermissionSetInlinePolicy` | generic | +| ssoadmin | `aws_ssoadmin_permission_set_managed_policies` | `AWS::SSO::PermissionSetManagedPolicy` | generic | +| ssoadmin | `aws_ssoadmin_permission_set_permissions_boundaries` | `AWS::SSO::PermissionSetPermissionsBoundary` | generic | +| ssoadmin | `aws_ssoadmin_permission_sets` | `AWS::SSO::PermissionSet` | generic | +| ssoadmin | `aws_ssoadmin_trusted_token_issuers` | `AWS::SSO::TrustedTokenIssuer` | generic | +| stepfunctions | `aws_stepfunctions_activities` | `AWS::Stepfunctions::Activity` | generic | +| stepfunctions | `aws_stepfunctions_executions` | `AWS::Stepfunctions::Execution` | generic | +| stepfunctions | `aws_stepfunctions_map_run_executions` | `AWS::Stepfunctions::MapRunExecution` | generic | +| stepfunctions | `aws_stepfunctions_map_runs` | `AWS::Stepfunctions::MapRun` | generic | +| stepfunctions | `aws_stepfunctions_state_machines` | `AWS::StepFunctions::StateMachine` | generic | +| storagegateway | `aws_storagegateway_automatic_tape_creation_policies` | `AWS::StorageGateway::AutomaticTapeCreationPolicy` | generic | +| storagegateway | `aws_storagegateway_cache_reports` | `AWS::StorageGateway::CacheReport` | generic | +| storagegateway | `aws_storagegateway_file_shares` | `AWS::StorageGateway::FileShare` | generic | +| storagegateway | `aws_storagegateway_file_system_associations` | `AWS::StorageGateway::FileSystemAssociation` | generic | +| storagegateway | `aws_storagegateway_gateways` | `AWS::StorageGateway::Gateway` | generic | +| storagegateway | `aws_storagegateway_local_disks` | `AWS::StorageGateway::LocalDisk` | generic | +| storagegateway | `aws_storagegateway_tape_pools` | `AWS::StorageGateway::TapePool` | generic | +| storagegateway | `aws_storagegateway_tapes` | `AWS::StorageGateway::Tape` | generic | +| storagegateway | `aws_storagegateway_volume_recovery_points` | `AWS::StorageGateway::VolumeRecoveryPoint` | generic | +| storagegateway | `aws_storagegateway_volumes` | `AWS::StorageGateway::Volume` | generic | +| support | `aws_support_case_communications` | `AWS::Support::CaseCommunication` | generic | +| support | `aws_support_cases` | `AWS::Support::Cas` | generic | +| support | `aws_support_services` | `AWS::Support::Service` | generic | +| support | `aws_support_severity_levels` | `AWS::Support::SeverityLevel` | generic | +| support | `aws_support_trusted_advisor_check_results` | `AWS::Support::TrustedAdvisorCheckResult` | generic | +| support | `aws_support_trusted_advisor_check_summaries` | `AWS::Support::TrustedAdvisorCheckSummary` | generic | +| support | `aws_support_trusted_advisor_checks` | `AWS::Support::TrustedAdvisorCheck` | generic | +| swf | `aws_swf_activity_types` | `AWS::SWF::ActivityType` | generic | +| swf | `aws_swf_closed_workflow_executions` | `AWS::SWF::ClosedWorkflowExecution` | generic | +| swf | `aws_swf_domains` | `AWS::SWF::Domain` | generic | +| swf | `aws_swf_open_workflow_executions` | `AWS::SWF::OpenWorkflowExecution` | generic | +| swf | `aws_swf_workflow_types` | `AWS::SWF::WorkflowType` | generic | +| timestream | `aws_timestream_databases` | `AWS::Timestream::Databas` | generic | +| timestream | `aws_timestream_tables` | `AWS::Timestream::Table` | generic | +| transcribe | `aws_transcribe_call_analytics_categories` | `AWS::Transcribe::CallAnalyticsCategory` | generic | +| transcribe | `aws_transcribe_call_analytics_jobs` | `AWS::Transcribe::CallAnalyticsJob` | generic | +| transcribe | `aws_transcribe_language_models` | `AWS::Transcribe::LanguageModel` | generic | +| transcribe | `aws_transcribe_medical_scribe_jobs` | `AWS::Transcribe::MedicalScribeJob` | generic | +| transcribe | `aws_transcribe_medical_transcription_jobs` | `AWS::Transcribe::MedicalTranscriptionJob` | generic | +| transcribe | `aws_transcribe_medical_vocabularies` | `AWS::Transcribe::MedicalVocabulary` | generic | +| transcribe | `aws_transcribe_transcription_jobs` | `AWS::Transcribe::TranscriptionJob` | generic | +| transcribe | `aws_transcribe_vocabularies` | `AWS::Transcribe::Vocabulary` | generic | +| transcribe | `aws_transcribe_vocabulary_filters` | `AWS::Transcribe::VocabularyFilter` | generic | +| transfer | `aws_transfer_agreements` | `AWS::Transfer::Agreement` | generic | +| transfer | `aws_transfer_certificates` | `AWS::Transfer::Certificate` | generic | +| transfer | `aws_transfer_connectors` | `AWS::Transfer::Connector` | generic | +| transfer | `aws_transfer_profiles` | `AWS::Transfer::Profile` | generic | +| transfer | `aws_transfer_servers` | `AWS::Transfer::Server` | generic | +| transfer | `aws_transfer_users` | `AWS::Transfer::User` | generic | +| transfer | `aws_transfer_workflows` | `AWS::Transfer::Workflow` | generic | +| trustedadvisor | `aws_trustedadvisor_organization_recommendation_accounts` | `AWS::Trustedadvisor::OrganizationRecommendationAccount` | generic | +| trustedadvisor | `aws_trustedadvisor_organization_recommendation_resources` | `AWS::Trustedadvisor::OrganizationRecommendationResource` | generic | +| trustedadvisor | `aws_trustedadvisor_organization_recommendations` | `AWS::Trustedadvisor::OrganizationRecommendation` | generic | +| trustedadvisor | `aws_trustedadvisor_recommendation_resources` | `AWS::Trustedadvisor::RecommendationResource` | generic | +| trustedadvisor | `aws_trustedadvisor_recommendations` | `AWS::Trustedadvisor::Recommendation` | generic | +| vpc | `aws_vpc_lattice_resource_configurations` | `AWS::Vpc::LatticeResourceConfiguration` | generic | +| vpc | `aws_vpc_lattice_resource_gateways` | `AWS::Vpc::LatticeResourceGateway` | generic | +| vpc | `aws_vpc_lattice_service_networks` | `AWS::Vpc::LatticeServiceNetwork` | generic | +| vpc | `aws_vpc_lattice_services` | `AWS::Vpc::LatticeService` | generic | +| waf | `aws_waf_ipsets` | `AWS::WAF::Ipset` | generic | +| waf | `aws_waf_rule_groups` | `AWS::WAF::RuleGroup` | generic | +| waf | `aws_waf_rules` | `AWS::WAF::Rule` | generic | +| waf | `aws_waf_subscribed_rule_groups` | `AWS::WAF::SubscribedRuleGroup` | generic | +| waf | `aws_waf_web_acls` | `AWS::WAF::WebAcl` | generic | +| wafregional | `aws_wafregional_rate_based_rules` | `AWS::WAFRegional::RateBasedRule` | generic | +| wafregional | `aws_wafregional_rule_groups` | `AWS::WAFRegional::RuleGroup` | generic | +| wafregional | `aws_wafregional_rules` | `AWS::WAFRegional::Rule` | generic | +| wafregional | `aws_wafregional_web_acls` | `AWS::WAFRegional::WebAcl` | generic | +| wafv2 | `aws_wafv2_ipsets` | `AWS::WAFv2::Ipset` | generic | +| wafv2 | `aws_wafv2_managed_rule_groups` | `AWS::WAFv2::ManagedRuleGroup` | generic | +| wafv2 | `aws_wafv2_regex_pattern_sets` | `AWS::WAFv2::RegexPatternSet` | generic | +| wafv2 | `aws_wafv2_rule_groups` | `AWS::WAFv2::RuleGroup` | generic | +| wafv2 | `aws_wafv2_web_acls` | `AWS::WAFv2::WebACL` | generic | +| wellarchitected | `aws_wellarchitected_lens_review_improvements` | `AWS::WellArchitected::LensReviewImprovement` | generic | +| wellarchitected | `aws_wellarchitected_lens_reviews` | `AWS::WellArchitected::LensReview` | generic | +| wellarchitected | `aws_wellarchitected_lenses` | `AWS::WellArchitected::Lens` | generic | +| wellarchitected | `aws_wellarchitected_share_invitations` | `AWS::WellArchitected::ShareInvitation` | generic | +| wellarchitected | `aws_wellarchitected_workload_milestones` | `AWS::WellArchitected::WorkloadMilestone` | generic | +| wellarchitected | `aws_wellarchitected_workload_shares` | `AWS::WellArchitected::WorkloadShare` | generic | +| wellarchitected | `aws_wellarchitected_workloads` | `AWS::WellArchitected::Workload` | generic | +| workspaces | `aws_workspaces_connection_alias_permissions` | `AWS::WorkSpaces::ConnectionAliasPermission` | generic | +| workspaces | `aws_workspaces_connection_aliases` | `AWS::WorkSpaces::ConnectionAlias` | generic | +| workspaces | `aws_workspaces_directories` | `AWS::WorkSpaces::Directory` | generic | +| workspaces | `aws_workspaces_workspaces` | `AWS::WorkSpaces::Workspace` | generic | +| xray | `aws_xray_encryption_configs` | `AWS::XRay::EncryptionConfig` | generic | +| xray | `aws_xray_groups` | `AWS::XRay::Group` | generic | +| xray | `aws_xray_resource_policies` | `AWS::XRay::ResourcePolicy` | generic | +| xray | `aws_xray_sampling_rules` | `AWS::XRay::SamplingRule` | generic | + diff --git a/docs/authoring/indexed-resources/azure-resource-catalog.md b/docs/authoring/indexed-resources/azure-resource-catalog.md index 7b89ecd8d..87b562d0f 100644 --- a/docs/authoring/indexed-resources/azure-resource-catalog.md +++ b/docs/authoring/indexed-resources/azure-resource-catalog.md @@ -2,7 +2,7 @@ Every Azure resource type the native `azureapi` indexer can discover. This page is the companion catalog for [`azure.md`](./azure.md); see that page for how to enable the indexer, what data each row carries, and the typed/generic distinction. -_619 resource types - 25 typed (rich-payload), 594 generic (basic envelope). Generated 2026-05-28 from `src/indexers/azure_resource_type_registry.yaml`._ +_619 resource types - 25 typed (rich-payload), 594 generic (basic envelope). Generated 2026-07-02 from `src/indexers/azure_resource_type_registry.yaml`._ _Regenerate with `python scripts/azure/dump_azure_resource_catalog.py` after touching the registry or overrides; do not hand-edit this file._ diff --git a/docs/authoring/indexed-resources/gcp-resource-catalog.md b/docs/authoring/indexed-resources/gcp-resource-catalog.md new file mode 100644 index 000000000..473c44e9d --- /dev/null +++ b/docs/authoring/indexed-resources/gcp-resource-catalog.md @@ -0,0 +1,418 @@ +# GCP resource catalog + +Every GCP resource type the native `gcpapi` indexer can discover. This page is the companion catalog for [`gcp.md`](./gcp.md); see that page for how to enable the indexer, what data each row carries, and the typed/generic distinction. + +_404 resource types - 13 typed (SDK collectors), 391 generic (Cloud Asset Inventory pass). Generated 2026-07-02 from `src/indexers/gcp_resource_type_registry.yaml`._ + +_Regenerate with `python scripts/gcp/dump_gcp_resource_catalog.py` after touching the registry or overrides; do not hand-edit this file._ + +* `typed` - hand-written `google-cloud-*` collector; runs without CAI. +* `generic` - discoverable via the optional Cloud Asset Inventory accelerator when a CAI asset type is mapped. + +| Service | CloudQuery table name | CAI asset type | Tier | +| --- | --- | --- | --- | +| accessapproval | `gcp_accessapproval_folder_approval_requests` | `accessapproval.googleapis.com/FolderApprovalRequest` | generic | +| accessapproval | `gcp_accessapproval_folder_service_accounts` | `accessapproval.googleapis.com/FolderServiceAccount` | generic | +| accessapproval | `gcp_accessapproval_folder_settings` | `accessapproval.googleapis.com/FolderSetting` | generic | +| accessapproval | `gcp_accessapproval_organization_approval_requests` | `accessapproval.googleapis.com/OrganizationApprovalRequest` | generic | +| accessapproval | `gcp_accessapproval_organization_service_accounts` | `accessapproval.googleapis.com/OrganizationServiceAccount` | generic | +| accessapproval | `gcp_accessapproval_organization_settings` | `accessapproval.googleapis.com/OrganizationSetting` | generic | +| accessapproval | `gcp_accessapproval_project_approval_requests` | `accessapproval.googleapis.com/ProjectApprovalRequest` | generic | +| accessapproval | `gcp_accessapproval_project_service_accounts` | `accessapproval.googleapis.com/ProjectServiceAccount` | generic | +| accessapproval | `gcp_accessapproval_project_settings` | `accessapproval.googleapis.com/ProjectSetting` | generic | +| aiplatform | `gcp_aiplatform_batch_prediction_jobs` | `aiplatform.googleapis.com/BatchPredictionJob` | generic | +| aiplatform | `gcp_aiplatform_custom_jobs` | `aiplatform.googleapis.com/CustomJob` | generic | +| aiplatform | `gcp_aiplatform_dataset_locations` | `aiplatform.googleapis.com/DatasetLocation` | generic | +| aiplatform | `gcp_aiplatform_datasets` | `aiplatform.googleapis.com/Dataset` | generic | +| aiplatform | `gcp_aiplatform_endpoint_locations` | `aiplatform.googleapis.com/EndpointLocation` | generic | +| aiplatform | `gcp_aiplatform_endpoints` | `aiplatform.googleapis.com/Endpoint` | generic | +| aiplatform | `gcp_aiplatform_featurestore_locations` | `aiplatform.googleapis.com/FeaturestoreLocation` | generic | +| aiplatform | `gcp_aiplatform_featurestores` | `aiplatform.googleapis.com/Featurestore` | generic | +| aiplatform | `gcp_aiplatform_hyperparameter_tuning_jobs` | `aiplatform.googleapis.com/HyperparameterTuningJob` | generic | +| aiplatform | `gcp_aiplatform_index_endpoints` | `aiplatform.googleapis.com/IndexEndpoint` | generic | +| aiplatform | `gcp_aiplatform_index_locations` | `aiplatform.googleapis.com/IndexLocation` | generic | +| aiplatform | `gcp_aiplatform_indexendpoint_locations` | `aiplatform.googleapis.com/IndexendpointLocation` | generic | +| aiplatform | `gcp_aiplatform_indexes` | `aiplatform.googleapis.com/Index` | generic | +| aiplatform | `gcp_aiplatform_job_locations` | `aiplatform.googleapis.com/JobLocation` | generic | +| aiplatform | `gcp_aiplatform_metadata_locations` | `aiplatform.googleapis.com/MetadataLocation` | generic | +| aiplatform | `gcp_aiplatform_metadata_stores` | `aiplatform.googleapis.com/MetadataStore` | generic | +| aiplatform | `gcp_aiplatform_model_deployment_monitoring_jobs` | `aiplatform.googleapis.com/ModelDeploymentMonitoringJob` | generic | +| aiplatform | `gcp_aiplatform_model_locations` | `aiplatform.googleapis.com/ModelLocation` | generic | +| aiplatform | `gcp_aiplatform_models` | `aiplatform.googleapis.com/Model` | generic | +| aiplatform | `gcp_aiplatform_operations` | `aiplatform.googleapis.com/Operation` | generic | +| aiplatform | `gcp_aiplatform_pipeline_jobs` | `aiplatform.googleapis.com/PipelineJob` | generic | +| aiplatform | `gcp_aiplatform_pipeline_locations` | `aiplatform.googleapis.com/PipelineLocation` | generic | +| aiplatform | `gcp_aiplatform_specialist_pools` | `aiplatform.googleapis.com/SpecialistPool` | generic | +| aiplatform | `gcp_aiplatform_specialistpool_locations` | `aiplatform.googleapis.com/SpecialistpoolLocation` | generic | +| aiplatform | `gcp_aiplatform_studies` | `aiplatform.googleapis.com/Study` | generic | +| aiplatform | `gcp_aiplatform_tensorboard_locations` | `aiplatform.googleapis.com/TensorboardLocation` | generic | +| aiplatform | `gcp_aiplatform_tensorboards` | `aiplatform.googleapis.com/Tensorboard` | generic | +| aiplatform | `gcp_aiplatform_training_pipelines` | `aiplatform.googleapis.com/TrainingPipeline` | generic | +| aiplatform | `gcp_aiplatform_vizier_locations` | `aiplatform.googleapis.com/VizierLocation` | generic | +| alloydb | `gcp_alloydb_clusters` | `alloydb.googleapis.com/Cluster` | generic | +| alloydb | `gcp_alloydb_instances` | `alloydb.googleapis.com/Instance` | generic | +| apigateway | `gcp_apigateway_apis` | `apigateway.googleapis.com/Api` | generic | +| apigateway | `gcp_apigateway_gateways` | `apigateway.googleapis.com/Gateway` | generic | +| apikeys | `gcp_apikeys_keys` | `apikeys.googleapis.com/Key` | generic | +| appengine | `gcp_appengine_apps` | `appengine.googleapis.com/Application` | generic | +| appengine | `gcp_appengine_authorized_certificates` | `appengine.googleapis.com/AuthorizedCertificate` | generic | +| appengine | `gcp_appengine_authorized_domains` | `appengine.googleapis.com/AuthorizedDomain` | generic | +| appengine | `gcp_appengine_domain_mappings` | `appengine.googleapis.com/DomainMapping` | generic | +| appengine | `gcp_appengine_firewall_ingress_rules` | `appengine.googleapis.com/FirewallIngressRule` | generic | +| appengine | `gcp_appengine_instances` | `appengine.googleapis.com/Instance` | generic | +| appengine | `gcp_appengine_services` | `appengine.googleapis.com/Service` | generic | +| appengine | `gcp_appengine_versions` | `appengine.googleapis.com/Version` | generic | +| applicationintegration | `gcp_applicationintegration_authconfigs` | `applicationintegration.googleapis.com/Authconfig` | generic | +| applicationintegration | `gcp_applicationintegration_certificates` | `applicationintegration.googleapis.com/Certificate` | generic | +| applicationintegration | `gcp_applicationintegration_integration_execution_suspensions` | `applicationintegration.googleapis.com/IntegrationExecutionSuspension` | generic | +| applicationintegration | `gcp_applicationintegration_integration_executions` | `applicationintegration.googleapis.com/IntegrationExecution` | generic | +| applicationintegration | `gcp_applicationintegration_integration_versions` | `applicationintegration.googleapis.com/IntegrationVersion` | generic | +| applicationintegration | `gcp_applicationintegration_integrations` | `applicationintegration.googleapis.com/Integration` | generic | +| applicationintegration | `gcp_applicationintegration_sfdc_channels` | `applicationintegration.googleapis.com/SfdcChannel` | generic | +| applicationintegration | `gcp_applicationintegration_sfdc_instances` | `applicationintegration.googleapis.com/SfdcInstance` | generic | +| artifactregistry | `gcp_artifactregistry_docker_images` | `artifactregistry.googleapis.com/DockerImage` | generic | +| artifactregistry | `gcp_artifactregistry_files` | `artifactregistry.googleapis.com/File` | generic | +| artifactregistry | `gcp_artifactregistry_locations` | `artifactregistry.googleapis.com/Location` | generic | +| artifactregistry | `gcp_artifactregistry_packages` | `artifactregistry.googleapis.com/Package` | generic | +| artifactregistry | `gcp_artifactregistry_repositories` | `artifactregistry.googleapis.com/Repository` | generic | +| artifactregistry | `gcp_artifactregistry_tags` | `artifactregistry.googleapis.com/Tag` | generic | +| artifactregistry | `gcp_artifactregistry_versions` | `artifactregistry.googleapis.com/Version` | generic | +| baremetalsolution | `gcp_baremetalsolution_instances` | `baremetalsolution.googleapis.com/Instance` | generic | +| baremetalsolution | `gcp_baremetalsolution_networks` | `baremetalsolution.googleapis.com/Network` | generic | +| baremetalsolution | `gcp_baremetalsolution_nfs_shares` | `baremetalsolution.googleapis.com/NfsShare` | generic | +| baremetalsolution | `gcp_baremetalsolution_volume_luns` | `baremetalsolution.googleapis.com/VolumeLun` | generic | +| baremetalsolution | `gcp_baremetalsolution_volumes` | `baremetalsolution.googleapis.com/Volume` | generic | +| batch | `gcp_batch_jobs` | `batch.googleapis.com/Job` | generic | +| batch | `gcp_batch_task_groups` | `batch.googleapis.com/TaskGroup` | generic | +| batch | `gcp_batch_tasks` | `batch.googleapis.com/Task` | generic | +| beyondcorp | `gcp_beyondcorp_app_connections` | `beyondcorp.googleapis.com/AppConnection` | generic | +| beyondcorp | `gcp_beyondcorp_app_connectors` | `beyondcorp.googleapis.com/AppConnector` | generic | +| beyondcorp | `gcp_beyondcorp_app_gateways` | `beyondcorp.googleapis.com/AppGateway` | generic | +| bigquery | `gcp_bigquery_datasets` | `bigquery.googleapis.com/Dataset` | generic | +| bigquery | `gcp_bigquery_tables` | `bigquery.googleapis.com/Table` | generic | +| bigquerydatatransfer | `gcp_bigquerydatatransfer_configs` | `bigquerydatatransfer.googleapis.com/Config` | generic | +| bigquerydatatransfer | `gcp_bigquerydatatransfer_datasources` | `bigquerydatatransfer.googleapis.com/Datasource` | generic | +| bigquerydatatransfer | `gcp_bigquerydatatransfer_locations` | `bigquerydatatransfer.googleapis.com/Location` | generic | +| bigquerydatatransfer | `gcp_bigquerydatatransfer_logs` | `bigquerydatatransfer.googleapis.com/Log` | generic | +| bigquerydatatransfer | `gcp_bigquerydatatransfer_runs` | `bigquerydatatransfer.googleapis.com/Run` | generic | +| bigtableadmin | `gcp_bigtableadmin_app_profiles` | `bigtableadmin.googleapis.com/AppProfile` | generic | +| bigtableadmin | `gcp_bigtableadmin_backups` | `bigtableadmin.googleapis.com/Backup` | generic | +| bigtableadmin | `gcp_bigtableadmin_clusters` | `bigtableadmin.googleapis.com/Cluster` | generic | +| bigtableadmin | `gcp_bigtableadmin_instances` | `bigtableadmin.googleapis.com/Instance` | generic | +| bigtableadmin | `gcp_bigtableadmin_tables` | `bigtableadmin.googleapis.com/Table` | generic | +| billing | `gcp_billing_billing_account_subaccounts` | `billing.googleapis.com/BillingAccountSubaccount` | generic | +| billing | `gcp_billing_billing_accounts` | `-` | generic | +| billing | `gcp_billing_budgets` | `billing.googleapis.com/Budget` | generic | +| billing | `gcp_billing_projects` | `billing.googleapis.com/Project` | generic | +| billing | `gcp_billing_service_skus` | `billing.googleapis.com/ServiceSku` | generic | +| billing | `gcp_billing_services` | `billing.googleapis.com/Service` | generic | +| binaryauthorization | `gcp_binaryauthorization_assertors` | `binaryauthorization.googleapis.com/Assertor` | generic | +| certificatemanager | `gcp_certificatemanager_certificate_issuance_configs` | `certificatemanager.googleapis.com/CertificateIssuanceConfig` | generic | +| certificatemanager | `gcp_certificatemanager_certificate_map_entries` | `certificatemanager.googleapis.com/CertificateMapEntry` | generic | +| certificatemanager | `gcp_certificatemanager_certificate_maps` | `certificatemanager.googleapis.com/CertificateMap` | generic | +| certificatemanager | `gcp_certificatemanager_certificates` | `certificatemanager.googleapis.com/Certificate` | generic | +| certificatemanager | `gcp_certificatemanager_dns_authorizations` | `certificatemanager.googleapis.com/DnsAuthorization` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets` | `cloudasset.googleapis.com/Asset` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets_access_policies` | `cloudasset.googleapis.com/AssetsAccessPolicy` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets_history` | `cloudasset.googleapis.com/AssetsHistory` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets_iam_policies` | `cloudasset.googleapis.com/AssetsIamPolicy` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets_org_policies` | `cloudasset.googleapis.com/AssetsOrgPolicy` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets_os_inventories` | `cloudasset.googleapis.com/AssetsOsInventory` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets_relationships` | `cloudasset.googleapis.com/AssetsRelationship` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_assets_resources` | `cloudasset.googleapis.com/AssetsResource` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_effective_iam_policies` | `cloudasset.googleapis.com/EffectiveIamPolicy` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_feeds` | `cloudasset.googleapis.com/Feed` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_org_assets` | `cloudasset.googleapis.com/OrgAsset` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_org_assets_access_policies` | `cloudasset.googleapis.com/OrgAssetsAccessPolicy` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_org_assets_iam_policies` | `cloudasset.googleapis.com/OrgAssetsIamPolicy` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_org_assets_org_policies` | `cloudasset.googleapis.com/OrgAssetsOrgPolicy` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_org_assets_os_inventories` | `cloudasset.googleapis.com/OrgAssetsOsInventory` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_org_assets_relationships` | `cloudasset.googleapis.com/OrgAssetsRelationship` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_org_assets_resources` | `cloudasset.googleapis.com/OrgAssetsResource` | generic | +| cloudassetinventory | `gcp_cloudassetinventory_savedqueries` | `cloudasset.googleapis.com/Savedquery` | generic | +| cloudbuild | `gcp_cloudbuild_builds` | `cloudbuild.googleapis.com/Build` | generic | +| cloudbuild | `gcp_cloudbuild_connection_repositories` | `cloudbuild.googleapis.com/ConnectionRepository` | generic | +| cloudbuild | `gcp_cloudbuild_connections` | `cloudbuild.googleapis.com/Connection` | generic | +| cloudbuild | `gcp_cloudbuild_triggers` | `cloudbuild.googleapis.com/Trigger` | generic | +| cloudbuild | `gcp_cloudbuild_worker_pools` | `cloudbuild.googleapis.com/WorkerPool` | generic | +| clouddeploy | `gcp_clouddeploy_delivery_pipelines` | `clouddeploy.googleapis.com/DeliveryPipeline` | generic | +| clouddeploy | `gcp_clouddeploy_job_runs` | `clouddeploy.googleapis.com/JobRun` | generic | +| clouddeploy | `gcp_clouddeploy_releases` | `clouddeploy.googleapis.com/Releas` | generic | +| clouddeploy | `gcp_clouddeploy_rollouts` | `clouddeploy.googleapis.com/Rollout` | generic | +| clouddeploy | `gcp_clouddeploy_targets` | `clouddeploy.googleapis.com/Target` | generic | +| clouderrorreporting | `gcp_clouderrorreporting_error_events` | `clouderrorreporting.googleapis.com/ErrorEvent` | generic | +| clouderrorreporting | `gcp_clouderrorreporting_error_group_stats` | `clouderrorreporting.googleapis.com/ErrorGroupStat` | generic | +| cloudresourcemanager | `gcp_cloudresourcemanager_organizations` | `cloudresourcemanager.googleapis.com/Organization` | generic | +| cloudscheduler | `gcp_cloudscheduler_jobs` | `cloudscheduler.googleapis.com/Job` | generic | +| cloudscheduler | `gcp_cloudscheduler_locations` | `cloudscheduler.googleapis.com/Location` | generic | +| cloudsupport | `gcp_cloudsupport_cases` | `cloudsupport.googleapis.com/Cas` | generic | +| cloudtasks | `gcp_cloudtasks_locations` | `cloudtasks.googleapis.com/Location` | generic | +| cloudtasks | `gcp_cloudtasks_queues` | `cloudtasks.googleapis.com/Queue` | generic | +| cloudtasks | `gcp_cloudtasks_tasks` | `cloudtasks.googleapis.com/Task` | generic | +| cloudtrace | `gcp_cloudtrace_traces` | `cloudtrace.googleapis.com/Trace` | generic | +| composer | `gcp_composer_environments` | `composer.googleapis.com/Environment` | generic | +| composer | `gcp_composer_image_versions` | `composer.googleapis.com/ImageVersion` | generic | +| composer | `gcp_composer_operations` | `composer.googleapis.com/Operation` | generic | +| compute | `gcp_compute_addresses` | `compute.googleapis.com/Address` | typed | +| compute | `gcp_compute_autoscalers` | `compute.googleapis.com/Autoscaler` | generic | +| compute | `gcp_compute_backend_buckets` | `compute.googleapis.com/BackendBucket` | generic | +| compute | `gcp_compute_backend_services` | `compute.googleapis.com/BackendService` | generic | +| compute | `gcp_compute_disk_types` | `compute.googleapis.com/DiskType` | generic | +| compute | `gcp_compute_disks` | `compute.googleapis.com/Disk` | typed | +| compute | `gcp_compute_external_vpn_gateways` | `compute.googleapis.com/ExternalVpnGateway` | generic | +| compute | `gcp_compute_firewalls` | `compute.googleapis.com/Firewall` | typed | +| compute | `gcp_compute_forwarding_rules` | `compute.googleapis.com/ForwardingRule` | generic | +| compute | `gcp_compute_global_addresses` | `compute.googleapis.com/GlobalAddress` | generic | +| compute | `gcp_compute_global_forwarding_rules` | `compute.googleapis.com/GlobalForwardingRule` | generic | +| compute | `gcp_compute_health_checks` | `compute.googleapis.com/HealthCheck` | generic | +| compute | `gcp_compute_image_policies` | `compute.googleapis.com/ImagePolicy` | generic | +| compute | `gcp_compute_images` | `compute.googleapis.com/Image` | generic | +| compute | `gcp_compute_instance_group_instances` | `compute.googleapis.com/InstanceGroupInstance` | generic | +| compute | `gcp_compute_instance_group_managers` | `compute.googleapis.com/InstanceGroupManager` | generic | +| compute | `gcp_compute_instance_group_regional_instances` | `compute.googleapis.com/InstanceGroupRegionalInstance` | generic | +| compute | `gcp_compute_instance_groups` | `compute.googleapis.com/InstanceGroup` | generic | +| compute | `gcp_compute_instance_tag_bindings` | `compute.googleapis.com/InstanceTagBinding` | generic | +| compute | `gcp_compute_instance_templates` | `compute.googleapis.com/InstanceTemplate` | generic | +| compute | `gcp_compute_instances` | `compute.googleapis.com/Instance` | typed | +| compute | `gcp_compute_interconnect_attachments` | `compute.googleapis.com/InterconnectAttachment` | generic | +| compute | `gcp_compute_interconnect_locations` | `compute.googleapis.com/InterconnectLocation` | generic | +| compute | `gcp_compute_interconnect_remote_locations` | `compute.googleapis.com/InterconnectRemoteLocation` | generic | +| compute | `gcp_compute_interconnects` | `compute.googleapis.com/Interconnect` | generic | +| compute | `gcp_compute_machine_types` | `compute.googleapis.com/MachineType` | generic | +| compute | `gcp_compute_network_endpoint_groups` | `compute.googleapis.com/NetworkEndpointGroup` | generic | +| compute | `gcp_compute_network_firewall_policies` | `compute.googleapis.com/NetworkFirewallPolicy` | generic | +| compute | `gcp_compute_networks` | `compute.googleapis.com/Network` | typed | +| compute | `gcp_compute_osconfig_inventories` | `compute.googleapis.com/OsconfigInventory` | generic | +| compute | `gcp_compute_osconfig_os_patch_deployments` | `compute.googleapis.com/OsconfigOsPatchDeployment` | generic | +| compute | `gcp_compute_osconfig_os_patch_jobs` | `compute.googleapis.com/OsconfigOsPatchJob` | generic | +| compute | `gcp_compute_osconfig_os_patch_jobs_instance_details` | `compute.googleapis.com/OsconfigOsPatchJobsInstanceDetail` | generic | +| compute | `gcp_compute_osconfig_os_policy_assignment_reports` | `compute.googleapis.com/OsconfigOsPolicyAssignmentReport` | generic | +| compute | `gcp_compute_osconfig_os_policy_assignments` | `compute.googleapis.com/OsconfigOsPolicyAssignment` | generic | +| compute | `gcp_compute_osconfig_os_vulnerability_reports` | `compute.googleapis.com/OsconfigOsVulnerabilityReport` | generic | +| compute | `gcp_compute_packet_mirrorings` | `compute.googleapis.com/PacketMirroring` | generic | +| compute | `gcp_compute_projects` | `compute.googleapis.com/Project` | generic | +| compute | `gcp_compute_region_instance_templates` | `compute.googleapis.com/RegionInstanceTemplate` | generic | +| compute | `gcp_compute_region_network_firewall_policies` | `compute.googleapis.com/RegionNetworkFirewallPolicy` | generic | +| compute | `gcp_compute_router_nat_mapping_infos` | `compute.googleapis.com/RouterNatMappingInfo` | generic | +| compute | `gcp_compute_routers` | `compute.googleapis.com/Router` | generic | +| compute | `gcp_compute_routes` | `compute.googleapis.com/Route` | generic | +| compute | `gcp_compute_security_policies` | `compute.googleapis.com/SecurityPolicy` | generic | +| compute | `gcp_compute_snapshots` | `compute.googleapis.com/Snapshot` | typed | +| compute | `gcp_compute_ssl_certificates` | `compute.googleapis.com/SslCertificate` | generic | +| compute | `gcp_compute_ssl_policies` | `compute.googleapis.com/SslPolicy` | generic | +| compute | `gcp_compute_subnetworks` | `compute.googleapis.com/Subnetwork` | typed | +| compute | `gcp_compute_target_grpc_proxies` | `compute.googleapis.com/TargetGrpcProxy` | generic | +| compute | `gcp_compute_target_http_proxies` | `compute.googleapis.com/TargetHttpProxy` | generic | +| compute | `gcp_compute_target_https_proxies` | `compute.googleapis.com/TargetHttpsProxy` | generic | +| compute | `gcp_compute_target_instances` | `compute.googleapis.com/TargetInstance` | generic | +| compute | `gcp_compute_target_pools` | `compute.googleapis.com/TargetPool` | generic | +| compute | `gcp_compute_target_ssl_proxies` | `compute.googleapis.com/TargetSslProxy` | generic | +| compute | `gcp_compute_target_tcp_proxies` | `compute.googleapis.com/TargetTcpProxy` | generic | +| compute | `gcp_compute_target_vpn_gateways` | `compute.googleapis.com/TargetVpnGateway` | generic | +| compute | `gcp_compute_url_maps` | `compute.googleapis.com/UrlMap` | generic | +| compute | `gcp_compute_vpn_gateways` | `compute.googleapis.com/VpnGateway` | generic | +| compute | `gcp_compute_vpn_tunnels` | `compute.googleapis.com/VpnTunnel` | generic | +| compute | `gcp_compute_zones` | `compute.googleapis.com/Zone` | generic | +| container | `gcp_container_clusters` | `container.googleapis.com/Cluster` | typed | +| container | `gcp_container_node_pools` | `container.googleapis.com/NodePool` | generic | +| containeranalysis | `gcp_containeranalysis_occurrences` | `containeranalysis.googleapis.com/Occurrence` | generic | +| databasemigration | `gcp_databasemigration_locations` | `datamigration.googleapis.com/Location` | generic | +| databasemigration | `gcp_databasemigration_migration_jobs` | `datamigration.googleapis.com/MigrationJob` | generic | +| databasemigration | `gcp_databasemigration_operations` | `datamigration.googleapis.com/Operation` | generic | +| dataflow | `gcp_dataflow_job_messages` | `dataflow.googleapis.com/JobMessage` | generic | +| dataflow | `gcp_dataflow_job_metrics` | `dataflow.googleapis.com/JobMetric` | generic | +| dataflow | `gcp_dataflow_jobs` | `dataflow.googleapis.com/Job` | generic | +| dataflow | `gcp_dataflow_snapshots` | `dataflow.googleapis.com/Snapshot` | generic | +| datafusion | `gcp_datafusion_available_versions` | `datafusion.googleapis.com/AvailableVersion` | generic | +| datafusion | `gcp_datafusion_instance_operations` | `datafusion.googleapis.com/InstanceOperation` | generic | +| datafusion | `gcp_datafusion_instances` | `datafusion.googleapis.com/Instance` | generic | +| dataproc | `gcp_dataproc_autoscaling_policies` | `dataproc.googleapis.com/AutoscalingPolicy` | generic | +| dataproc | `gcp_dataproc_cluster_nodegroups` | `dataproc.googleapis.com/ClusterNodegroup` | generic | +| dataproc | `gcp_dataproc_clusters` | `dataproc.googleapis.com/Cluster` | generic | +| dataproc | `gcp_dataproc_jobs` | `dataproc.googleapis.com/Job` | generic | +| dataproc | `gcp_dataproc_regions` | `dataproc.googleapis.com/Region` | generic | +| deploymentmanager | `gcp_deploymentmanager_deployments` | `deploymentmanager.googleapis.com/Deployment` | generic | +| deploymentmanager | `gcp_deploymentmanager_manifests` | `deploymentmanager.googleapis.com/Manifest` | generic | +| deploymentmanager | `gcp_deploymentmanager_operations` | `deploymentmanager.googleapis.com/Operation` | generic | +| deploymentmanager | `gcp_deploymentmanager_resources` | `deploymentmanager.googleapis.com/Resource` | generic | +| deploymentmanager | `gcp_deploymentmanager_types` | `deploymentmanager.googleapis.com/Type` | generic | +| dns | `gcp_dns_managed_zones` | `dns.googleapis.com/ManagedZone` | generic | +| dns | `gcp_dns_policies` | `dns.googleapis.com/Policy` | generic | +| dns | `gcp_dns_resource_record_sets` | `dns.googleapis.com/ResourceRecordSet` | generic | +| domains | `gcp_domains_registrations` | `domains.googleapis.com/Registration` | generic | +| essentialcontacts | `gcp_essentialcontacts_folder_contacts` | `essentialcontacts.googleapis.com/FolderContact` | generic | +| essentialcontacts | `gcp_essentialcontacts_organization_contacts` | `essentialcontacts.googleapis.com/OrganizationContact` | generic | +| essentialcontacts | `gcp_essentialcontacts_project_contacts` | `essentialcontacts.googleapis.com/ProjectContact` | generic | +| eventarc | `gcp_eventarc_channels` | `eventarc.googleapis.com/Channel` | generic | +| eventarc | `gcp_eventarc_providers` | `eventarc.googleapis.com/Provider` | generic | +| eventarc | `gcp_eventarc_triggers` | `eventarc.googleapis.com/Trigger` | generic | +| filestore | `gcp_filestore_backups` | `file.googleapis.com/Backup` | generic | +| filestore | `gcp_filestore_instances` | `file.googleapis.com/Instance` | generic | +| filestore | `gcp_filestore_locations` | `file.googleapis.com/Location` | generic | +| filestore | `gcp_filestore_operations` | `file.googleapis.com/Operation` | generic | +| filestore | `gcp_filestore_snapshots` | `file.googleapis.com/Snapshot` | generic | +| firebase | `gcp_firebase_hosting_site_channels` | `firebase.googleapis.com/HostingSiteChannel` | generic | +| firebase | `gcp_firebase_hosting_site_custom_domains` | `firebase.googleapis.com/HostingSiteCustomDomain` | generic | +| firebase | `gcp_firebase_hosting_site_releases` | `firebase.googleapis.com/HostingSiteReleas` | generic | +| firebase | `gcp_firebase_hosting_site_versions` | `firebase.googleapis.com/HostingSiteVersion` | generic | +| firebase | `gcp_firebase_hosting_sites` | `firebase.googleapis.com/HostingSite` | generic | +| firebase | `gcp_firebase_rules_releases` | `firebase.googleapis.com/RulesReleas` | generic | +| firebase | `gcp_firebase_rules_rulesets` | `firebase.googleapis.com/RulesRuleset` | generic | +| firebaseappcheck | `gcp_firebaseappcheck_app_attest_configs` | `firebaseappcheck.googleapis.com/AppAttestConfig` | generic | +| firebaseappcheck | `gcp_firebaseappcheck_device_check_configs` | `firebaseappcheck.googleapis.com/DeviceCheckConfig` | generic | +| firebaseappcheck | `gcp_firebaseappcheck_play_integrity_configs` | `firebaseappcheck.googleapis.com/PlayIntegrityConfig` | generic | +| firebaseappcheck | `gcp_firebaseappcheck_recaptcha_configs` | `firebaseappcheck.googleapis.com/RecaptchaConfig` | generic | +| firebaseappcheck | `gcp_firebaseappcheck_recaptcha_enterprise_configs` | `firebaseappcheck.googleapis.com/RecaptchaEnterpriseConfig` | generic | +| firebaseappcheck | `gcp_firebaseappcheck_safety_net_configs` | `firebaseappcheck.googleapis.com/SafetyNetConfig` | generic | +| firestore | `gcp_firestore_databases` | `firestore.googleapis.com/Databas` | generic | +| functions | `gcp_functions_function_policies` | `cloudfunctions.googleapis.com/FunctionPolicy` | generic | +| functions | `gcp_functions_functions` | `cloudfunctions.googleapis.com/CloudFunction` | generic | +| functionsv2 | `gcp_functionsv2_function_policies` | `cloudfunctions.googleapis.com/FunctionPolicy` | generic | +| functionsv2 | `gcp_functionsv2_functions` | `cloudfunctions.googleapis.com/Function` | generic | +| iam | `gcp_iam_deny_policies` | `iam.googleapis.com/DenyPolicy` | generic | +| iam | `gcp_iam_organizational_roles` | `iam.googleapis.com/OrganizationalRole` | generic | +| iam | `gcp_iam_predefined_roles` | `iam.googleapis.com/PredefinedRole` | generic | +| iam | `gcp_iam_roles` | `iam.googleapis.com/Role` | generic | +| iam | `gcp_iam_service_account_keys` | `iam.googleapis.com/ServiceAccountKey` | generic | +| iam | `gcp_iam_service_account_policies` | `iam.googleapis.com/ServiceAccountPolicy` | generic | +| iam | `gcp_iam_service_accounts` | `iam.googleapis.com/ServiceAccount` | typed | +| iam | `gcp_iam_workload_identity_pool_providers` | `iam.googleapis.com/WorkloadIdentityPoolProvider` | generic | +| iam | `gcp_iam_workload_identity_pools` | `iam.googleapis.com/WorkloadIdentityPool` | generic | +| identitytoolkit | `gcp_identitytoolkit_accounts` | `identitytoolkit.googleapis.com/Account` | generic | +| identitytoolkit | `gcp_identitytoolkit_default_supported_idps` | `identitytoolkit.googleapis.com/DefaultSupportedIdp` | generic | +| identitytoolkit | `gcp_identitytoolkit_inbound_saml_configs` | `identitytoolkit.googleapis.com/InboundSamlConfig` | generic | +| identitytoolkit | `gcp_identitytoolkit_oauth_idp_configs` | `identitytoolkit.googleapis.com/OauthIdpConfig` | generic | +| identitytoolkit | `gcp_identitytoolkit_project_configs` | `identitytoolkit.googleapis.com/ProjectConfig` | generic | +| identitytoolkit | `gcp_identitytoolkit_project_public_configs` | `identitytoolkit.googleapis.com/ProjectPublicConfig` | generic | +| identitytoolkit | `gcp_identitytoolkit_recaptcha_params` | `identitytoolkit.googleapis.com/RecaptchaParam` | generic | +| identitytoolkit | `gcp_identitytoolkit_tenants` | `identitytoolkit.googleapis.com/Tenant` | generic | +| kms | `gcp_kms_crypto_key_versions` | `cloudkms.googleapis.com/CryptoKeyVersion` | generic | +| kms | `gcp_kms_crypto_keys` | `cloudkms.googleapis.com/CryptoKey` | generic | +| kms | `gcp_kms_ekm_connections` | `cloudkms.googleapis.com/EkmConnection` | generic | +| kms | `gcp_kms_import_jobs` | `cloudkms.googleapis.com/ImportJob` | generic | +| kms | `gcp_kms_keyrings` | `cloudkms.googleapis.com/KeyRing` | generic | +| kms | `gcp_kms_locations` | `cloudkms.googleapis.com/Location` | generic | +| livestream | `gcp_livestream_channels` | `livestream.googleapis.com/Channel` | generic | +| livestream | `gcp_livestream_inputs` | `livestream.googleapis.com/Input` | generic | +| logging | `gcp_logging_audit_logs` | `logging.googleapis.com/AuditLog` | generic | +| logging | `gcp_logging_metrics` | `logging.googleapis.com/Metric` | generic | +| logging | `gcp_logging_sinks` | `logging.googleapis.com/Sink` | generic | +| looker | `gcp_looker_instance_operations` | `looker.googleapis.com/InstanceOperation` | generic | +| looker | `gcp_looker_instances` | `looker.googleapis.com/Instance` | generic | +| memorystore | `gcp_memorystore_instances` | `memorystore.googleapis.com/Instance` | generic | +| memorystore | `gcp_memorystore_locations` | `memorystore.googleapis.com/Location` | generic | +| memorystore | `gcp_memorystore_operations` | `memorystore.googleapis.com/Operation` | generic | +| monitoring | `gcp_monitoring_alert_policies` | `monitoring.googleapis.com/AlertPolicy` | generic | +| networkconnectivity | `gcp_networkconnectivity_internal_ranges` | `networkconnectivity.googleapis.com/InternalRange` | generic | +| networkconnectivity | `gcp_networkconnectivity_locations` | `networkconnectivity.googleapis.com/Location` | generic | +| networkintelligencecenter | `gcp_networkintelligencecenter_connectivity_tests` | `networkmanagement.googleapis.com/ConnectivityTest` | generic | +| networkintelligencecenter | `gcp_networkintelligencecenter_locations` | `networkmanagement.googleapis.com/Location` | generic | +| networkintelligencecenter | `gcp_networkintelligencecenter_operations` | `networkmanagement.googleapis.com/Operation` | generic | +| networksecurity | `gcp_networksecurity_address_groups` | `networksecurity.googleapis.com/AddressGroup` | generic | +| networksecurity | `gcp_networksecurity_firewall_endpoints` | `networksecurity.googleapis.com/FirewallEndpoint` | generic | +| networksecurity | `gcp_networksecurity_security_profile_groups` | `networksecurity.googleapis.com/SecurityProfileGroup` | generic | +| networksecurity | `gcp_networksecurity_security_profiles` | `networksecurity.googleapis.com/SecurityProfile` | generic | +| networksecurity | `gcp_networksecurity_tls_inspection_policies` | `networksecurity.googleapis.com/TlsInspectionPolicy` | generic | +| networkservices | `gcp_networkservices_endpoint_policies` | `networkservices.googleapis.com/EndpointPolicy` | generic | +| networkservices | `gcp_networkservices_gateways` | `networkservices.googleapis.com/Gateway` | generic | +| networkservices | `gcp_networkservices_grpc_routes` | `networkservices.googleapis.com/GrpcRoute` | generic | +| networkservices | `gcp_networkservices_http_routes` | `networkservices.googleapis.com/HttpRoute` | generic | +| networkservices | `gcp_networkservices_meshes` | `networkservices.googleapis.com/Mesh` | generic | +| networkservices | `gcp_networkservices_service_bindings` | `networkservices.googleapis.com/ServiceBinding` | generic | +| networkservices | `gcp_networkservices_tcp_routes` | `networkservices.googleapis.com/TcpRoute` | generic | +| networkservices | `gcp_networkservices_tls_routes` | `networkservices.googleapis.com/TlsRoute` | generic | +| organization | `gcp_organization_folders_policies` | `cloudresourcemanager.googleapis.com/FoldersPolicy` | generic | +| organization | `gcp_organization_policies` | `cloudresourcemanager.googleapis.com/Policy` | generic | +| organization | `gcp_organization_projects_policies` | `cloudresourcemanager.googleapis.com/ProjectsPolicy` | generic | +| policyanalyzer | `gcp_policyanalyzer_activities` | `policyanalyzer.googleapis.com/Activity` | generic | +| privateca | `gcp_privateca_authorities` | `privateca.googleapis.com/Authority` | generic | +| privateca | `gcp_privateca_certificates` | `privateca.googleapis.com/Certificate` | generic | +| privateca | `gcp_privateca_pools` | `privateca.googleapis.com/Pool` | generic | +| projects | `gcp_projects` | `cloudresourcemanager.googleapis.com/Project` | typed | +| pubsub | `gcp_pubsub_schema_revisions` | `pubsub.googleapis.com/SchemaRevision` | generic | +| pubsub | `gcp_pubsub_schemas` | `pubsub.googleapis.com/Schema` | generic | +| pubsub | `gcp_pubsub_snapshots` | `pubsub.googleapis.com/Snapshot` | generic | +| pubsub | `gcp_pubsub_subscriptions` | `pubsub.googleapis.com/Subscription` | typed | +| pubsub | `gcp_pubsub_topics` | `pubsub.googleapis.com/Topic` | typed | +| recommendations | `gcp_recommendations_folders` | `recommendations.googleapis.com/Folder` | generic | +| recommendations | `gcp_recommendations_folders_insights` | `recommendations.googleapis.com/FoldersInsight` | generic | +| recommendations | `gcp_recommendations_folders_locations` | `recommendations.googleapis.com/FoldersLocation` | generic | +| recommendations | `gcp_recommendations_organizations` | `recommendations.googleapis.com/Organization` | generic | +| recommendations | `gcp_recommendations_organizations_insights` | `recommendations.googleapis.com/OrganizationsInsight` | generic | +| recommendations | `gcp_recommendations_organizations_locations` | `recommendations.googleapis.com/OrganizationsLocation` | generic | +| recommendations | `gcp_recommendations_projects` | `recommendations.googleapis.com/Project` | generic | +| recommendations | `gcp_recommendations_projects_insights` | `recommendations.googleapis.com/ProjectsInsight` | generic | +| recommendations | `gcp_recommendations_projects_locations` | `recommendations.googleapis.com/ProjectsLocation` | generic | +| redis | `gcp_redis_instances` | `redis.googleapis.com/Instance` | generic | +| resourcemanager | `gcp_resourcemanager_folder_policies` | `cloudresourcemanager.googleapis.com/FolderPolicy` | generic | +| resourcemanager | `gcp_resourcemanager_folders` | `cloudresourcemanager.googleapis.com/Folder` | generic | +| resourcemanager | `gcp_resourcemanager_organization_policies` | `cloudresourcemanager.googleapis.com/OrganizationPolicy` | generic | +| resourcemanager | `gcp_resourcemanager_organization_projects` | `cloudresourcemanager.googleapis.com/OrganizationProject` | generic | +| resourcemanager | `gcp_resourcemanager_organization_tag_keys` | `cloudresourcemanager.googleapis.com/OrganizationTagKey` | generic | +| resourcemanager | `gcp_resourcemanager_organization_tag_values` | `cloudresourcemanager.googleapis.com/OrganizationTagValue` | generic | +| resourcemanager | `gcp_resourcemanager_project_policies` | `cloudresourcemanager.googleapis.com/ProjectPolicy` | generic | +| resourcemanager | `gcp_resourcemanager_project_tag_bindings` | `cloudresourcemanager.googleapis.com/ProjectTagBinding` | generic | +| resourcemanager | `gcp_resourcemanager_project_tag_keys` | `cloudresourcemanager.googleapis.com/ProjectTagKey` | generic | +| resourcemanager | `gcp_resourcemanager_project_tag_values` | `cloudresourcemanager.googleapis.com/ProjectTagValue` | generic | +| resourcemanager | `gcp_resourcemanager_projects` | `cloudresourcemanager.googleapis.com/Project` | generic | +| resourcemanager | `gcp_resourcemanager_projects_search` | `cloudresourcemanager.googleapis.com/ProjectsSearch` | generic | +| resourcemanager | `gcp_resourcemanager_subfolders` | `cloudresourcemanager.googleapis.com/Subfolder` | generic | +| run | `gcp_run_executions` | `run.googleapis.com/Execution` | generic | +| run | `gcp_run_job_policies` | `run.googleapis.com/JobPolicy` | generic | +| run | `gcp_run_jobs` | `run.googleapis.com/Job` | generic | +| run | `gcp_run_locations` | `run.googleapis.com/Location` | generic | +| run | `gcp_run_revisions` | `run.googleapis.com/Revision` | generic | +| run | `gcp_run_service_policies` | `run.googleapis.com/ServicePolicy` | generic | +| run | `gcp_run_services` | `run.googleapis.com/Service` | generic | +| run | `gcp_run_tasks` | `run.googleapis.com/Task` | generic | +| run | `gcp_run_worker_pool_policies` | `run.googleapis.com/WorkerPoolPolicy` | generic | +| run | `gcp_run_worker_pools` | `run.googleapis.com/WorkerPool` | generic | +| secretmanager | `gcp_secretmanager_secrets` | `secretmanager.googleapis.com/Secret` | generic | +| securitycenter | `gcp_securitycenter_folder_event_threat_detection` | `securitycenter.googleapis.com/FolderEventThreatDetection` | generic | +| securitycenter | `gcp_securitycenter_folder_findings` | `securitycenter.googleapis.com/FolderFinding` | generic | +| securitycenter | `gcp_securitycenter_org_event_threat_detection_settings` | `securitycenter.googleapis.com/OrgEventThreatDetectionSetting` | generic | +| securitycenter | `gcp_securitycenter_organization_findings` | `securitycenter.googleapis.com/OrganizationFinding` | generic | +| securitycenter | `gcp_securitycenter_project_event_threat_detection` | `securitycenter.googleapis.com/ProjectEventThreatDetection` | generic | +| securitycenter | `gcp_securitycenter_project_findings` | `securitycenter.googleapis.com/ProjectFinding` | generic | +| servicehealth | `gcp_servicehealth_events` | `servicehealth.googleapis.com/Event` | generic | +| servicehealth | `gcp_servicehealth_locations` | `servicehealth.googleapis.com/Location` | generic | +| serviceusage | `gcp_serviceusage_service_project_quota_metrics` | `serviceusage.googleapis.com/ServiceProjectQuotaMetric` | generic | +| serviceusage | `gcp_serviceusage_services` | `serviceusage.googleapis.com/Service` | generic | +| sourcerepo | `gcp_sourcerepo_config` | `sourcerepo.googleapis.com/Config` | generic | +| sourcerepo | `gcp_sourcerepo_repos` | `sourcerepo.googleapis.com/Repo` | generic | +| spanner | `gcp_spanner_databases` | `spanner.googleapis.com/Database` | generic | +| spanner | `gcp_spanner_instances` | `spanner.googleapis.com/Instance` | generic | +| sql | `gcp_sql_backups` | `sqladmin.googleapis.com/Backup` | generic | +| sql | `gcp_sql_databases` | `sqladmin.googleapis.com/Databas` | generic | +| sql | `gcp_sql_instances` | `sqladmin.googleapis.com/Instance` | generic | +| sql | `gcp_sql_ssl_certs` | `sqladmin.googleapis.com/SslCert` | generic | +| sql | `gcp_sql_users` | `sqladmin.googleapis.com/User` | generic | +| storage | `gcp_storage_bucket_objects` | `storage.googleapis.com/BucketObject` | generic | +| storage | `gcp_storage_bucket_policies` | `storage.googleapis.com/BucketPolicy` | generic | +| storage | `gcp_storage_bucket_tag_bindings` | `storage.googleapis.com/BucketTagBinding` | generic | +| storage | `gcp_storage_buckets` | `storage.googleapis.com/Bucket` | typed | +| storage | `gcp_storage_hmac_keys` | `storage.googleapis.com/HmacKey` | generic | +| storagetransfer | `gcp_storagetransfer_agent_pools` | `storagetransfer.googleapis.com/AgentPool` | generic | +| storagetransfer | `gcp_storagetransfer_transfer_jobs` | `storagetransfer.googleapis.com/TransferJob` | generic | +| storagetransfer | `gcp_storagetransfer_transfer_operations` | `storagetransfer.googleapis.com/TransferOperation` | generic | +| translate | `gcp_translate_glossaries` | `translate.googleapis.com/Glossary` | generic | +| videotranscoder | `gcp_videotranscoder_job_templates` | `transcoder.googleapis.com/JobTemplate` | generic | +| videotranscoder | `gcp_videotranscoder_jobs` | `transcoder.googleapis.com/Job` | generic | +| vision | `gcp_vision_product_reference_images` | `vision.googleapis.com/ProductReferenceImage` | generic | +| vision | `gcp_vision_products` | `vision.googleapis.com/Product` | generic | +| vmmigration | `gcp_vmmigration_groups` | `vmmigration.googleapis.com/Group` | generic | +| vmmigration | `gcp_vmmigration_source_datacenter_connectors` | `vmmigration.googleapis.com/SourceDatacenterConnector` | generic | +| vmmigration | `gcp_vmmigration_source_migrating_vm_clone_jobs` | `vmmigration.googleapis.com/SourceMigratingVmCloneJob` | generic | +| vmmigration | `gcp_vmmigration_source_migrating_vm_cutover_jobs` | `vmmigration.googleapis.com/SourceMigratingVmCutoverJob` | generic | +| vmmigration | `gcp_vmmigration_source_migrating_vms` | `vmmigration.googleapis.com/SourceMigratingVm` | generic | +| vmmigration | `gcp_vmmigration_source_utilization_reports` | `vmmigration.googleapis.com/SourceUtilizationReport` | generic | +| vmmigration | `gcp_vmmigration_sources` | `vmmigration.googleapis.com/Source` | generic | +| vmmigration | `gcp_vmmigration_target_projects` | `vmmigration.googleapis.com/TargetProject` | generic | +| vpcaccess | `gcp_vpcaccess_connectors` | `vpcaccess.googleapis.com/Connector` | generic | +| vpcaccess | `gcp_vpcaccess_locations` | `vpcaccess.googleapis.com/Location` | generic | +| websecurityscanner | `gcp_websecurityscanner_scan_config_scan_run_crawled_urls` | `websecurityscanner.googleapis.com/ScanConfigScanRunCrawledUrl` | generic | +| websecurityscanner | `gcp_websecurityscanner_scan_config_scan_run_findings` | `websecurityscanner.googleapis.com/ScanConfigScanRunFinding` | generic | +| websecurityscanner | `gcp_websecurityscanner_scan_config_scan_runs` | `websecurityscanner.googleapis.com/ScanConfigScanRun` | generic | +| websecurityscanner | `gcp_websecurityscanner_scan_configs` | `websecurityscanner.googleapis.com/ScanConfig` | generic | +| workflows | `gcp_workflows_workflows` | `workflows.googleapis.com/Workflow` | generic | + diff --git a/docs/authoring/indexed-resources/kubernetes-resource-catalog.md b/docs/authoring/indexed-resources/kubernetes-resource-catalog.md new file mode 100644 index 000000000..cac60f51a --- /dev/null +++ b/docs/authoring/indexed-resources/kubernetes-resource-catalog.md @@ -0,0 +1,23 @@ +# Kubernetes resource catalog + +Built-in Kubernetes resource types the kubeapi indexer discovers. + +_Generated 2026-07-02 from `indexers/kubetypes.py`._ + +Custom CRDs are declared in generation rules (`resourceTypes`) and indexed +selectively — they are not listed here. + +| Resource type | Notes | +|---|---| +| `cluster` | Built-in Kubernetes kind | +| `namespace` | Built-in Kubernetes kind | +| `deployment` | Built-in Kubernetes kind | +| `daemonset` | Built-in Kubernetes kind | +| `statefulset` | Built-in Kubernetes kind | +| `job` | Built-in Kubernetes kind | +| `cronjob` | Built-in Kubernetes kind | +| `ingress` | Built-in Kubernetes kind | +| `service` | Built-in Kubernetes kind | +| `pod` | Built-in Kubernetes kind | +| `custom` | Built-in Kubernetes kind | +| `persistentvolumeclaim` | Built-in Kubernetes kind | diff --git a/docs/authoring/indexed-resources/runwhen-platform-resource-catalog.md b/docs/authoring/indexed-resources/runwhen-platform-resource-catalog.md new file mode 100644 index 000000000..db912bc34 --- /dev/null +++ b/docs/authoring/indexed-resources/runwhen-platform-resource-catalog.md @@ -0,0 +1,19 @@ +# RunWhen platform resource catalog + +Resource types indexed under `platform: runwhen`. + +_Generated 2026-07-02 from `scripts/runwhen/dump_runwhen_resource_catalog.py`._ + +| Resource type | Match names | Typed collector | Notes | +|---|---|---|---| +| `workspace` | `workspace` | yes | One instance per workspace-builder run | + +## match_resource properties (workspace) + +| Property | Description | +|---|---| +| `name` | Workspace name | +| `qualified_name` | Same as workspace name | +| `owner_email` | From workspaceInfo `workspaceOwnerEmail` | +| `location_id` | Default location id | +| `location_name` | Default location name | diff --git a/docs/authoring/indexed-resources/runwhen-platform.md b/docs/authoring/indexed-resources/runwhen-platform.md new file mode 100644 index 000000000..4040bb36f --- /dev/null +++ b/docs/authoring/indexed-resources/runwhen-platform.md @@ -0,0 +1,51 @@ +# RunWhen platform indexed resources + +The **`runwhen`** platform exposes workspace-scoped resources for generation rules +that are not tied to a cloud object or Kubernetes CRD. + +## Resource types + +| Resource type | Scope | Description | +|---|---|---| +| `workspace` | One per workspace-builder run | Anchor for MCP tool-builder codebundles using `platform: runwhen` | + +## Template variables + +When a generation rule matches a `workspace` resource, templates receive: + +| Variable | Value | +|---|---| +| `match_resource.name` | Workspace name | +| `match_resource.qualified_name` | Workspace name | +| `match_resource.owner_email` | `workspaceOwnerEmail` from workspaceInfo | +| `workspace.name` | Workspace name (from base template variables) | +| `workspace.owner_email` | Owner email | +| `default_location` | Default runner location id | + +## Example generation rule + +```yaml +apiVersion: runwhen.com/v1 +kind: GenerationRules +spec: + platform: runwhen + generationRules: + - resourceTypes: + - workspace + matchRules: + - type: pattern + pattern: ".+" + properties: [name] + mode: substring + slxs: + - baseName: my-task + qualifiers: ["workspace"] + baseTemplateName: my-health-check + levelOfDetail: detailed + outputItems: + - type: slx + - type: runbook + templateName: my-health-check-taskset.yaml +``` + +See the RunWhen MCP `render_codecollection_skill` tool for generating this layout from a tested tool-builder script. diff --git a/generation-rules-guide.md b/generation-rules-guide.md index 7f876ead5..13d6f8843 100644 --- a/generation-rules-guide.md +++ b/generation-rules-guide.md @@ -6,7 +6,7 @@ apiVersion: runwhen.com/v1 kind: GenerationRules spec: - platform: # azure, kubernetes, gcp, aws + platform: # azure, kubernetes, gcp, aws, runwhen generationRules: - resourceTypes: [] matchRules: [] @@ -16,90 +16,101 @@ spec: ## Resource Type Specifications -### Basic Resource Types +Each rule block lists names under `resourceTypes`. The file-level **`spec.platform`** +(`azure`, `kubernetes`, `aws`, `gcp`, `runwhen`) is the default platform for +every entry in that file unless an entry overrides it. + +### Typical names (canonical + aliases) + +Indexers resolve names through per-platform registries. Use the **CloudQuery table +name** (canonical) or a documented **alias** — both work when `spec.platform` +is set: + ```yaml +# spec.platform: azure +resourceTypes: + - azure_compute_virtual_machines # canonical + - virtual_machine # alias → same type as above + - azure_appservice_web_apps + +# spec.platform: kubernetes +resourceTypes: + - deployment + - pod + - buckets.storage.gcp.upbound.io # CRD: plural.group[/version] + +# spec.platform: aws resourceTypes: - - resource_group # Simple name - - azure:resource_group # Platform-prefixed - - kubernetes:pod # Cross-platform + - aws_ec2_instances + - aws_s3_buckets + +# spec.platform: gcp +resourceTypes: + - gcp_compute_instances + - gcp_storage_buckets + +# spec.platform: runwhen (MCP tool-builder / workspace-scoped SLXs) +resourceTypes: + - workspace ``` -### Discovering Available Resource Types +Full lists: [`docs/authoring/indexed-resources/`](../docs/authoring/indexed-resources/) +and the generated `*-resource-catalog.md` files (regenerated from indexer code). + +### Optional platform override (`platform:type`) -To find the exact resource types available in your environment, examine your resource dump: +Only the **first** `:` splits platform from type. Use this when one entry must +target a different platform than `spec.platform` (uncommon): ```yaml -# Resource dump structure shows available resource types -platforms: - azure: !Platform - resourceTypes: - resource_group: !ResourceType # <- This is the resource type name to use - instances: {...} - virtual_machine: !ResourceType # <- Another available resource type - instances: {...} +spec: + platform: azure + generationRules: + - resourceTypes: + - resource_group # → azure (from spec.platform) + - kubernetes:deployment # → kubernetes (override for this entry) ``` -You can also use the CloudQuery documentation to find the full list of supported resource types for your specific provider: -- **Azure**: [CloudQuery Azure Plugin](https://www.cloudquery.io/docs/plugins/sources/azure/tables) - All Azure resource types -- **AWS**: [CloudQuery AWS Plugin](https://www.cloudquery.io/docs/plugins/sources/aws/tables) - All AWS resource types -- **GCP**: [CloudQuery GCP Plugin](https://www.cloudquery.io/docs/plugins/sources/gcp/tables) - All GCP resource types -- **Kubernetes**: [CloudQuery Kubernetes Plugin](https://www.cloudquery.io/docs/plugins/sources/k8s/tables) - All Kubernetes resource types - -> **Important**: The available resource types depend on which CloudQuery provider plugins you have configured and enabled in your environment. +This is **not** “cross-platform matching” in one rule — it selects which indexer +serves that entry. Prefer **separate generation-rule files** per `spec.platform`. -### Platform-Specific Resource Types +Kubernetes CRDs use `plural.group[/version]` (dots in the group; optional +`/version`). Do not confuse CRD syntax with `platform:type` overrides. -RunWhen Local supports **all CloudQuery resource types for the specific provider/platform** you're using. The resource type names correspond to the CloudQuery table schema names, but are typically simplified (e.g., `azure_resources_resource_groups` becomes `resource_group`). +### Dict form ```yaml -# Azure - Examples from CloudQuery Azure plugin -resourceTypes: - - resource_group # azure_resources_resource_groups - - virtual_machine # azure_compute_virtual_machines - - storage_account # azure_storage_accounts - - app_service # azure_web_apps - - sql_database # azure_sql_databases - - key_vault # azure_keyvault_vaults - - network_security_group # azure_network_security_groups - - virtual_network # azure_network_virtual_networks - - load_balancer # azure_network_load_balancers - -# Kubernetes - Examples from CloudQuery Kubernetes plugin -resourceTypes: - - pod # k8s_core_pods - - service # k8s_core_services - - deployment # k8s_apps_deployments - - namespace # k8s_core_namespaces - - configmap # k8s_core_config_maps - - secret # k8s_core_secrets - - ingress # k8s_networking_ingresses - - persistent_volume # k8s_core_persistent_volumes - - statefulset # k8s_apps_stateful_sets - -# AWS - Examples from CloudQuery AWS plugin -resourceTypes: - - ec2_instance # aws_ec2_instances - - s3_bucket # aws_s3_buckets - - rds_instance # aws_rds_instances - - lambda_function # aws_lambda_functions - - vpc # aws_ec2_vpcs - - security_group # aws_ec2_security_groups - - iam_role # aws_iam_roles - - cloudformation_stack # aws_cloudformation_stacks - - elb_load_balancer # aws_elbv2_load_balancers - -# GCP - Examples from CloudQuery GCP plugin resourceTypes: - - compute_instance # gcp_compute_instances - - storage_bucket # gcp_storage_buckets - - sql_instance # gcp_sql_instances - - kubernetes_cluster # gcp_container_clusters - - cloud_function # gcp_cloudfunctions_functions - - firewall_rule # gcp_compute_firewall_rules - - vpc_network # gcp_compute_networks + - resourceType: azure_keyvault_vaults + - platform: gcp + resourceType: gcp_compute_instances ``` -> **Note**: The exact resource type names may vary. Check your resource dump or CloudQuery documentation for the specific resource types available in your environment. +### Discovering available resource types + +**Review discovered resources in the Workspace Explorer UI** (workspace-builder on +port **8000**) — not by opening `resource-dump.yaml` on the filesystem: + +| Method | Use | +| --- | --- | +| [http://localhost:8000/explorer/](http://localhost:8000/explorer/) | Browse platforms, resource types, and instance payloads after discovery | +| `GET /explorer/api/summary` | JSON overview of indexed platforms and counts | +| `GET /explorer/api/resources?platform=…&resource_type=…` | Filter instances; inspect fields for `matchRules` paths | +| `docs/authoring/indexed-resources/*-resource-catalog.md` | Full type list from indexer registries (no cluster required) | + +See [Resource store query API](docs/architecture/resource-store-query-api.md) for +API details. Legacy YAML dumps under `shared/` are deprecated for authoring. + +CloudQuery plugin tables remain useful background for field shapes: + +- **Azure**: [CloudQuery Azure Plugin](https://www.cloudquery.io/docs/plugins/sources/azure/tables) +- **AWS**: [CloudQuery AWS Plugin](https://www.cloudquery.io/docs/plugins/sources/aws/tables) +- **GCP**: [CloudQuery GCP Plugin](https://www.cloudquery.io/docs/plugins/sources/gcp/tables) +- **Kubernetes**: [CloudQuery Kubernetes Plugin](https://www.cloudquery.io/docs/plugins/sources/k8s/tables) + +> **Important**: Which types appear in Explorer depends on your generation rules +> (selective discovery) and indexer backend — not every catalog row is indexed in +> every run. ## Match Rules @@ -424,8 +435,8 @@ All matched resources provide these template variables: ## Common Troubleshooting ### Issue: Generation Rule Not Matching -- Check that `resourceTypes` matches exactly what's in your resource dump -- Verify `properties` paths are correct (use `/` for nested paths) +- Confirm `resourceTypes` against Explorer (`http://localhost:8000/explorer/`) or the authoring catalogs — not legacy filesystem dumps +- Verify `properties` paths against a live resource payload in Explorer (use `/` for nested paths) - Test regex patterns with online regex testers - Enable debug logging to see match attempts diff --git a/scripts/aws/dump_aws_resource_catalog.py b/scripts/aws/dump_aws_resource_catalog.py new file mode 100644 index 000000000..a308bf12c --- /dev/null +++ b/scripts/aws/dump_aws_resource_catalog.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +"""Regenerate ``docs/authoring/indexed-resources/aws-resource-catalog.md``. + +The catalog is the user-facing companion to ``aws.md``: a single sortable +table of every AWS resource type the ``awsapi`` indexer knows about, +grouped by service. It's derived directly from +``src/indexers/aws_resource_type_registry.yaml`` (which itself is generated +from the CloudQuery AWS plugin's table list and the manual overrides in +``scripts/aws/aws_resource_type_overrides.yaml``). + +Run this script after editing ``aws_resource_type_overrides.yaml`` and +re-running ``sync_aws_resource_type_registry.py``. Hand-edits to the +generated catalog get overwritten; touch the registry / overrides instead. + +Usage:: + + python scripts/aws/dump_aws_resource_catalog.py +""" + +from __future__ import annotations + +import datetime as _dt +import sys +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[2] +_SRC = _REPO_ROOT / "src" +sys.path.insert(0, str(_SRC)) + +from indexers.aws_resource_type_registry import load_registry # noqa: E402 + +_OUTPUT = ( + _REPO_ROOT + / "docs" + / "authoring" + / "indexed-resources" + / "aws-resource-catalog.md" +) + + +def main() -> None: + registry = load_registry() + rows = sorted( + registry, + key=lambda e: ((e.category or "~"), e.cloudquery_table_name), + ) + typed_count = sum(1 for e in rows if e.typed_collector) + generated_at = _dt.datetime.now(_dt.timezone.utc).strftime("%Y-%m-%d") + + lines: list[str] = [] + lines.append("# AWS resource catalog") + lines.append("") + lines.append( + "Every AWS resource type the native `awsapi` indexer can " + "discover. This page is the companion catalog for " + "[`aws.md`](./aws.md); see that page for how to enable the " + "indexer, what data each row carries, and the typed/generic " + "distinction." + ) + lines.append("") + lines.append( + f"_{len(rows)} resource types - {typed_count} typed (rich-payload), " + f"{len(rows) - typed_count} generic (Cloud Control envelope). " + f"Generated {generated_at} from " + "`src/indexers/aws_resource_type_registry.yaml`._" + ) + lines.append("") + lines.append( + "_Regenerate with `python scripts/aws/dump_aws_resource_catalog.py` " + "after touching the registry or overrides; do not hand-edit this file._" + ) + lines.append("") + lines.append( + "* `typed` - hand-written `boto3` collector returns a richer payload." + ) + lines.append( + "* `generic` - covered by the Cloud Control API catch-all when a " + "CloudFormation type exists; rows without a CFN type are registry-only " + "and skipped by generic discovery." + ) + lines.append("") + lines.append("| Service | CloudQuery table name | CFN type | Tier |") + lines.append("| --- | --- | --- | --- |") + for e in rows: + cat = e.category or "-" + cq = e.cloudquery_table_name + cfn = e.cfn_type or "-" + tier = "typed" if e.typed_collector else "generic" + lines.append(f"| {cat} | `{cq}` | `{cfn}` | {tier} |") + lines.append("") + + _OUTPUT.write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"Wrote {_OUTPUT.relative_to(_REPO_ROOT)} ({len(rows)} entries)") + + +if __name__ == "__main__": + main() diff --git a/scripts/docs/sync_authoring_to_docs_site.py b/scripts/docs/sync_authoring_to_docs_site.py new file mode 100644 index 000000000..75d1691b8 --- /dev/null +++ b/scripts/docs/sync_authoring_to_docs_site.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python3 +"""Sync ``docs/authoring/`` markdown into the RunWhen docs site (Starlight). + +**Optional publish step only.** Canonical authoring reference stays in this repo +(``docs/authoring/`` + generated catalogs). MCP agents use the +``author-generation-rules`` skill, which points here — not docs.runwhen.com +legacy author pages. + +Use when the docs team is ready to replace stale ``/authors/generation-rules/`` +content on docs.runwhen.com with refreshed Starlight pages derived from this tree. + +Transforms for Starlight: + - Prepends YAML frontmatter (title, description, sidebar order/label) + - Strips the first ``# heading`` (title comes from frontmatter) + - Converts GitHub ``[!NOTE]`` alerts to Starlight ``:::note`` admonitions + - Rewrites internal links to docs-site paths + +Usage:: + + python scripts/docs/sync_authoring_to_docs_site.py + python scripts/docs/sync_authoring_to_docs_site.py --check # exit 1 if drift +""" + +from __future__ import annotations + +import argparse +import re +import sys +from dataclasses import dataclass +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[2] +_DEFAULT_DOCS_REPO = _REPO_ROOT.parent.parent / "runwhen" / "docs" +_AUTHORS_ROOT = "src/content/docs/authors" + + +@dataclass(frozen=True) +class PageSpec: + source: Path + dest_rel: str + title: str + description: str + sidebar_order: int + sidebar_label: str | None = None + sidebar_hidden: bool = False + + +_RWL_ARCH = "https://github.com/runwhen-contrib/runwhen-local/blob/main/docs/architecture" +_RWL_DOCS = "https://github.com/runwhen-contrib/runwhen-local/blob/main/docs" + + +def _pages() -> list[PageSpec]: + authoring = _REPO_ROOT / "docs" / "authoring" + return [ + PageSpec( + authoring / "concepts.md", + "concepts.md", + "Authoring Concepts", + "CodeBundle, Skill, SLX, and Runbook terminology for RunWhen Local authors.", + 1, + "Concepts", + ), + PageSpec( + authoring / "indexed-resources/README.md", + "indexed-resources/index.md", + "Indexed Resources", + "Overview of platform indexers and resource type catalogs for generation rules.", + 0, + "Overview", + ), + PageSpec( + authoring / "indexed-resources/azure.md", + "indexed-resources/azure.md", + "Azure Indexed Resources", + "What the azureapi indexer discovers and how generation rules match Azure resources.", + 1, + "Azure", + ), + PageSpec( + authoring / "indexed-resources/aws.md", + "indexed-resources/aws.md", + "AWS Indexed Resources", + "What the awsapi indexer discovers and how generation rules match AWS resources.", + 2, + "AWS", + ), + PageSpec( + authoring / "indexed-resources/gcp.md", + "indexed-resources/gcp.md", + "GCP Indexed Resources", + "What the gcpapi indexer discovers and how generation rules match GCP resources.", + 3, + "GCP", + ), + PageSpec( + authoring / "indexed-resources/kubernetes.md", + "indexed-resources/kubernetes.md", + "Kubernetes Indexed Resources", + "Built-in and CRD resource types the kubeapi indexer discovers.", + 4, + "Kubernetes", + ), + PageSpec( + authoring / "indexed-resources/runwhen-platform.md", + "indexed-resources/runwhen-platform.md", + "RunWhen Platform Resources", + "Workspace-scoped resources indexed under platform runwhen (MCP tool-builder output).", + 5, + "RunWhen Platform", + ), + PageSpec( + authoring / "indexed-resources/azure-resource-catalog.md", + "indexed-resources/azure-resource-catalog.md", + "Azure Resource Catalog", + "Sortable table of every Azure resource type the azureapi indexer knows.", + 10, + "Azure Catalog", + ), + PageSpec( + authoring / "indexed-resources/aws-resource-catalog.md", + "indexed-resources/aws-resource-catalog.md", + "AWS Resource Catalog", + "Sortable table of every AWS resource type the awsapi indexer knows.", + 11, + "AWS Catalog", + ), + PageSpec( + authoring / "indexed-resources/gcp-resource-catalog.md", + "indexed-resources/gcp-resource-catalog.md", + "GCP Resource Catalog", + "Sortable table of every GCP resource type the gcpapi indexer knows.", + 12, + "GCP Catalog", + ), + PageSpec( + authoring / "indexed-resources/kubernetes-resource-catalog.md", + "indexed-resources/kubernetes-resource-catalog.md", + "Kubernetes Resource Catalog", + "Built-in Kubernetes kinds available to generation rules.", + 13, + "Kubernetes Catalog", + ), + PageSpec( + authoring / "indexed-resources/runwhen-platform-resource-catalog.md", + "indexed-resources/runwhen-platform-resource-catalog.md", + "RunWhen Platform Resource Catalog", + "Resource types under platform runwhen.", + 14, + "RunWhen Catalog", + ), + PageSpec( + authoring / "generation-rules/README.md", + "generation-rules/schema.md", + "Generation Rules Schema", + "Schema reference for .runwhen/generation-rules YAML files.", + 1, + "Schema Reference", + ), + PageSpec( + _REPO_ROOT / "generation-rules-guide.md", + "generation-rules/syntax-reference.md", + "Generation Rules Syntax Reference", + "Complete matchRules, slxs, outputItems, and platform-specific syntax.", + 2, + "Syntax Reference", + ), + PageSpec( + authoring / "generation-rules/tag-hierarchy-contract.md", + "generation-rules/tag-hierarchy.md", + "Tag and Hierarchy Contract", + "Conventions for platform tag and hierarchy templates.", + 3, + "Tag Hierarchy", + ), + PageSpec( + authoring / "generation-rules/examples/README.md", + "generation-rules/examples/index.md", + "Generation Rule Examples", + "End-to-end generation rule examples by platform and pattern.", + 10, + "Examples Overview", + ), + PageSpec( + authoring / "generation-rules/examples/azure-keyvault-slx.md", + "generation-rules/examples/azure-keyvault-slx.md", + "Example: Azure Key Vault SLX", + "Generation rule for private Key Vaults with SKILL.md overlay.", + 11, + "Azure Key Vault", + ), + PageSpec( + authoring / "generation-rules/examples/azure-vm-disk-runbook.md", + "generation-rules/examples/azure-vm-disk-runbook.md", + "Example: Azure VM Disk Runbook", + "Match production VMs and expose OS disk IDs to templates.", + 12, + "Azure VM Disk", + ), + PageSpec( + authoring / "generation-rules/examples/kubernetes-deployment-slx.md", + "generation-rules/examples/kubernetes-deployment-slx.md", + "Example: Kubernetes Deployment SLX", + "Multi-replica Deployment rollout health check.", + 13, + "K8s Deployment", + ), + PageSpec( + authoring / "generation-rules/examples/multi-resource-runbook.md", + "generation-rules/examples/multi-resource-runbook.md", + "Example: Azure Web App Context", + "Pass related ARM IDs from a single matched resource into templates.", + 14, + "Web App Context", + ), + ] + + +_LINK_REWRITES: list[tuple[str, str]] = [ + (r"\(\./azure-resource-catalog\.md\)", "(/authors/indexed-resources/azure-resource-catalog/)"), + (r"\(\./aws-resource-catalog\.md\)", "(/authors/indexed-resources/aws-resource-catalog/)"), + (r"\(\./gcp-resource-catalog\.md\)", "(/authors/indexed-resources/gcp-resource-catalog/)"), + (r"\(\./kubernetes-resource-catalog\.md\)", "(/authors/indexed-resources/kubernetes-resource-catalog/)"), + (r"\(\./runwhen-platform-resource-catalog\.md\)", "(/authors/indexed-resources/runwhen-platform-resource-catalog/)"), + (r"\(\./README\.md\)", "(/authors/indexed-resources/)"), + (r"\(\./azure\.md\)", "(/authors/indexed-resources/azure/)"), + (r"\(\./aws\.md\)", "(/authors/indexed-resources/aws/)"), + (r"\(\./gcp\.md\)", "(/authors/indexed-resources/gcp/)"), + (r"\(\./kubernetes\.md\)", "(/authors/indexed-resources/kubernetes/)"), + (r"\(\./runwhen-platform\.md\)", "(/authors/indexed-resources/runwhen-platform/)"), + (r"\(\.\./indexed-resources/README\.md\)", "(/authors/indexed-resources/)"), + (r"\(\.\./indexed-resources/([^)]+)\)", r"(/authors/indexed-resources/\1/)"), + (r"\(\.\./README\.md\)", "(/authors/generation-rules/schema/)"), + (r"\(\.\./\.\./\.\./generation-rules-guide\.md\)", "(/authors/generation-rules/syntax-reference/)"), + (r"\(\./tag-hierarchy-contract\.md\)", "(/authors/generation-rules/tag-hierarchy/)"), + (r"\(\./examples/([^)]+)\)", r"(/authors/generation-rules/examples/\1/)"), + (r"\(\.\./examples/([^)]+)\)", r"(/authors/generation-rules/examples/\1/)"), + (r"\(\.\./\.\./architecture/([^)#]+)(#[^)]+)?\)", rf"({_RWL_ARCH}/\1\2)"), + (r"\(\.\./\.\./user-guide/([^)]+)\)", rf"({_RWL_DOCS}/user-guide/\1)"), + (r"\[([^\]]+)\]\(\.\./\.\./architecture/[^)]+\)", r"\1 (see runwhen-local architecture docs)"), + (r"\[([^\]]+)\]\(\.\./\.\./user-guide/[^)]+\)", r"\1"), +] + + +def _strip_leading_h1(text: str) -> str: + lines = text.splitlines() + if lines and lines[0].startswith("# "): + lines = lines[1:] + while lines and not lines[0].strip(): + lines = lines[1:] + return "\n".join(lines) + + +def _convert_admonitions(text: str) -> str: + out: list[str] = [] + i = 0 + lines = text.splitlines() + while i < len(lines): + line = lines[i] + note_match = re.match(r"^>\s*\[!NOTE\]\s*$", line) + if note_match: + out.append(":::note") + i += 1 + while i < len(lines) and lines[i].startswith(">"): + out.append(lines[i][1:].lstrip() if lines[i].startswith("> ") else lines[i][1:]) + i += 1 + out.append(":::") + continue + out.append(line) + i += 1 + return "\n".join(out) + + +def _rewrite_links(text: str) -> str: + for pattern, replacement in _LINK_REWRITES: + text = re.sub(pattern, replacement, text) + return text + + +def _render_page(spec: PageSpec) -> str: + raw = spec.source.read_text(encoding="utf-8") + body = _strip_leading_h1(raw) + body = _convert_admonitions(body) + body = _rewrite_links(body) + label_line = "" + if spec.sidebar_label: + label_line = f' label: "{spec.sidebar_label}"\n' + hidden_line = "" + if spec.sidebar_hidden: + hidden_line = " hidden: true\n" + frontmatter = ( + "---\n" + f'title: "{spec.title}"\n' + f'description: "{spec.description}"\n' + "sidebar:\n" + f" order: {spec.sidebar_order}\n" + f"{label_line}" + f"{hidden_line}" + "---\n\n" + ) + if body and not body.startswith("##"): + body = f"## Overview\n\n{body}" + return frontmatter + body + ("\n" if body else "") + + +def sync(docs_repo: Path, check: bool = False) -> int: + authors_dir = docs_repo / _AUTHORS_ROOT + if not authors_dir.is_dir(): + print(f"ERROR: docs authors dir not found: {authors_dir}", file=sys.stderr) + return 1 + + drift = 0 + for spec in _pages(): + if not spec.source.is_file(): + print(f"ERROR: missing source {spec.source}", file=sys.stderr) + return 1 + rendered = _render_page(spec) + dest = authors_dir / spec.dest_rel + dest.parent.mkdir(parents=True, exist_ok=True) + if dest.exists() and dest.read_text(encoding="utf-8") == rendered: + print(f"OK {spec.dest_rel}") + continue + if check: + print(f"DRIFT {spec.dest_rel}") + drift += 1 + continue + dest.write_text(rendered, encoding="utf-8") + print(f"WROTE {spec.dest_rel}") + + return 1 if drift else 0 + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--docs-repo", + type=Path, + default=_DEFAULT_DOCS_REPO, + help=f"Path to runwhen/docs checkout (default: {_DEFAULT_DOCS_REPO})", + ) + parser.add_argument( + "--check", + action="store_true", + help="Exit 1 if destination files differ from rendered output", + ) + args = parser.parse_args() + raise SystemExit(sync(args.docs_repo, check=args.check)) + + +if __name__ == "__main__": + main() diff --git a/scripts/gcp/dump_gcp_resource_catalog.py b/scripts/gcp/dump_gcp_resource_catalog.py new file mode 100644 index 000000000..8855d5803 --- /dev/null +++ b/scripts/gcp/dump_gcp_resource_catalog.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Regenerate ``docs/authoring/indexed-resources/gcp-resource-catalog.md``. + +The catalog is the user-facing companion to ``gcp.md``: a single sortable +table of every GCP resource type the ``gcpapi`` indexer knows about, +grouped by service. It's derived directly from +``src/indexers/gcp_resource_type_registry.yaml`` (which itself is generated +from the CloudQuery GCP plugin's table list and the manual overrides in +``scripts/gcp/gcp_resource_type_overrides.yaml``). + +Run this script after editing ``gcp_resource_type_overrides.yaml`` and +re-running ``sync_gcp_resource_type_registry.py``. Hand-edits to the +generated catalog get overwritten; touch the registry / overrides instead. + +Usage:: + + python scripts/gcp/dump_gcp_resource_catalog.py +""" + +from __future__ import annotations + +import datetime as _dt +import sys +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[2] +_SRC = _REPO_ROOT / "src" +sys.path.insert(0, str(_SRC)) + +from indexers.gcp_resource_type_registry import load_registry # noqa: E402 + +_OUTPUT = ( + _REPO_ROOT + / "docs" + / "authoring" + / "indexed-resources" + / "gcp-resource-catalog.md" +) + + +def main() -> None: + registry = load_registry() + rows = sorted( + registry, + key=lambda e: ((e.category or "~"), e.cloudquery_table_name), + ) + typed_count = sum(1 for e in rows if e.typed_collector) + generated_at = _dt.datetime.now(_dt.timezone.utc).strftime("%Y-%m-%d") + + lines: list[str] = [] + lines.append("# GCP resource catalog") + lines.append("") + lines.append( + "Every GCP resource type the native `gcpapi` indexer can " + "discover. This page is the companion catalog for " + "[`gcp.md`](./gcp.md); see that page for how to enable the " + "indexer, what data each row carries, and the typed/generic " + "distinction." + ) + lines.append("") + lines.append( + f"_{len(rows)} resource types - {typed_count} typed (SDK collectors), " + f"{len(rows) - typed_count} generic (Cloud Asset Inventory pass). " + f"Generated {generated_at} from " + "`src/indexers/gcp_resource_type_registry.yaml`._" + ) + lines.append("") + lines.append( + "_Regenerate with `python scripts/gcp/dump_gcp_resource_catalog.py` " + "after touching the registry or overrides; do not hand-edit this file._" + ) + lines.append("") + lines.append( + "* `typed` - hand-written `google-cloud-*` collector; runs without CAI." + ) + lines.append( + "* `generic` - discoverable via the optional Cloud Asset Inventory " + "accelerator when a CAI asset type is mapped." + ) + lines.append("") + lines.append("| Service | CloudQuery table name | CAI asset type | Tier |") + lines.append("| --- | --- | --- | --- |") + for e in rows: + cat = e.category or "-" + cq = e.cloudquery_table_name + cai = e.cai_asset_type or "-" + tier = "typed" if e.typed_collector else "generic" + lines.append(f"| {cat} | `{cq}` | `{cai}` | {tier} |") + lines.append("") + + _OUTPUT.write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"Wrote {_OUTPUT.relative_to(_REPO_ROOT)} ({len(rows)} entries)") + + +if __name__ == "__main__": + main() diff --git a/scripts/kubernetes/dump_kubernetes_resource_catalog.py b/scripts/kubernetes/dump_kubernetes_resource_catalog.py new file mode 100644 index 000000000..9752a046e --- /dev/null +++ b/scripts/kubernetes/dump_kubernetes_resource_catalog.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Regenerate ``docs/authoring/indexed-resources/kubernetes-resource-catalog.md``.""" + +from __future__ import annotations + +import datetime as _dt +import sys +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[2] +_SRC = _REPO_ROOT / "src" +sys.path.insert(0, str(_SRC)) + +from indexers.kubetypes import KubernetesResourceType # noqa: E402 + +_OUTPUT = ( + _REPO_ROOT + / "docs" + / "authoring" + / "indexed-resources" + / "kubernetes-resource-catalog.md" +) + + +def main() -> None: + generated_at = _dt.datetime.now(_dt.timezone.utc).strftime("%Y-%m-%d") + lines = [ + "# Kubernetes resource catalog", + "", + "Built-in Kubernetes resource types the kubeapi indexer discovers.", + "", + f"_Generated {generated_at} from `indexers/kubetypes.py`._", + "", + "Custom CRDs are declared in generation rules (`resourceTypes`) and indexed", + "selectively — they are not listed here.", + "", + "| Resource type | Notes |", + "|---|---|", + ] + for resource_type in KubernetesResourceType: + lines.append(f"| `{resource_type.value}` | Built-in Kubernetes kind |") + lines.extend(["",]) + _OUTPUT.parent.mkdir(parents=True, exist_ok=True) + _OUTPUT.write_text("\n".join(lines), encoding="utf-8") + print(f"Wrote {_OUTPUT}") + + +if __name__ == "__main__": + main() diff --git a/scripts/runwhen/dump_runwhen_resource_catalog.py b/scripts/runwhen/dump_runwhen_resource_catalog.py new file mode 100644 index 000000000..f6fe40f4e --- /dev/null +++ b/scripts/runwhen/dump_runwhen_resource_catalog.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Regenerate ``docs/authoring/indexed-resources/runwhen-platform-resource-catalog.md``.""" + +from __future__ import annotations + +import datetime as _dt +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[2] +_OUTPUT = ( + _REPO_ROOT + / "docs" + / "authoring" + / "indexed-resources" + / "runwhen-platform-resource-catalog.md" +) + + +def main() -> None: + generated_at = _dt.datetime.now(_dt.timezone.utc).strftime("%Y-%m-%d") + lines = [ + "# RunWhen platform resource catalog", + "", + "Resource types indexed under `platform: runwhen`.", + "", + f"_Generated {generated_at} from `scripts/runwhen/dump_runwhen_resource_catalog.py`._", + "", + "| Resource type | Match names | Typed collector | Notes |", + "|---|---|---|---|", + "| `workspace` | `workspace` | yes | One instance per workspace-builder run |", + "", + "## match_resource properties (workspace)", + "", + "| Property | Description |", + "|---|---|", + "| `name` | Workspace name |", + "| `qualified_name` | Same as workspace name |", + "| `owner_email` | From workspaceInfo `workspaceOwnerEmail` |", + "| `location_id` | Default location id |", + "| `location_name` | Default location name |", + "", + ] + _OUTPUT.parent.mkdir(parents=True, exist_ok=True) + _OUTPUT.write_text("\n".join(lines), encoding="utf-8") + print(f"Wrote {_OUTPUT}") + + +if __name__ == "__main__": + main() diff --git a/src/component.py b/src/component.py index 83d24db99..92d07a6bf 100644 --- a/src/component.py +++ b/src/component.py @@ -248,7 +248,7 @@ def init_components(): # be added here, which is less than ideal, although practically may not be # a huge deal. component_stages_init = ( - (Stage.INDEXER, ["load_resources", "kubeapi", "azureapi", "gcpapi", "awsapi", "cloudquery", "azure_devops"]), + (Stage.INDEXER, ["load_resources", "kubeapi", "azureapi", "gcpapi", "awsapi", "cloudquery", "azure_devops", "runwhen_platform"]), (Stage.ENRICHER, ["generation_rules"]), (Stage.RENDERER, ["render_output_items", "dump_resources"]) ) diff --git a/src/enrichers/generation_rules.py b/src/enrichers/generation_rules.py index ac05d508e..e45062e84 100644 --- a/src/enrichers/generation_rules.py +++ b/src/enrichers/generation_rules.py @@ -35,6 +35,7 @@ from .gcp import GCPPlatformHandler, GCP_PLATFORM from .aws import AWSPlatformHandler, AWS_PLATFORM from .azure_devops import AzureDevOpsPlatformHandler +from .runwhen_platform import RunWhenPlatformHandler, RUNWHEN_PLATFORM from renderers.render_output_items import OUTPUT_ITEMS_PROPERTY from renderers.render_output_items import OutputItem as RendererOutputItem @@ -1183,6 +1184,7 @@ def load(context: Context) -> None: GCP_PLATFORM: GCPPlatformHandler(), AWS_PLATFORM: AWSPlatformHandler(), "azure_devops": AzureDevOpsPlatformHandler(), + RUNWHEN_PLATFORM: RunWhenPlatformHandler(), } context.set_property(PLATFORM_HANDLERS_PROPERTY_NAME, platform_handlers) request_code_collections = context.get_setting("CODE_COLLECTIONS") diff --git a/src/enrichers/runwhen_platform.py b/src/enrichers/runwhen_platform.py new file mode 100644 index 000000000..587a7554c --- /dev/null +++ b/src/enrichers/runwhen_platform.py @@ -0,0 +1,54 @@ +"""Platform handler for RunWhen platform generation rules.""" + +from __future__ import annotations + +from typing import Any, Optional + +from resources import Resource + +from .generation_rule_types import LevelOfDetail, PlatformHandler + +RUNWHEN_PLATFORM = "runwhen" +WORKSPACE_RESOURCE_TYPE = "workspace" + + +class RunWhenPlatformHandler(PlatformHandler): + def __init__(self) -> None: + super().__init__(RUNWHEN_PLATFORM) + + def get_level_of_detail(self, resource: Resource) -> LevelOfDetail: + return LevelOfDetail.DETAILED + + def get_resource_qualifier_value(self, resource: Resource, qualifier_name: str) -> Optional[str]: + if qualifier_name in ("workspace", "resource", "name"): + return resource.name + if qualifier_name == "owner_email": + return getattr(resource, "owner_email", None) + if qualifier_name == "location_id": + return getattr(resource, "location_id", None) + if qualifier_name == "location_name": + return getattr(resource, "location_name", None) + return None + + def get_resource_property_values(self, resource: Resource, property_name: str) -> Optional[list[Any]]: + property_name = property_name.lower() + if property_name == "name": + return [resource.name] + value = getattr(resource, property_name, None) + if value is not None: + return [value] + return None + + def get_standard_template_variables(self, resource: Resource) -> dict[str, Any]: + return { + "workspace_resource": { + "name": resource.name, + "qualified_name": resource.qualified_name, + "owner_email": getattr(resource, "owner_email", None), + "location_id": getattr(resource, "location_id", None), + "location_name": getattr(resource, "location_name", None), + } + } + + def resolve_template_variable_value(self, resource: Resource, variable_name: str) -> Optional[Any]: + return self.get_resource_qualifier_value(resource, variable_name) diff --git a/src/indexers/runwhen_platform.py b/src/indexers/runwhen_platform.py new file mode 100644 index 000000000..fde55af69 --- /dev/null +++ b/src/indexers/runwhen_platform.py @@ -0,0 +1,54 @@ +"""Index RunWhen platform resources for generation-rule matching. + +The ``runwhen`` platform exposes workspace-scoped resources so generation rules +can render SLXs without tying discovery to a cloud or Kubernetes object. +""" + +from __future__ import annotations + +import logging + +from component import Context +from resources import REGISTRY_PROPERTY_NAME, Registry + +logger = logging.getLogger(__name__) + +DOCUMENTATION = ( + "Index RunWhen platform resources (workspace anchor) for generation rules " + "with platform: runwhen" +) + +RUNWHEN_PLATFORM = "runwhen" +WORKSPACE_RESOURCE_TYPE = "workspace" + + +def index(context: Context) -> None: + workspace_name = context.get_setting("WORKSPACE_NAME") + workspace_owner_email = context.get_setting("WORKSPACE_OWNER_EMAIL") + location_id = context.get_setting("LOCATION_ID") + location_name = context.get_setting("LOCATION_NAME") + + if not workspace_name: + logger.warning("WORKSPACE_NAME not set; skipping runwhen platform indexing") + return + + registry: Registry = context.get_property(REGISTRY_PROPERTY_NAME) + attributes = { + "owner_email": workspace_owner_email, + "short_name": workspace_name, + "location_id": location_id, + "location_name": location_name, + "platform": RUNWHEN_PLATFORM, + "resource_type": WORKSPACE_RESOURCE_TYPE, + } + registry.add_resource( + RUNWHEN_PLATFORM, + WORKSPACE_RESOURCE_TYPE, + workspace_name, + workspace_name, + attributes, + ) + logger.info( + "Indexed runwhen platform workspace resource: name=%s", + workspace_name, + ) diff --git a/src/indexers/test_runwhen_platform.py b/src/indexers/test_runwhen_platform.py new file mode 100644 index 000000000..eb691de74 --- /dev/null +++ b/src/indexers/test_runwhen_platform.py @@ -0,0 +1,76 @@ +"""Tests for the runwhen platform indexer and platform handler.""" + +from __future__ import annotations + +import os +import sys +from unittest import TestCase +from unittest.mock import MagicMock + +_THIS_DIR = os.path.dirname(os.path.abspath(__file__)) +_SRC_DIR = os.path.dirname(_THIS_DIR) +if _SRC_DIR not in sys.path: + sys.path.insert(0, _SRC_DIR) + +from enrichers.runwhen_platform import ( # noqa: E402 + RUNWHEN_PLATFORM, + WORKSPACE_RESOURCE_TYPE, + RunWhenPlatformHandler, +) +from indexers import runwhen_platform # noqa: E402 +from resources import REGISTRY_PROPERTY_NAME, Registry, ResourceTypeSpec # noqa: E402 + + +class RunWhenPlatformIndexerTests(TestCase): + def test_index_adds_workspace_resource(self) -> None: + registry = Registry() + context = MagicMock() + context.get_property.return_value = registry + + def _setting(name: str): + values = { + "WORKSPACE_NAME": "demo-workspace", + "WORKSPACE_OWNER_EMAIL": "ops@example.com", + "LOCATION_ID": "loc-123", + "LOCATION_NAME": "shared-cluster", + } + return values.get(name) + + context.get_setting.side_effect = _setting + + runwhen_platform.index(context) + + resource_type = registry.lookup_resource_type(RUNWHEN_PLATFORM, WORKSPACE_RESOURCE_TYPE) + assert resource_type is not None + assert len(resource_type.instances) == 1 + resource = next(iter(resource_type.instances.values())) + assert resource.name == "demo-workspace" + assert resource.qualified_name == "demo-workspace" + assert resource.owner_email == "ops@example.com" + + +class RunWhenPlatformHandlerTests(TestCase): + def setUp(self) -> None: + self.handler = RunWhenPlatformHandler() + self.registry = Registry() + self.registry.add_resource( + RUNWHEN_PLATFORM, + WORKSPACE_RESOURCE_TYPE, + "demo-workspace", + "demo-workspace", + {"owner_email": "ops@example.com"}, + ) + self.context = MagicMock() + self.context.get_property.return_value = self.registry + + def test_get_resources_returns_workspace_instance(self) -> None: + spec = ResourceTypeSpec.construct_from_config("workspace", RUNWHEN_PLATFORM) + resources = list(self.handler.get_resources(spec, self.context)) + assert len(resources) == 1 + assert resources[0].name == "demo-workspace" + + def test_get_resource_qualifier_value_workspace(self) -> None: + spec = ResourceTypeSpec.construct_from_config("workspace", RUNWHEN_PLATFORM) + resource = list(self.handler.get_resources(spec, self.context))[0] + assert self.handler.get_resource_qualifier_value(resource, "workspace") == "demo-workspace" + assert self.handler.get_resource_property_values(resource, "name") == ["demo-workspace"] diff --git a/src/run.sh b/src/run.sh index 116199ad9..3374744b1 100755 --- a/src/run.sh +++ b/src/run.sh @@ -60,9 +60,9 @@ touch "$LOCK_FILE" # workspaceInfo.yaml (azureIndexerBackend=cloudquery, gcpIndexerBackend=cloudquery, # awsIndexerBackend=cloudquery). CloudQuery is still included below so the # override keeps working; by default it is a no-op for all three clouds. -COMPONENTS="load_resources,kubeapi,azureapi,gcpapi,awsapi,azure_devops,generation_rules,render_output_items,dump_resources" +COMPONENTS="load_resources,kubeapi,azureapi,gcpapi,awsapi,azure_devops,runwhen_platform,generation_rules,render_output_items,dump_resources" if [ $DISABLE_CLOUDQUERY -eq 0 ]; then - COMPONENTS="load_resources,kubeapi,azureapi,gcpapi,awsapi,cloudquery,azure_devops,generation_rules,render_output_items,dump_resources" + COMPONENTS="load_resources,kubeapi,azureapi,gcpapi,awsapi,cloudquery,azure_devops,runwhen_platform,generation_rules,render_output_items,dump_resources" fi # Run the Python script with your specified arguments