Metadata-Version: 2.4
Name: aws-resource-validator
Version: 2.2.0
Summary: Validate, get validation patterns and generate valid AWS resource names, plus Pydantic v2 models mirroring the boto3 typed-dicts for every AWS service.
License: Apache-2.0
License-File: LICENSE
Author: Alexy Grabov
Author-email: alexy.grabov@gmail.com
Requires-Python: >=3.11,<4.0
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Provides-Extra: ai
Provides-Extra: all
Provides-Extra: apigateway
Provides-Extra: apigatewayv2
Provides-Extra: athena
Provides-Extra: bedrock
Provides-Extra: cloudformation
Provides-Extra: cloudwatch
Provides-Extra: cognito-idp
Provides-Extra: compute
Provides-Extra: data
Provides-Extra: dynamodb
Provides-Extra: ec2
Provides-Extra: ecs
Provides-Extra: elbv2
Provides-Extra: events
Provides-Extra: firehose
Provides-Extra: generator
Provides-Extra: glue
Provides-Extra: iam
Provides-Extra: integration
Provides-Extra: kinesis
Provides-Extra: kms
Provides-Extra: lambda
Provides-Extra: logs
Provides-Extra: management
Provides-Extra: networking
Provides-Extra: rds
Provides-Extra: redshift
Provides-Extra: rest
Provides-Extra: route53
Provides-Extra: s3
Provides-Extra: sagemaker
Provides-Extra: secretsmanager
Provides-Extra: security
Provides-Extra: sns
Provides-Extra: sqs
Provides-Extra: ssm
Provides-Extra: stepfunctions
Provides-Extra: sts
Requires-Dist: aws-resource-validator-ai (==2.2.0) ; extra == "ai"
Requires-Dist: aws-resource-validator-ai (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-apigateway (==2.2.0) ; extra == "apigateway"
Requires-Dist: aws-resource-validator-apigatewayv2 (==2.2.0) ; extra == "apigatewayv2"
Requires-Dist: aws-resource-validator-athena (==2.2.0) ; extra == "athena"
Requires-Dist: aws-resource-validator-bedrock (==2.2.0) ; extra == "bedrock"
Requires-Dist: aws-resource-validator-cloudformation (==2.2.0) ; extra == "cloudformation"
Requires-Dist: aws-resource-validator-cloudwatch (==2.2.0) ; extra == "cloudwatch"
Requires-Dist: aws-resource-validator-cognito-idp (==2.2.0) ; extra == "cognito-idp"
Requires-Dist: aws-resource-validator-compute (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-compute (==2.2.0) ; extra == "compute"
Requires-Dist: aws-resource-validator-data (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-data (==2.2.0) ; extra == "data"
Requires-Dist: aws-resource-validator-dynamodb (==2.2.0) ; extra == "dynamodb"
Requires-Dist: aws-resource-validator-ec2 (==2.2.0) ; extra == "ec2"
Requires-Dist: aws-resource-validator-ecs (==2.2.0) ; extra == "ecs"
Requires-Dist: aws-resource-validator-elbv2 (==2.2.0) ; extra == "elbv2"
Requires-Dist: aws-resource-validator-events (==2.2.0) ; extra == "events"
Requires-Dist: aws-resource-validator-firehose (==2.2.0) ; extra == "firehose"
Requires-Dist: aws-resource-validator-glue (==2.2.0) ; extra == "glue"
Requires-Dist: aws-resource-validator-iam (==2.2.0) ; extra == "iam"
Requires-Dist: aws-resource-validator-integration (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-integration (==2.2.0) ; extra == "integration"
Requires-Dist: aws-resource-validator-kinesis (==2.2.0) ; extra == "kinesis"
Requires-Dist: aws-resource-validator-kms (==2.2.0) ; extra == "kms"
Requires-Dist: aws-resource-validator-lambda (==2.2.0) ; extra == "lambda"
Requires-Dist: aws-resource-validator-logs (==2.2.0) ; extra == "logs"
Requires-Dist: aws-resource-validator-management (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-management (==2.2.0) ; extra == "management"
Requires-Dist: aws-resource-validator-networking (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-networking (==2.2.0) ; extra == "networking"
Requires-Dist: aws-resource-validator-rds (==2.2.0) ; extra == "rds"
Requires-Dist: aws-resource-validator-redshift (==2.2.0) ; extra == "redshift"
Requires-Dist: aws-resource-validator-rest (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-rest (==2.2.0) ; extra == "rest"
Requires-Dist: aws-resource-validator-route53 (==2.2.0) ; extra == "route53"
Requires-Dist: aws-resource-validator-s3 (==2.2.0) ; extra == "s3"
Requires-Dist: aws-resource-validator-sagemaker (==2.2.0) ; extra == "sagemaker"
Requires-Dist: aws-resource-validator-secretsmanager (==2.2.0) ; extra == "secretsmanager"
Requires-Dist: aws-resource-validator-security (==2.2.0) ; extra == "all"
Requires-Dist: aws-resource-validator-security (==2.2.0) ; extra == "security"
Requires-Dist: aws-resource-validator-sns (==2.2.0) ; extra == "sns"
Requires-Dist: aws-resource-validator-sqs (==2.2.0) ; extra == "sqs"
Requires-Dist: aws-resource-validator-ssm (==2.2.0) ; extra == "ssm"
Requires-Dist: aws-resource-validator-stepfunctions (==2.2.0) ; extra == "stepfunctions"
Requires-Dist: aws-resource-validator-sts (==2.2.0) ; extra == "sts"
Requires-Dist: black ; extra == "generator"
Requires-Dist: botocore
Requires-Dist: exrex
Requires-Dist: jinja2 ; extra == "generator"
Requires-Dist: pydantic (>=2.13.5,<3.0)
Requires-Dist: requests ; extra == "generator"
Requires-Dist: rich
Requires-Dist: typer
Requires-Dist: typer ; extra == "generator"
Description-Content-Type: text/markdown


# AWS Resource Validator

![version](https://img.shields.io/github/v/release/CoreOxide/aws_resource_validator)
![PythonSupport](https://img.shields.io/static/v1?label=python&message=3.11-3.13&color=blue?style=flat-square&logo=python)
[![GitHub License](https://img.shields.io/github/license/CoreOxide/aws_resource_validator)](https://github.com/CoreOxide/aws_resource_validator/blob/main/LICENSE)]
![github-star-badge](https://img.shields.io/github/stars/CoreOxide/aws_resource_validator.svg?style=social)
![issues](https://img.shields.io/github/issues/CoreOxide/aws_resource_validator)

`aws_resource_validator` is a Python package that creates objects to validate, show constraints of common AWS resource names, and generate compatible patterns for tests. This helps ensure that AWS resource names comply with AWS naming rules and can be used for testing and validation purposes.

**[📜Documentation](https://coreoxide.github.io/aws_resource_validator/)** | **[Blogs website](https://alexy-grabov.medium.com/aws-resource-names-validation-and-generation-24ceb127e609)**

## Features

- **Developer CLI (`arv`)**: Validate names, inspect AWS constraints, and generate synthetic test values directly in your terminal with Rich UI output.
- **Validation**: Check if a given AWS resource name meets the AWS naming constraints.
- **Constraint Display**: Display constraints for different AWS resource names.
- **Pattern Generation**: Generate compatible patterns for AWS resource names for testing purposes.
- **Opt-in Pydantic pattern validation**: String fields on the generated Pydantic
  models can be checked against the AWS-documented regex + length bounds on
  demand, without changing the default construction path.

## Installation

The core package ships the resource validator and the `BaseValidatorModel`
runtime; per-service Pydantic models are shipped as extras so you only
download what you need.

```sh
# Core only (validators, generators, BaseValidatorModel).
pip install aws-resource-validator

# One or more individual services.
pip install 'aws-resource-validator[s3,ec2,lambda]'

# A whole domain shard (installs every service in that shard).
pip install 'aws-resource-validator[data]'       # storage, databases, analytics
pip install 'aws-resource-validator[security]'   # IAM, KMS, WAF, ...
pip install 'aws-resource-validator[compute]'    # EC2, Lambda, ECS, EKS, ...
pip install 'aws-resource-validator[ai]'         # Bedrock, SageMaker, ...
pip install 'aws-resource-validator[networking]' # VPC, DNS, CDN, ...
pip install 'aws-resource-validator[integration]' # SNS, SQS, EventBridge, ...
pip install 'aws-resource-validator[management]' # CloudWatch, CloudFormation, ...
pip install 'aws-resource-validator[rest]'       # Media, IoT, gaming, long tail

# Everything.
pip install 'aws-resource-validator[all]'

# Regenerate models yourself (maintainers only).
pip install 'aws-resource-validator[generator]'
```

See [`docs/packaging.md`](docs/packaging.md) for the full list of standalone
service packages, shard membership, and the detailed install matrix.

## Developer CLI (`arv`)

The package includes a command-line tool, `arv`, providing instant terminal validation, constraint inspection, and test data generation powered by [Rich](https://github.com/Textualize/rich).

```sh
# Validate an AWS resource name against AWS constraints
arv validate lambda FunctionName "my-lambda-function"

# Enforce strict end-to-end regex matching (rather than botocore prefix matching)
arv validate lambda FunctionName "invalid func! name" --strict

# Inspect naming limits, regex patterns, and sample values
arv inspect lambda FunctionName

# Inspect all patterned shapes available for a service
arv inspect dynamodb

# Generate compliant synthetic test names
arv generate lambda FunctionName --count 3

# Raw output for shell scripts and pipelines
arv generate lambda FunctionName --plain

# Machine-readable JSON output for CI/CD checks
arv validate lambda FunctionName "my-func" --json

# List registered AWS services and shape counts
arv list --search s3
```

## Python Usage Example

Here's a simple example demonstrating how to use `aws_resource_validator`:

```python
from aws_resource_validator.class_definitions import Acm, class_registry

# Use type hint so that you can use `api_registry` with full class definitions
acm: Acm = class_registry.Acm

print(acm.Arn.pattern)
print(acm.Arn.type)
print(acm.Arn.validate("example-arn"))
print(acm.Arn.generate())
```

Using Pydantic models for boto3 models:

```python
import boto3

from aws_resource_validator.pydantic_models.dynamodb.dynamodb_classes import ListTablesOutput

dynamodb = boto3.client('dynamodb')

def list_dynamo_tables() -> List[str]:
    return ListTablesOutput(**dynamodb.list_tables()).TableNames


if __name__ == "__main__":
    tables: List[str] = list_dynamo_tables()
    print("DynamoDB Tables:", tables)
```

### Opt-in pattern validation on generated Pydantic models

Generated models carry the AWS-documented regex + length bounds for every
string field backed by a botocore shape that defines one. The check is
**off by default** so that `Cls(**data)` behaves exactly as before — no
overhead, no new exceptions, full backward compatibility. Activate it per
call by passing `context={"aws_validate_patterns": True}` to
`model_validate`:

```python
from pydantic import ValidationError

from aws_resource_validator.pydantic_models.acm_pca.acm_pca_classes import (
    CreateCertificateAuthorityAuditReportRequestTypeDef as Req,
)

payload = {
    "CertificateAuthorityArn": "not-an-arn",
    "S3BucketName": "my-bucket",
    "AuditReportResponseFormat": "JSON",
}

# Default: no pattern check. Accepts the bad ARN silently.
Req.model_validate(payload)

# Opt-in: rejects values that don't match the AWS shape regex / length bounds.
try:
    Req.model_validate(payload, context={"aws_validate_patterns": True})
except ValidationError as exc:
    for err in exc.errors():
        # err["type"] == "aws_pattern" for fields that failed the AWS regex.
        print(err["loc"], err["type"], err["msg"])
```

Validation runs through `APIObject.validate(value)` from Pipeline A, so the
regex and length bounds are always in lockstep with `class_registry`.
Fields whose target shape has no regex (or whose annotation is more
complex than `str` / `Optional[str]` / `List[str]` / `Optional[List[str]]`)
are not decorated and pass through unchanged even when validation is
active. Unknown `(service, shape)` pairs resolve to a permissive no-op —
a stale emitter will never break a caller's validation call.

## Maintainer workflows

Day-to-day repo care is scripted under `scripts/release/`. All scripts are
invoked as modules (`python -m scripts.release.<name>`) so the `scripts/`
package resolves correctly. See [CLAUDE.md](CLAUDE.md) for the architectural
invariants these scripts assume.

### Regenerating Pydantic models after `poetry update`

`poetry update` can install a newer `boto3-stubs` whose TypedDict shapes
differ from the committed `pydantic_models/` tree. Run:

```sh
python -m scripts.release.regenerate           # Pipeline B + manifest sync + gauntlet
python -m scripts.release.regenerate --only s3 # scope to one service
python -m scripts.release.regenerate --pipeline-a  # also regen class_definitions.py (needs GITHUB_TOKEN)
python -m scripts.release.regenerate --dry-run     # preview without touching the tree
python -m scripts.release.regenerate --skip-checks # skip pytest + ruff + mypy
```

It wipes `aws_resource_validator/pydantic_models/`, reruns
`arv-generate pipeline-b`, re-syncs `pyproject.toml` extras and
`docs/packaging.md`, and runs the full pytest/ruff/mypy gauntlet. It
leaves changes unstaged for review; the suggested commit is printed at
the end. Pipeline A is off by default — it hits GitHub for live
botocore shapes and doesn't need to run on every stubs bump.

### Cutting a release

```sh
python -m scripts.release.prepare_release 2.0.3
```

Rewrites `__version__` + `[project].version`, re-pins every extra to
the new version via `sync_extras --write`, regenerates
`docs/packaging.md`, and runs the gauntlet. Leaves changes unstaged.
Then:

```sh
git add aws_resource_validator/__init__.py pyproject.toml docs/packaging.md
git commit -m "Bump version to 2.0.3"
git tag v2.0.3 && git push origin main v2.0.3
gh release create v2.0.3   # triggers release-package.yml
```

Publishing the GitHub release fires the `release-package.yml`
workflow, which builds the main wheel + 423 per-service wheels + 8
shard metapackages and uploads them to PyPI via
`scripts/release/publish_wheels.py`. The first release of a version
pays the one-time new-project registration cap (~65 min/chunk);
subsequent versions of existing projects upload in one shot.

### Other release-tooling entry points

| Script | Purpose |
|---|---|
| `build_subpackages.py` | Builds per-service + shard wheels into `dist/` (invoked by CI). |
| `publish_wheels.py` | PyPI uploader with new-project rate-limit handling. Client-side `--skip-existing` via the JSON API. |
| `verify_wheels.py` | Asserts wheel contents (no stray `__init__.py` under `pydantic_models/`, etc.). |
| `smoke_test.py` | Installs each freshly-built wheel into a throwaway venv and imports it. |
| `sync_extras.py --check` / `--write` | Reconciles `[project.optional-dependencies]` with `popular_services.txt` + `shards.toml`. CI enforces `--check`. |
| `sync_packaging_docs.py --check` / `--write` | Same for `docs/packaging.md`. |

### Popular services and shards

- `scripts/release/popular_services.txt` — one service name per line
  (directory form, e.g. `lambda_`). Each gets a dedicated
  `aws-resource-validator-<svc>` wheel and a top-level extras key.
- `scripts/release/shards.toml` — groups services into domain shards
  (metapackage wheels). Exactly one shard must have `catch_all = true`
  and it absorbs every service not explicitly listed elsewhere.

After editing either file, run
`python -m scripts.release.sync_extras --write` and
`python -m scripts.release.sync_packaging_docs --write` so
`pyproject.toml` and `docs/packaging.md` stay in sync.

### Known gotchas

- **The repo does not commit `poetry.lock`.** The circular constraint
  between the main wheel and the per-service sub-packages (pinned via
  `==<version>` in extras) can't be resolved by Poetry's lockfile
  resolver across a version bump. CI uses pip, not Poetry, for the
  same reason. See `.gitignore` for the why.
- **`pydantic_models/` is a PEP 420 namespace package.** No
  `__init__.py` under it, ever — adding one breaks cross-wheel imports
  from the `aws-resource-validator-<svc>` family. `verify_wheels.py`
  enforces this.
- **`lambda` is a Python keyword.** The service directory is
  `pydantic_models/lambda_/` but the extras key and PyPI project name
  are `lambda` and `aws-resource-validator-lambda`. Normalization
  happens in `scripts/release/_naming.py::extra_key`.

## Contributing

We welcome contributions from everyone. Please see our [CONTRIBUTING.md](CONTRIBUTING.md) for more details.

## Security

For information on reporting security vulnerabilities, please see our [SECURITY.md](SECURITY.md).

## Code of Conduct

Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.

## License

This project is licensed under the Apache-2.0 License. See the [LICENSE](LICENSE) file for details.

## Contact

If you have any questions, feel free to reach out to us:

- Alexy Grabov: [alexy.grabov@gmail.com](mailto:alexy.grabov@gmail.com) ![linkedin](https://img.shields.io/badge/LinkedIn-0077B5?style=flat-square&logo=linkedin&logoColor=white&link=https://www.linkedin.com/in/alexygrabov)
- Yafit Tupman: [ytupman@gmail.com](mailto:ytupman@gmail.com) ![linkedin](https://img.shields.io/badge/LinkedIn-0077B5?style=flat-square&logo=linkedin&logoColor=white&link=https://www.linkedin.com/in/yafit-tupman)

