diff --git a/.gitignore b/.gitignore index 3a5d60dda..7378e222a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,6 @@ coverage.xml /.pytest_cache/ /.mypy_cache/ taskcat_outputs/ -docs/apidocs/ # Doc Site site/ *.zip diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a12f0d31d..64729d903 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,4 @@ -exclude: ^(.travis.yml|.pre-commit-config.yaml|.bumpversion.cfg)$ +exclude: ^(.pre-commit-config.yaml|.bumpversion.cfg)$ fail_fast: true repos: - repo: https://github.com/pre-commit/mirrors-isort diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c0a4e9d46..000000000 --- a/.travis.yml +++ /dev/null @@ -1,144 +0,0 @@ -# taskcat ci config version v2 -# Python Versions -# Python: 3.7 -# -# Create development builds (Triggered by commit to develop branch) -# - Builds pypi package to https://test.pypi.org/project/taskcat/ -# - Tags development builds -# -dist: xenial -language: python - -branches: - only: - - main - -python: - - "3.7.2" - - "3.8" -before_install: - - pip install -r travis-specific-requirements.txt - - pip install -r dev-requirements.txt - - cd /tmp - - GIT_SECRETS_RELEASE=1.3.0 - - wget https://github.com/awslabs/git-secrets/archive/${GIT_SECRETS_RELEASE}.tar.gz - - tar -xvf ${GIT_SECRETS_RELEASE}.tar.gz - - cd git-secrets-${GIT_SECRETS_RELEASE}/ - - sudo make install - - cd ${TRAVIS_BUILD_DIR} -install: - - pip install . -script: pre-commit run --all-files - -jobs: - include: - - stage: "[Version Bump] Check/Create Release PR" - name: "[Version Bump] Check/Create Release PR" - if: branch = main AND commit_message !~ /(Bump|Release taskcat)/ AND type = push - before_script: - - | - pip install bump2version - HUB_DIST=linux-amd64 - HUB_VERSION=$(curl -w "%{url_effective}\n" -I -L -s -S github.com/github/hub/releases/latest -o /dev/null | awk -F'releases/tag/v' '{ print $2 }') - curl "https://github.com/github/hub/releases/download/v${HUB_VERSION}/hub-${HUB_DIST}-${HUB_VERSION}.tgz" -L | tar xvz && sudo ./hub-${HUB_DIST}-${HUB_VERSION}/install && rm -r ./hub-${HUB_DIST}-${HUB_VERSION} - - mkdir -p ~/.config/taskcat - - | - echo -e "github.com:\n- user: aws-ia-ci\n oauth_token: ${GHT}\n protocol: https" > ~/.config/hub - script: - - export RELEASE_ID=$(cut -f1-2 -d . VERSION) - - export ORIGINAL_VERSION=$(cat VERSION) - - git checkout "release/v${RELEASE_ID}" || git checkout -b "release/v${RELEASE_ID}" - - bumpversion --no-commit --allow-dirty --no-tag patch - - bumpversion --commit --allow-dirty --no-tag release --message "Bump Version - Creating a new minor version" - - export NEW_VERSION=$(cat VERSION) - - git push "https://${GHT}:@github.com/${TRAVIS_REPO_SLUG}" "release/v${RELEASE_ID}" --force || travis_terminate 1 - - | - OPEN_PR=$(hub pr list -s open --base main --head "release/v${RELEASE_ID}" -L 1 -f "%I") - if [ -z "${OPEN_PR}" ]; then - hub pull-request -m "Release taskcat [${NEW_VERSION}]" -h "release/v${RELEASE_ID}" - fi - - | - OPEN_PR=$(hub pr list -s open --base main --head "release/v${RELEASE_ID}" -L 1 -f "%I") - LAST_RELEASE_COMMIT=$(git rev-list --tags --max-count=1) - TAG_BODY=$(git --no-pager log --no-merges --oneline ${LAST_RELEASE_COMMIT}..HEAD --pretty='- %h %s') - hub api -XPATCH repos/${TRAVIS_REPO_SLUG}/issues/${OPEN_PR} -f body="${TAG_BODY}" - - - stage: "[Version Bump] Create PyPI Development release" - name: "[Version Bump] Create PyPI Development release" - if: branch = main AND type = push - before_script: - - pip install bump2version - - pip install packaging - - export UPSTREAM_PYPI_VERSION=$(python -c "from packaging import version; import requests; versions = requests.get('https://pypi.org/pypi/taskcat/json').json()['releases'].keys(); versions = [version.Version(x) for x in versions]; print(sorted(versions, reverse=True)[0])") - script: - - | - echo "${UPSTREAM_PYPI_VERSION}" | egrep -i '\.dev[0-9]{1,4}' - if [[ $? -eq 0 ]]; then - echo "Bumping the development version" - # Replacing VERSION (ex: 0.9.12) with upstream value (ex: 0.9.13.dev0) - sed -i -e "s,$(cat VERSION),${UPSTREAM_PYPI_VERSION},g" .bumpversion.cfg - sed -i -e "s,$(cat VERSION),${UPSTREAM_PYPI_VERSION},g" VERSION - # Now bumping 0.9.13.dev0 -> 0.9.13.dev1 - bumpversion --allow-dirty --no-tag --no-commit build - export NEW_DEV_BUILD=true - else - # v0.9.0 -> v0.9.1.dev0 - bumpversion --allow-dirty --no-tag --no-commit patch - fi - - cat VERSION - - | - if [[ "$(cat VERSION)" == "${UPSTREAM_PYPI_VERSION}" ]]; then - echo "Something went wrong when bumping the version. Exiting." - travis_terminate 1 - fi - - | - egrep -i '\.dev[0-9]{1,4}' VERSION - if [[ $? -eq 1 ]]; then - echo "No .dev pre-release tag found in VERSION. Not building PYPI package" - travis_terminate 1 - fi - deploy: - - provider: pypi - skip_cleanup: true - user: $PYPI_USER - password: $PYPI_PASSWORD - on: - branch: main - - - stage: "Tag build changelog/Push pypi and github release/Update docs" - name: "Tag build changelog/Push pypi and github release/Update docs" - if: branch = main AND fork = false AND type = push - script: - - | - echo "${TRAVIS_COMMIT_MESSAGE}" | egrep -i 'Merge pull request.*from aws-ia/release.*$' - if [[ $? -eq 0 ]]; then - LAST_RELEASE_COMMIT=$(git rev-list --tags --max-count=1) - TAG_BODY=$(git --no-pager log --no-merges --oneline ${LAST_RELEASE_COMMIT}..HEAD --pretty='- %h %s') - git tag -a "$(cat VERSION)" -m "${TAG_BODY}" - git push --tags "https://$GHT:@github.com/$TRAVIS_REPO_SLUG" - export RELEASE_THE_KRAKEN=true - fi - deploy: - - provider: releases - skip_cleanup: true - api_key: "$GHT" - file: directory/* - on: - branch: main - fork: false - condition: $RELEASE_THE_KRAKEN = true - - - provider: pypi - skip_cleanup: true - user: $PYPI_USER - password: $PYPI_PASSWORD - on: - branch: main - fork: false - condition: $RELEASE_THE_KRAKEN = true - - # Add Docker provider -cache: - directories: - - $HOME/.cache/pip - - $HOME/.cache/pre-commit diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 000000000..a039de99a --- /dev/null +++ b/DOCUMENTATION.md @@ -0,0 +1,167 @@ +# TaskCat Documentation Generation + +This guide explains how to generate and maintain TaskCat's documentation using the automated `gendocs.sh` script. + +## Quick Start + +```bash +# 1. First-time setup (installs dependencies and creates structure) +./gendocs.sh --install + +# 2. Preview documentation locally +./gendocs.sh --preview + +# 3. Build for production +./gendocs.sh --build + +# 4. Deploy to GitHub Pages +./gendocs.sh --deploy +``` + +## Script Options + +| Option | Short | Description | +|--------|-------|-------------| +| `--install` | `-i` | Install dependencies and create documentation structure | +| `--preview` | `-p` | Start local development server at http://localhost:8000 | +| `--build` | `-b` | Build static documentation site | +| `--deploy` | `-d` | Deploy to GitHub Pages | +| `--clean` | `-c` | Clean build artifacts | +| `--help` | `-h` | Show help message | + +## Documentation Structure + +After running `--install`, the following structure is created: + +``` +docs/ +├── index.md # Home page +├── installation.md # Installation guide +├── quickstart.md # Quick start guide +├── configuration.md # Configuration reference +├── user-guide/ # User guides +│ ├── template-testing.md +│ ├── multi-region.md +│ └── parameter-overrides.md +├── examples/ # Usage examples +│ ├── basic.md +│ └── advanced.md +├── reference/ # Auto-generated API docs +└── assets/ # Images and static files +``` + +## Features + +### Modern Design +- Material Design theme with dark/light mode toggle +- Responsive layout for mobile and desktop +- Professional appearance suitable for enterprise use + +### Auto-Generated API Documentation +- Automatically extracts docstrings from Python code +- Generates comprehensive API reference +- Maintains links between related functions and classes + +### Developer-Friendly +- Live reload during development +- Syntax highlighting for code blocks +- Tabbed content for multiple formats (YAML/JSON) +- Admonitions for tips, warnings, and notes + +### GitHub Integration +- One-command deployment to GitHub Pages +- Automatic edit links to source files +- Social links and repository information + +## Customization + +### Adding Content +1. Create new `.md` files in the `docs/` directory +2. Update the `nav` section in `mkdocs.yml` +3. Use standard Markdown with Material extensions + +### Styling +- Modify `mkdocs.yml` for theme customization +- Add custom CSS in `docs/assets/css/` +- Update colors, fonts, and layout options + +### API Documentation +The API documentation is automatically generated from your Python docstrings. The script: +1. Scans all Python files in the `taskcat/` directory +2. Extracts Google-style docstrings +3. Creates cross-referenced documentation +4. Maintains source code links + +## Deployment + +### GitHub Pages Setup +1. Enable GitHub Pages in repository settings +2. Set source to "GitHub Actions" or "gh-pages branch" +3. Run `./gendocs.sh --deploy` to publish + +### Continuous Integration +Add to your GitHub Actions workflow: + +```yaml +- name: Generate Documentation + run: | + ./gendocs.sh --install + ./gendocs.sh --build + ./gendocs.sh --deploy +``` + +## Troubleshooting + +### Common Issues + +**Python/pip not found:** +```bash +# Install Python 3.8+ and pip +# On macOS: brew install python +# On Ubuntu: apt-get install python3 python3-pip +``` + +**MkDocs command not found:** +```bash +./gendocs.sh --install # Reinstall dependencies +``` + +**Port 8000 already in use:** +```bash +# Kill existing process or use different port +mkdocs serve --dev-addr=localhost:8001 +``` + +### Getting Help +- Run `./gendocs.sh --help` for usage information +- Check MkDocs documentation: https://www.mkdocs.org/ +- Material theme docs: https://squidfunk.github.io/mkdocs-material/ + +## Best Practices + +1. **Keep docstrings updated** - API docs are generated from code +2. **Use consistent formatting** - Follow Google docstring style +3. **Add examples** - Include code examples in documentation +4. **Test locally** - Always preview before deploying +5. **Version control** - Commit documentation changes with code changes + +## Advanced Usage + +### Custom Plugins +Add plugins to `mkdocs.yml`: +```yaml +plugins: + - search + - mkdocstrings + - mermaid2 # For diagrams + - pdf-export # For PDF generation +``` + +### Multiple Versions +For version-specific documentation: +```bash +mike deploy --push --update-aliases 1.0 latest +mike set-default --push latest +``` + +This creates a professional documentation site that automatically stays in sync with your codebase and provides an excellent user experience for TaskCat users and contributors. diff --git a/README.md b/README.md deleted file mode 100644 index 344f3b226..000000000 --- a/README.md +++ /dev/null @@ -1,35 +0,0 @@ -[](https://taskcat.io/) -[](https://travis-ci.com/aws-ia/taskcat) [](https://badge.fury.io/py/taskcat) [](https://opensource.org/licenses/Apache-2.0) - - - -## What is TaskCat? -**TaskCat** is a tool that tests AWS CloudFormation templates. It deploys your AWS -CloudFormation template in multiple AWS Regions and generates a report with a pass/fail -grade for each region. You can specify the regions and number of Availability Zones you -want to include in the test, and pass in parameter values from your AWS CloudFormation -template. TaskCat is implemented as a Python class that you import, instantiate, and run. - -TaskCat was developed by the aws-ia team to test AWS CloudFormation templates -that automatically deploy workloads on AWS. We’re pleased to make the tool available to -all developers who want to validate their custom AWS CloudFormation templates across -AWS Regions - -__See [TaskCat documentation](https://aws-ia.github.io/taskcat/).__ - -## Support -[](https://github.com/aws-ia/taskcat/issues/new/choose) -[](https://github.com/aws-ia/taskcat/issues/new/choose) - -## GitHub - -[](https://github.com/aws-ia/taskcat) -[](https://github.com/aws-ia/taskcat/issues) -[](https://github.com/aws-ia/taskcat/issues?q=is%3Aissue+is%3Aclosed) -[](https://github.com/aws-ia/taskcat/pulls) -[](https://github.com/aws-ia/taskcat/pulls?q=is%3Apr+is%3Aclosed) - -## PyPi - -[](https://pypi.org/project/taskcat/#history) -[](https://pypi.org/project/taskcat/#history) diff --git a/do_docs_generate.sh b/do_docs_generate.sh deleted file mode 100755 index 3640a2a31..000000000 --- a/do_docs_generate.sh +++ /dev/null @@ -1,18 +0,0 @@ -# Clean up docs -mkdir -p docs/apidocs -mkdir -p docs/schema -# Install docs tools -pip install portray pdocs json-schema-for-humans - -# Gererate API docs -portray as_html taskcat -o docs/apidocs/ --overwrite - -# Generate taskcat schema docs -python3 generate_schema.py -generate-schema-doc --config expand_buttons=true taskcat/cfg/config_schema.json docs/schema/taskcat_schema.md - -printf "\n\nReformatting schema files to specifications. Ignore the end-of-file-fixer error.\n\n" -pre-commit run --all-files - -# Push to gh_pages -portray on_github_pages --overwrite diff --git a/docs-requirements.txt b/docs-requirements.txt new file mode 100644 index 000000000..ed8e46e06 --- /dev/null +++ b/docs-requirements.txt @@ -0,0 +1,11 @@ +mkdocs>=1.5.0 +mkdocs-material>=9.4.0 +mkdocstrings[python]>=0.23.0 +mkdocs-gen-files>=0.5.0 +mkdocs-literate-nav>=0.6.0 +mkdocs-section-index>=0.3.0 +mkdocs-minify-plugin>=0.7.0 +mkdocs-git-revision-date-localized-plugin>=1.2.0 +pymdown-extensions>=10.0.0 +pillow>=10.0.0 +cairosvg>=2.7.0 diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md deleted file mode 100644 index 1826dedae..000000000 --- a/docs/INSTALLATION.md +++ /dev/null @@ -1,56 +0,0 @@ - -## Installation - -Currently only installation via pip is supported. - -### Requirements - -[](https://pypi.org/project/taskcat/#history) - - -The host taskcat is run on requires access to an AWS account, this can be done by any -of the following mechanisms: - -1. Environment variables -2. Shared credential file (~/.aws/credentials) -3. AWS config file (~/.aws/config) -4. Assume Role provider -5. Boto2 config file (/etc/boto.cfg and ~/.boto) -6. Instance metadata service on an Amazon EC2 instance that has an IAM role configured. - -for more info see the [boto3 credential configuration documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html). - -!!! note - docker is only required if building lambda functions using a Dockerfile - -### Installing via pip3 - -```python -pip3 install taskcat -``` -### Installing via pip3 --user -*will install taskcat into homedir, useful if you get permissions errors with the regular method* - -```python -pip3 install taskcat --user -``` - -???+note - The user install dir is platform specific - - On Mac: - - - `~/Library/Python/3.x/bin/taskcat` - - On Linux: - - - `~/.local/bin` - -!!! warning - Be sure to add the python bin dir to your **$PATH** - -### Windows - -Taskcat on Windows is **not supported**. - -If you are running Windows 10 we recommend that you install [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about) and then install taskcat inside the WSL environment. For details, see [Install and configure TaskCat on Microsoft Windows 10](https://aws.amazon.com/blogs/infrastructure-and-automation/install-and-configure-taskcat-on-microsoft-windows-10/). diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 27992a063..000000000 --- a/docs/README.md +++ /dev/null @@ -1,34 +0,0 @@ -[](https://taskcat.io/) - -[](https://travis-ci.com/aws-ia/taskcat) [](https://badge.fury.io/py/taskcat) [](https://opensource.org/licenses/Apache-2.0) - - -## What is taskcat? -**taskcat** is a tool that tests AWS CloudFormation templates. It deploys your AWS -CloudFormation template in multiple AWS Regions and generates a report with a pass/fail -grade for each region. You can specify the regions and number of Availability Zones you -want to include in the test, and pass in parameter values from your AWS CloudFormation -template. taskcat is implemented as a Python class that you import, instantiate, and run. - -taskcat was developed by the aws-ia team to test AWS CloudFormation templates -that automatically deploy workloads on AWS. We’re pleased to make the tool available to -all developers who want to validate their custom AWS CloudFormation templates across -AWS Regions - - -## Support -[](https://github.com/aws-ia/taskcat/issues/new/choose) -[](https://github.com/aws-ia/taskcat/issues/new/choose) - -## GitHub - -[](https://github.com/aws-ia/taskcat) -[](https://github.com/aws-ia/taskcat/issues) -[](https://github.com/aws-ia/taskcat/issues?q=is%3Aissue+is%3Aclosed) -[](https://github.com/aws-ia/taskcat/pulls) -[](https://github.com/aws-ia/taskcat/pulls?q=is%3Apr+is%3Aclosed) - -## PyPi - -[](https://pypi.org/project/taskcat/#history) -[](https://pypi.org/project/taskcat/#history) diff --git a/docs/administrative/CODE_OF_CONDUCT.md b/docs/administrative/CODE_OF_CONDUCT.md index 754616508..a325d924b 100644 --- a/docs/administrative/CODE_OF_CONDUCT.md +++ b/docs/administrative/CODE_OF_CONDUCT.md @@ -2,11 +2,11 @@ ## 1. Purpose -A primary goal of TaskCat is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). +A primary goal of taskcat is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. -We invite all those who participate in TaskCat to help us create safe and positive experiences for everyone. +We invite all those who participate in taskcat to help us create safe and positive experiences for everyone. ## 2. Open Source Citizenship diff --git a/docs/administrative/CONTRIBUTING.md b/docs/administrative/CONTRIBUTING.md deleted file mode 100644 index 93ccf61b0..000000000 --- a/docs/administrative/CONTRIBUTING.md +++ /dev/null @@ -1,43 +0,0 @@ -# Contributing Guidelines - -Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional documentation, we greatly value feedback and contributions from our community. - -Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. - -Documentation Links: - -[Module Documentation](https://aws-ia.github.io/taskcat/) - -[User Guide](https://aws-ia.github.io/auto-testing.html) - -## Reporting Bugs/Feature Requests - -We welcome you to use the GitHub issue tracker to report bugs or suggest features. - -When filing an issue, please check [existing open](https://github.com/aws-ia/taskcat/issues), or [recently closed](https://github.com/aws-ia/taskcat/issues?q=is%3Aissue+is%3Aclosed), issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: - -* A reproducible test case or series of steps -* The version of our code being used -* Any modifications you've made relevant to the bug -* Anything unusual about your environment or deployment - -## Contributing via Pull Requests (Pull request template provided) -Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: - -1. All changes are staged into the *develop* branch (Send PR to the *develop* branch) -2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. -3. You open an issue to discuss any significant work - we would hate for your time to be wasted. - -To send us a pull request, please: - -1. Fork the repository. -2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. -3. Ensure local tests pass. -4. Commit to your fork using clear commit messages. -5. Send us a pull request, answering any default questions in the pull request interface. -6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. - -GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). - -## Licensing -We may ask you to affirm the Apache 2.0 agreement for larger changes. diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 000000000..2c31d1267 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,425 @@ +# API Reference + +Complete reference for taskcat's Python API and command-line interface. + +## Command Line Interface + +### Main Commands + +#### `taskcat test run` + +Execute taskcat tests with specified configuration. + +```bash +taskcat test run [OPTIONS] +``` + +**Options:** +- `--config-file, -c` - Path to configuration file (default: `.taskcat.yml`) +- `--regions` - Comma-separated list of regions to test +- `--tests` - Comma-separated list of tests to run +- `--no-delete` - Skip resource cleanup (for debugging) +- `--project-root` - Path to project root directory +- `--output-directory` - Directory for test outputs + +**Examples:** +```bash +# Run all tests +taskcat test run + +# Run specific test +taskcat test run --tests vpc-test + +# Run in specific regions +taskcat test run --regions us-east-1,us-west-2 + +# Keep resources for debugging +taskcat test run --no-delete +``` + +#### `taskcat lint` + +Validate taskcat configuration and CloudFormation templates. + +```bash +taskcat lint [OPTIONS] +``` + +**Options:** +- `--config-file, -c` - Path to configuration file +- `--templates` - Validate CloudFormation templates only +- `--strict` - Enable strict validation mode + +**Examples:** +```bash +# Lint configuration +taskcat lint + +# Lint specific file +taskcat lint -c custom.yml + +# Validate templates only +taskcat lint --templates +``` + +#### `taskcat test list` + +List available tests in configuration. + +```bash +taskcat test list [OPTIONS] +``` + +**Options:** +- `--config-file, -c` - Path to configuration file + +#### `taskcat upload` + +Upload templates and artifacts to S3. + +```bash +taskcat upload [OPTIONS] +``` + +**Options:** +- `--config-file, -c` - Path to configuration file +- `--bucket` - S3 bucket name +- `--key-prefix` - S3 key prefix + +### Global Options + +Available for all commands: + +- `--help, -h` - Show help message +- `--version` - Show version information +- `--debug` - Enable debug logging +- `--quiet, -q` - Suppress output + +## Python API + +### Core Classes + +#### `TaskCat` + +Main class for programmatic access to taskcat functionality. + +```python +from taskcat import TaskCat + +# Initialize TaskCat +tc = TaskCat( + config_file='.taskcat.yml', + project_root='/path/to/project', + regions=['us-east-1', 'us-west-2'] +) + +# Run tests +results = tc.test() + +# Get test results +for test_name, result in results.items(): + print(f"Test {test_name}: {result.status}") +``` + +#### `Config` + +Configuration management class. + +```python +from taskcat.config import Config + +# Load configuration +config = Config.create( + project_root='/path/to/project', + config_file='.taskcat.yml' +) + +# Access configuration +print(config.project.name) +print(config.tests.keys()) +``` + +#### `TestResult` + +Test execution result container. + +```python +# Access test results +result = tc.test()['test-name'] + +print(result.status) # PASS, FAIL, or ERROR +print(result.region) # AWS region +print(result.stack_name) # CloudFormation stack name +print(result.outputs) # Stack outputs +print(result.events) # CloudFormation events +``` + +### Configuration Objects + +#### `ProjectConfig` + +Project-level configuration. + +```python +project = config.project + +print(project.name) # Project name +print(project.regions) # Default regions +print(project.parameters) # Default parameters +print(project.s3_bucket) # S3 bucket +print(project.lambda_source_path) # Lambda source path +``` + +#### `TestConfig` + +Individual test configuration. + +```python +test = config.tests['test-name'] + +print(test.template) # Template path +print(test.parameters) # Test parameters +print(test.regions) # Test regions +print(test.auth) # Authentication settings +``` + +### Utility Functions + +#### Parameter Generation + +```python +from taskcat._template_params import ParamGen + +# Generate parameters +param_gen = ParamGen( + project_root='/path/to/project', + param_dict={'Password': '$[taskcat_genpass_16S]'}, + bucket_name='my-bucket', + region='us-east-1', + boto_client=boto3.client('cloudformation'), + project_name='my-project', + test_name='my-test' +) + +# Access generated parameters +generated_params = param_gen.results +print(generated_params['Password']) # Generated password +``` + +#### Template Processing + +```python +from taskcat._cfn_lint import CfnLint + +# Validate CloudFormation template +linter = CfnLint() +results = linter.lint_file('template.yaml') + +for result in results: + print(f"{result.level}: {result.message}") +``` + +### Exception Handling + +#### `TaskCatException` + +Base exception for taskcat errors. + +```python +from taskcat.exceptions import TaskCatException + +try: + tc = TaskCat(config_file='invalid.yml') + results = tc.test() +except TaskCatException as e: + print(f"TaskCat error: {e}") +``` + +#### Common Exceptions + +- `TaskCatException` - Base taskcat exception +- `ConfigError` - Configuration validation errors +- `TemplateError` - CloudFormation template errors +- `RegionError` - AWS region-related errors + +### Advanced Usage + +#### Custom Hooks + +```python +from taskcat import TaskCat + +class CustomTaskCat(TaskCat): + def pre_test_hook(self, test_name, region): + """Execute before each test""" + print(f"Starting test {test_name} in {region}") + + def post_test_hook(self, test_name, region, result): + """Execute after each test""" + print(f"Test {test_name} completed: {result.status}") + +# Use custom class +tc = CustomTaskCat(config_file='.taskcat.yml') +results = tc.test() +``` + +#### Parallel Execution + +```python +import concurrent.futures +from taskcat import TaskCat + +def run_test(test_config): + tc = TaskCat(config_file=test_config) + return tc.test() + +# Run tests in parallel +configs = ['test1.yml', 'test2.yml', 'test3.yml'] + +with concurrent.futures.ThreadPoolExecutor() as executor: + futures = [executor.submit(run_test, config) for config in configs] + results = [future.result() for future in futures] +``` + +#### Custom Parameter Generation + +```python +from taskcat._template_params import ParamGen + +class CustomParamGen(ParamGen): + def custom_function(self): + """Custom parameter generation function""" + return "custom-value" + + def transform_parameter(self): + # Call parent method + super().transform_parameter() + + # Add custom transformations + if '$[custom_function]' in self.param_value: + self.param_value = self.param_value.replace( + '$[custom_function]', + self.custom_function() + ) +``` + +## Integration Examples + +### CI/CD Integration + +```python +#!/usr/bin/env python3 +"""CI/CD integration script""" + +import sys +from taskcat import TaskCat +from taskcat.exceptions import TaskCatException + +def main(): + try: + # Initialize TaskCat + tc = TaskCat( + config_file='.taskcat.yml', + regions=['us-east-1', 'us-west-2'] + ) + + # Run tests + results = tc.test() + + # Check results + failed_tests = [ + name for name, result in results.items() + if result.status != 'PASS' + ] + + if failed_tests: + print(f"Failed tests: {failed_tests}") + sys.exit(1) + else: + print("All tests passed!") + sys.exit(0) + + except TaskCatException as e: + print(f"TaskCat error: {e}") + sys.exit(1) + +if __name__ == '__main__': + main() +``` + +### Custom Reporting + +```python +import json +from taskcat import TaskCat + +def generate_custom_report(results): + """Generate custom test report""" + report = { + 'summary': { + 'total_tests': len(results), + 'passed': sum(1 for r in results.values() if r.status == 'PASS'), + 'failed': sum(1 for r in results.values() if r.status == 'FAIL'), + }, + 'details': [] + } + + for test_name, result in results.items(): + report['details'].append({ + 'test_name': test_name, + 'status': result.status, + 'region': result.region, + 'stack_name': result.stack_name, + 'duration': result.duration, + 'outputs': result.outputs + }) + + return report + +# Run tests and generate report +tc = TaskCat(config_file='.taskcat.yml') +results = tc.test() +report = generate_custom_report(results) + +# Save report +with open('test-report.json', 'w') as f: + json.dump(report, f, indent=2) +``` + +## Environment Variables + +TaskCat recognizes these environment variables: + +- `AWS_PROFILE` - AWS profile to use +- `AWS_REGION` - Default AWS region +- `TASKCAT_CONFIG_FILE` - Default configuration file path +- `TASKCAT_PROJECT_ROOT` - Default project root directory +- `TASKCAT_DEBUG` - Enable debug logging (set to `1`) + +## Return Codes + +Command-line return codes: + +- `0` - Success +- `1` - General error +- `2` - Configuration error +- `3` - Template validation error +- `4` - Test execution error + +## Version Information + +```bash +# Get version +taskcat --version + +# Get detailed version info +taskcat --version --verbose +``` + +```python +# Get version programmatically +import taskcat +print(taskcat.__version__) +``` + +For more detailed API documentation, see the inline docstrings and type hints in the source code. diff --git a/docs/assets/css/cyborg-theme.css b/docs/assets/css/cyborg-theme.css new file mode 100644 index 000000000..f39572083 --- /dev/null +++ b/docs/assets/css/cyborg-theme.css @@ -0,0 +1,319 @@ +/* Cyborg Theme Customizations for taskcat */ + +:root { + /* Cyborg theme colors */ + --cyborg-bg: #060606; + --cyborg-bg-alt: #121212; + --cyborg-text: #fff; + --cyborg-text-muted: #888; + --cyborg-primary: #2a9fd6; + --cyborg-secondary: #555; + --cyborg-success: #77b300; + --cyborg-info: #9933cc; + --cyborg-warning: #ff8800; + --cyborg-danger: #cc0000; + --cyborg-border: #222; + --cyborg-border-light: #333; + --cyborg-code-bg: #222; + --cyborg-code-text: #0f0; +} + +/* Base overrides */ +body { + background-color: var(--cyborg-bg); + color: var(--cyborg-text); +} + +/* Header styling */ +.md-header { + background-color: var(--cyborg-bg-alt); + color: var(--cyborg-text); + border-bottom: 1px solid var(--cyborg-border); +} + +.md-header__title { + color: var(--cyborg-primary); + font-weight: 700; +} + +/* Navigation styling */ +.md-nav { + color: var(--cyborg-text); +} + +.md-nav__title { + color: var(--cyborg-primary); + font-weight: 700; +} + +.md-nav__link { + color: var(--cyborg-text) !important; +} + +.md-nav__link:hover { + color: var(--cyborg-primary) !important; +} + +.md-nav__link--active { + color: var(--cyborg-primary) !important; + font-weight: 700; +} + +/* Sidebar styling */ +.md-sidebar { + background-color: var(--cyborg-bg-alt); + border-right: 1px solid var(--cyborg-border); +} + +/* Typography */ +h1 { + color: var(--cyborg-primary) !important; + border-bottom: 2px solid var(--cyborg-primary); + padding-bottom: 0.5rem; +} + +h2 { + color: var(--cyborg-info) !important; +} + +h3 { + color: var(--cyborg-warning) !important; +} + +h4 { + color: var(--cyborg-success) !important; +} + +a { + color: var(--cyborg-primary) !important; +} + +a:hover { + color: var(--cyborg-info) !important; + text-decoration: underline; +} + +/* Code blocks */ +.highlight { + background-color: var(--cyborg-code-bg) !important; + border: 1px solid var(--cyborg-border-light); +} + +.highlight pre { + color: var(--cyborg-text) !important; +} + +/* Inline code */ +code { + background-color: var(--cyborg-code-bg) !important; + color: var(--cyborg-code-text) !important; + border: 1px solid var(--cyborg-border-light); + padding: 0.2em 0.4em; +} + +/* Syntax highlighting - Cyborg style */ +.highlight .k { color: #cc99cd !important; } /* Keyword */ +.highlight .s { color: #8fc13e !important; } /* String */ +.highlight .c { color: #999999 !important; font-style: italic; } /* Comment */ +.highlight .m { color: #f08d49 !important; } /* Number */ +.highlight .o { color: #f8f8f2 !important; } /* Operator */ +.highlight .p { color: #f8f8f2 !important; } /* Punctuation */ +.highlight .n { color: #f8f8f2 !important; } /* Name */ +.highlight .nf { color: #2a9fd6 !important; } /* Function name */ +.highlight .nb { color: #f08d49 !important; } /* Built-in */ + +/* Tables */ +table { + background-color: var(--cyborg-bg-alt) !important; + border: 1px solid var(--cyborg-border) !important; +} + +th { + background-color: var(--cyborg-bg-alt) !important; + color: var(--cyborg-primary) !important; + border-bottom: 2px solid var(--cyborg-primary) !important; +} + +td { + border-bottom: 1px solid var(--cyborg-border) !important; +} + +tr:hover { + background-color: var(--cyborg-bg) !important; +} + +/* Admonitions */ +.admonition { + background-color: var(--cyborg-bg-alt) !important; + border-left: 4px solid var(--cyborg-primary) !important; +} + +.admonition-title { + background-color: rgba(42, 159, 214, 0.1) !important; + color: var(--cyborg-primary) !important; +} + +.admonition.note { + border-left-color: var(--cyborg-info) !important; +} + +.admonition.note .admonition-title { + background-color: rgba(153, 51, 204, 0.1) !important; + color: var(--cyborg-info) !important; +} + +.admonition.warning { + border-left-color: var(--cyborg-warning) !important; +} + +.admonition.warning .admonition-title { + background-color: rgba(255, 136, 0, 0.1) !important; + color: var(--cyborg-warning) !important; +} + +.admonition.danger { + border-left-color: var(--cyborg-danger) !important; +} + +.admonition.danger .admonition-title { + background-color: rgba(204, 0, 0, 0.1) !important; + color: var(--cyborg-danger) !important; +} + +/* Buttons */ +.md-button { + background-color: var(--cyborg-primary) !important; + color: var(--cyborg-text) !important; + border: none !important; +} + +.md-button:hover { + background-color: var(--cyborg-info) !important; + color: var(--cyborg-text) !important; + transform: translateY(-1px); +} + +/* Search */ +.md-search__input { + background-color: var(--cyborg-bg) !important; + color: var(--cyborg-text) !important; + border: 1px solid var(--cyborg-border-light) !important; +} + +.md-search__input::placeholder { + color: var(--cyborg-text-muted) !important; +} + +/* Footer */ +.md-footer { + background-color: var(--cyborg-bg-alt) !important; + color: var(--cyborg-text-muted) !important; +} + +.md-footer-meta { + background-color: var(--cyborg-bg) !important; +} + +/* Tabs */ +.tabbed-set > .tabbed-labels { + background-color: var(--cyborg-bg-alt) !important; +} + +.tabbed-set > .tabbed-labels > label { + color: var(--cyborg-text) !important; + background-color: var(--cyborg-bg-alt) !important; +} + +.tabbed-set > .tabbed-labels > label:hover { + color: var(--cyborg-primary) !important; +} + +.tabbed-set > .tabbed-labels > label[for]:checked { + color: var(--cyborg-primary) !important; + border-bottom: 2px solid var(--cyborg-primary) !important; +} + +/* Copy code button */ +.md-clipboard { + color: var(--cyborg-text-muted) !important; +} + +.md-clipboard:hover { + color: var(--cyborg-primary) !important; +} + +/* Custom elements */ +.feature-card { + background-color: var(--cyborg-bg-alt); + border: 1px solid var(--cyborg-border); + padding: 1.5rem; + margin-bottom: 1.5rem; + transition: all 0.3s ease; +} + +.feature-card:hover { + border-color: var(--cyborg-primary); + box-shadow: 0 0 10px rgba(42, 159, 214, 0.3); + transform: translateY(-5px); +} + +.feature-card h3 { + color: var(--cyborg-primary) !important; + margin-top: 0; +} + +/* Schema styling */ +.schema-container { + background-color: var(--cyborg-bg-alt); + border: 1px solid var(--cyborg-border); + margin: 1rem 0; + padding: 1rem; +} + +.schema-property { + margin: 1rem 0; + padding: 1rem; + background-color: var(--cyborg-bg); + border-left: 4px solid var(--cyborg-primary); +} + +.schema-property-name { + color: var(--cyborg-primary); + font-weight: 700; + font-family: 'Roboto Mono', monospace; +} + +.schema-property-type { + color: var(--cyborg-warning); + font-size: 0.9rem; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .md-nav__title { + background-color: var(--cyborg-bg-alt) !important; + color: var(--cyborg-primary) !important; + } +} + +/* Print styles */ +@media print { + body { + background-color: white !important; + color: black !important; + } + + h1, h2, h3, h4, h5, h6 { + color: black !important; + } + + a { + color: blue !important; + } + + pre, code { + background-color: #f5f5f5 !important; + color: black !important; + border: 1px solid #ddd !important; + } +} diff --git a/docs/assets/images/tcat.png b/docs/assets/images/tcat.png new file mode 100644 index 000000000..f50516cf8 Binary files /dev/null and b/docs/assets/images/tcat.png differ diff --git a/docs/assets/js/cyborg-theme.js b/docs/assets/js/cyborg-theme.js new file mode 100644 index 000000000..726801222 --- /dev/null +++ b/docs/assets/js/cyborg-theme.js @@ -0,0 +1,344 @@ +// Cyborg Theme Enhancements for taskcat Documentation + +document.addEventListener('DOMContentLoaded', function() { + // Initialize Cyborg theme enhancements + initCyborgTheme(); + addCodeCopyButtons(); + enhanceNavigation(); + addKeyboardShortcuts(); + addNeonEffects(); +}); + +// Initialize Cyborg theme +function initCyborgTheme() { + // Add theme class to body + document.body.classList.add('cyborg-theme'); + + // Add theme version to footer + const footer = document.querySelector('.md-footer-copyright'); + if (footer) { + const themeInfo = document.createElement('div'); + themeInfo.className = 'md-footer-theme-info'; + themeInfo.innerHTML = 'Powered by Cyborg'; + footer.appendChild(themeInfo); + } +} + +// Add copy buttons to code blocks +function addCodeCopyButtons() { + const codeBlocks = document.querySelectorAll('.highlight pre'); + + codeBlocks.forEach(function(codeBlock) { + const wrapper = document.createElement('div'); + wrapper.className = 'code-wrapper'; + wrapper.style.position = 'relative'; + + codeBlock.parentNode.insertBefore(wrapper, codeBlock); + wrapper.appendChild(codeBlock); + + const copyButton = document.createElement('button'); + copyButton.className = 'copy-button'; + copyButton.innerHTML = ' Copy'; + copyButton.setAttribute('aria-label', 'Copy code to clipboard'); + copyButton.style.cssText = ` + position: absolute; + top: 5px; + right: 5px; + background: #2a9fd6; + color: #fff; + border: none; + border-radius: 3px; + padding: 5px 10px; + font-size: 12px; + cursor: pointer; + opacity: 0.8; + transition: all 0.3s ease; + z-index: 10; + `; + + copyButton.addEventListener('mouseenter', function() { + this.style.opacity = '1'; + this.style.boxShadow = '0 0 10px rgba(42, 159, 214, 0.7)'; + }); + + copyButton.addEventListener('mouseleave', function() { + this.style.opacity = '0.8'; + this.style.boxShadow = 'none'; + }); + + copyButton.addEventListener('click', function() { + const code = codeBlock.textContent; + + if (navigator.clipboard && window.isSecureContext) { + navigator.clipboard.writeText(code).then(function() { + showCopySuccess(copyButton); + }).catch(function() { + fallbackCopy(code, copyButton); + }); + } else { + fallbackCopy(code, copyButton); + } + }); + + wrapper.appendChild(copyButton); + }); +} + +// Fallback copy method for older browsers +function fallbackCopy(text, button) { + const textArea = document.createElement('textarea'); + textArea.value = text; + textArea.style.position = 'fixed'; + textArea.style.left = '-999999px'; + textArea.style.top = '-999999px'; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + document.execCommand('copy'); + showCopySuccess(button); + } catch (err) { + console.error('Failed to copy text: ', err); + button.innerHTML = ' Failed'; + button.style.background = '#cc0000'; + setTimeout(function() { + button.innerHTML = ' Copy'; + button.style.background = '#2a9fd6'; + }, 2000); + } + + document.body.removeChild(textArea); +} + +// Show copy success feedback +function showCopySuccess(button) { + const originalText = button.innerHTML; + button.innerHTML = ' Copied!'; + button.style.background = '#77b300'; + button.style.boxShadow = '0 0 10px rgba(119, 179, 0, 0.7)'; + + setTimeout(function() { + button.innerHTML = originalText; + button.style.background = '#2a9fd6'; + button.style.boxShadow = '0 0 10px rgba(42, 159, 214, 0.7)'; + }, 2000); +} + +// Enhance navigation +function enhanceNavigation() { + // Add active class to current page in navigation + const currentPath = window.location.pathname; + const navLinks = document.querySelectorAll('.md-nav__link'); + + navLinks.forEach(function(link) { + const href = link.getAttribute('href'); + if (href && currentPath.endsWith(href)) { + link.classList.add('md-nav__link--active'); + link.style.borderLeft = '3px solid #2a9fd6'; + link.style.paddingLeft = '10px'; + + // Expand parent sections + let parent = link.parentElement; + while (parent) { + if (parent.classList.contains('md-nav__item--nested')) { + parent.classList.add('md-nav__item--expanded'); + const input = parent.querySelector('input'); + if (input) { + input.checked = true; + } + } + parent = parent.parentElement; + } + } + }); + + // Add hover effects to navigation links + navLinks.forEach(function(link) { + link.addEventListener('mouseenter', function() { + if (!this.classList.contains('md-nav__link--active')) { + this.style.borderLeft = '3px solid #9933cc'; + this.style.paddingLeft = '10px'; + this.style.transition = 'all 0.3s ease'; + } + }); + + link.addEventListener('mouseleave', function() { + if (!this.classList.contains('md-nav__link--active')) { + this.style.borderLeft = 'none'; + this.style.paddingLeft = '0'; + } + }); + }); +} + +// Add keyboard shortcuts +function addKeyboardShortcuts() { + document.addEventListener('keydown', function(e) { + // Ctrl/Cmd + K for search + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { + e.preventDefault(); + const searchInput = document.querySelector('.md-search__input'); + if (searchInput) { + searchInput.focus(); + } + } + + // Escape to close search + if (e.key === 'Escape') { + const searchInput = document.querySelector('.md-search__input'); + if (searchInput && document.activeElement === searchInput) { + searchInput.blur(); + } + } + }); +} + +// Add neon effects for Cyborg theme +function addNeonEffects() { + // Add neon effect to headings + const headings = document.querySelectorAll('h1, h2, h3'); + headings.forEach(function(heading) { + heading.addEventListener('mouseenter', function() { + this.style.textShadow = '0 0 10px currentColor'; + this.style.transition = 'text-shadow 0.3s ease'; + }); + + heading.addEventListener('mouseleave', function() { + this.style.textShadow = 'none'; + }); + }); + + // Add neon effect to code blocks + const codeBlocks = document.querySelectorAll('.highlight'); + codeBlocks.forEach(function(block) { + block.addEventListener('mouseenter', function() { + this.style.boxShadow = '0 0 15px rgba(42, 159, 214, 0.5)'; + this.style.transition = 'box-shadow 0.3s ease'; + }); + + block.addEventListener('mouseleave', function() { + this.style.boxShadow = 'none'; + }); + }); + + // Add neon effect to buttons + const buttons = document.querySelectorAll('.md-button'); + buttons.forEach(function(button) { + button.addEventListener('mouseenter', function() { + this.style.boxShadow = '0 0 15px rgba(42, 159, 214, 0.7)'; + this.style.transition = 'all 0.3s ease'; + }); + + button.addEventListener('mouseleave', function() { + this.style.boxShadow = 'none'; + }); + }); +} + +// Add smooth scrolling for anchor links +function addSmoothScrolling() { + document.querySelectorAll('a[href^="#"]').forEach(function(anchor) { + anchor.addEventListener('click', function(e) { + const targetId = this.getAttribute('href').substring(1); + const targetElement = document.getElementById(targetId); + + if (targetElement) { + e.preventDefault(); + targetElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + + // Update URL without jumping + history.pushState(null, null, '#' + targetId); + } + }); + }); +} + +// Initialize smooth scrolling +setTimeout(addSmoothScrolling, 1000); + +// Add accessibility features +function addAccessibilityFeatures() { + // Add skip to content link + const skipLink = document.createElement('a'); + skipLink.href = '#main-content'; + skipLink.textContent = 'Skip to main content'; + skipLink.className = 'skip-link'; + skipLink.style.cssText = ` + position: absolute; + top: -40px; + left: 0; + background: #2a9fd6; + color: #fff; + padding: 8px; + z-index: 1000; + transition: top 0.3s; + `; + + skipLink.addEventListener('focus', function() { + this.style.top = '0'; + }); + + skipLink.addEventListener('blur', function() { + this.style.top = '-40px'; + }); + + document.body.insertBefore(skipLink, document.body.firstChild); + + // Add main content landmark + const content = document.querySelector('.md-content'); + if (content) { + content.setAttribute('id', 'main-content'); + content.setAttribute('role', 'main'); + } +} + +// Initialize accessibility features +setTimeout(addAccessibilityFeatures, 500); + +// Add print styles +function addPrintStyles() { + const printStyles = document.createElement('style'); + printStyles.textContent = ` + @media print { + .md-header, .md-tabs, .md-sidebar, .md-footer, .md-top, .md-dialog, .md-search { + display: none !important; + } + + .md-content { + margin: 0 !important; + max-width: 100% !important; + } + + .md-content__inner { + padding: 0 !important; + margin: 0 !important; + } + + body { + color: black !important; + background: white !important; + } + + h1, h2, h3, h4, h5, h6 { + color: black !important; + break-after: avoid !important; + } + + pre, blockquote, tr, img { + break-inside: avoid !important; + } + + .copy-button { + display: none !important; + } + } + `; + document.head.appendChild(printStyles); +} + +// Initialize print styles +addPrintStyles(); diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 000000000..35aab67c5 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,478 @@ +# Configuration + +Learn how to configure taskcat for your specific testing needs with comprehensive configuration options. + +## Configuration File Structure + +taskcat uses YAML configuration files (`.taskcat.yml`) with this structure: + +```yaml +general: + # Global settings applied to all tests + +project: + # Project-specific settings + +tests: + # Individual test definitions +``` + +## Basic Configuration + +### Minimal Configuration + +```yaml +project: + name: my-project + regions: + - us-east-1 + +tests: + basic: + template: template.yaml +``` + +### Standard Configuration + +```yaml +project: + name: my-cloudformation-project + regions: + - us-east-1 + - us-west-2 + parameters: + Environment: test + Owner: development-team + +tests: + vpc-test: + template: templates/vpc.yaml + parameters: + VpcCidr: 10.0.0.0/16 + + app-test: + template: templates/app.yaml + parameters: + InstanceType: t3.micro + DatabasePassword: $[taskcat_genpass_16S] +``` + +## Global Settings + +Configure settings that apply to all tests: + +```yaml +general: + regions: + - us-east-1 + - us-west-2 + - eu-west-1 + parameters: + Environment: production + ProjectName: my-project + tags: + CostCenter: "1001" + Department: Engineering + s3_regional_buckets: true +``` + +### Global Properties + +| Property | Description | Example | +|----------|-------------|---------| +| `regions` | Default regions for all tests | `["us-east-1", "us-west-2"]` | +| `parameters` | Global CloudFormation parameters | `{"Environment": "prod"}` | +| `tags` | CloudFormation stack tags | `{"Project": "taskcat"}` | +| `s3_bucket` | Custom S3 bucket name | `"my-taskcat-bucket"` | +| `s3_regional_buckets` | Enable regional buckets | `true` | +| `auth` | AWS authentication profiles | `{"default": "my-profile"}` | + +## Project Settings + +Configure project-specific options: + +```yaml +project: + name: enterprise-application + owner: platform-team@company.com + regions: + - us-east-1 + - us-west-2 + parameters: + ProjectName: enterprise-app + Environment: production + lambda_source_path: functions/source + lambda_zip_path: functions/packages + package_lambda: true + shorten_stack_name: true + s3_object_acl: bucket-owner-read +``` + +### Project Properties + +| Property | Description | Default | +|----------|-------------|---------| +| `name` | Project identifier | Required | +| `owner` | Project owner email | - | +| `template` | Default template path | - | +| `lambda_source_path` | Lambda source directory | `lambda_functions/source` | +| `lambda_zip_path` | Lambda package directory | `lambda_functions/packages` | +| `package_lambda` | Enable Lambda packaging | `true` | +| `build_submodules` | Build submodule Lambdas | `true` | +| `shorten_stack_name` | Use short stack names | `false` | +| `role_name` | CloudFormation service role | - | + +## Test Configuration + +Define individual tests with specific settings: + +```yaml +tests: + # Basic test + simple-test: + template: templates/simple.yaml + + # Test with parameters + parameterized-test: + template: templates/app.yaml + parameters: + InstanceType: t3.medium + DatabasePassword: $[taskcat_genpass_20S] + + # Test with specific regions + regional-test: + template: templates/global.yaml + regions: + - us-east-1 + - eu-west-1 + - ap-southeast-1 + + # Test with authentication + authenticated-test: + template: templates/secure.yaml + auth: + us-east-1: production-profile + eu-west-1: europe-profile +``` + +### Test Properties + +| Property | Description | Required | +|----------|-------------|----------| +| `template` | CloudFormation template path | ✅ | +| `parameters` | Test-specific parameters | - | +| `regions` | Test-specific regions | - | +| `auth` | Authentication overrides | - | +| `artifact_regions` | Artifact copy regions | - | + +## Advanced Configuration + +### Multi-Environment Setup + +```yaml +project: + name: multi-env-app + +tests: + development: + template: templates/app.yaml + parameters: + Environment: dev + InstanceType: t3.micro + DatabaseInstanceClass: db.t3.micro + regions: + - us-east-1 + + staging: + template: templates/app.yaml + parameters: + Environment: staging + InstanceType: t3.small + DatabaseInstanceClass: db.t3.small + regions: + - us-east-1 + - us-west-2 + + production: + template: templates/app.yaml + parameters: + Environment: prod + InstanceType: m5.large + DatabaseInstanceClass: db.r5.large + regions: + - us-east-1 + - us-west-2 + - eu-west-1 +``` + +### Cross-Account Testing + +```yaml +project: + name: cross-account-app + +tests: + development-account: + template: templates/app.yaml + auth: + default: dev-account-profile + parameters: + Environment: dev + + production-account: + template: templates/app.yaml + auth: + default: prod-account-profile + parameters: + Environment: prod +``` + +### Lambda Function Testing + +```yaml +project: + name: serverless-app + lambda_source_path: src/functions + lambda_zip_path: dist/functions + package_lambda: true + build_submodules: true + +tests: + lambda-test: + template: templates/serverless.yaml + parameters: + Runtime: python3.9 + MemorySize: 256 + Timeout: 30 +``` + +## Authentication Configuration + +Configure AWS authentication for different regions or accounts: + +### Profile-Based Authentication + +```yaml +general: + auth: + default: my-default-profile + us-gov-east-1: govcloud-profile + cn-north-1: china-profile + +project: + auth: + us-east-1: production-profile + eu-west-1: europe-profile +``` + +### Test-Specific Authentication + +```yaml +tests: + secure-test: + template: templates/secure.yaml + auth: + us-east-1: security-profile + us-west-2: security-profile +``` + +## Parameter Configuration + +### Static Parameters + +```yaml +tests: + static-test: + template: templates/app.yaml + parameters: + InstanceType: t3.medium + Environment: production + EnableLogging: true + Port: 8080 +``` + +### Dynamic Parameters + +```yaml +tests: + dynamic-test: + template: templates/app.yaml + parameters: + # Generate unique values + S3Bucket: $[taskcat_autobucket] + DatabasePassword: $[taskcat_genpass_16S] + UniqueId: $[taskcat_genuuid] + + # Environment-aware values + CurrentRegion: $[taskcat_current_region] + ProjectName: $[taskcat_project_name] + TestName: $[taskcat_test_name] + + # AWS resource values + AvailabilityZones: $[taskcat_genaz_2] + KeyPair: $[taskcat_getkeypair] + + # External values + DatabaseHost: $[taskcat_ssm_/app/database/host] + ApiKey: $[taskcat_secretsmanager_prod/api/key] +``` + +## S3 Configuration + +### Bucket Management + +```yaml +project: + # Use custom bucket + s3_bucket: my-custom-taskcat-bucket + + # Enable regional buckets + s3_regional_buckets: true + + # Set object ACL + s3_object_acl: bucket-owner-read + + # Enable legacy signature version + s3_enable_sig_v2: false +``` + +### Artifact Regions + +```yaml +general: + artifact_regions: + - us-east-1 + - us-west-2 + - eu-west-1 + +tests: + global-test: + template: templates/global.yaml + artifact_regions: + - us-east-1 + - ap-southeast-1 +``` + +## Hooks Configuration + +Execute custom scripts before or after tests: + +```yaml +general: + prehooks: + - type: script + config: + command: ./scripts/setup.sh + + posthooks: + - type: script + config: + command: ./scripts/cleanup.sh + +tests: + custom-test: + template: templates/app.yaml + prehooks: + - type: script + config: + command: ./scripts/test-setup.sh +``` + +## Validation and Linting + +Validate your configuration: + +```bash +# Lint configuration +taskcat lint + +# Lint specific file +taskcat lint --config-file custom.yml + +# Validate templates +taskcat lint --templates +``` + +## Best Practices + +### 1. Use Hierarchical Configuration + +```yaml +# Global defaults +general: + regions: + - us-east-1 + - us-west-2 + parameters: + Environment: test + +# Project overrides +project: + parameters: + ProjectName: my-app + +# Test-specific settings +tests: + production: + parameters: + Environment: prod # Overrides global +``` + +### 2. Leverage Dynamic Values + +```yaml +tests: + flexible-test: + template: templates/app.yaml + parameters: + # Avoid hardcoded values + S3Bucket: $[taskcat_autobucket] + DatabasePassword: $[taskcat_genpass_20S] + + # Use context-aware values + StackName: $[taskcat_project_name]-$[taskcat_test_name] + Region: $[taskcat_current_region] +``` + +### 3. Organize Templates + +```yaml +project: + name: organized-project + +tests: + infrastructure: + template: infrastructure/vpc.yaml + + database: + template: database/rds.yaml + + application: + template: application/app.yaml +``` + +### 4. Use Meaningful Names + +```yaml +tests: + # Good: Descriptive names + vpc-with-public-subnets: + template: templates/vpc-public.yaml + + rds-mysql-multi-az: + template: templates/rds-mysql.yaml + + # Avoid: Generic names + test1: + template: template1.yaml +``` + +## Configuration Examples + +See the [Examples](examples.md) page for complete, real-world configuration examples. + +## Next Steps + +- [Dynamic Values](dynamic-values.md) - Master runtime parameters +- [Parameter Overrides](parameter-overrides.md) - Advanced parameter techniques +- [Schema Reference](schema.md) - Complete configuration reference diff --git a/docs/custom.css b/docs/custom.css deleted file mode 100644 index a870e2055..000000000 --- a/docs/custom.css +++ /dev/null @@ -1,95 +0,0 @@ -.md-typeset .example > .admonition-title, .md-typeset .example > summary { - /* background-color: rgba(124,77,255,.1); */ - /* border-color: #7c4dff; */ - background-color: #FFECB3; - border-color: orange; -} - -.md-typeset .example > .admonition-title::before, .md-typeset .example > summary::before { - /* background-color: #7c4dff; */ - background-color: black; -} - -.md-typeset .admonition.example, .md-typeset details.example { - /* border-color: #7c4dff; */ - border-color: orange; -} -[data-md-color-primary="black"] { - /* --md-typeset-a-color: #4051b5; */ - --md-typeset-a-color: orange; -} - -pre { line-height: 125%; } -td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } -td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } -.codehilite .hll { background-color: #ffffcc } -.codehilite { background: #f8f8f8; } -.codehilite .c { color: #408080; font-style: italic } /* Comment */ -.codehilite .err { border: 1px solid #FF0000 } /* Error */ -.codehilite .k { color: #008000; font-weight: bold } /* Keyword */ -.codehilite .o { color: #666666 } /* Operator */ -.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */ -.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */ -.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */ -.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */ -.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */ -.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */ -.codehilite .gd { color: #A00000 } /* Generic.Deleted */ -.codehilite .ge { font-style: italic } /* Generic.Emph */ -.codehilite .gr { color: #FF0000 } /* Generic.Error */ -.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.codehilite .gi { color: #00A000 } /* Generic.Inserted */ -.codehilite .go { color: #888888 } /* Generic.Output */ -.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.codehilite .gs { font-weight: bold } /* Generic.Strong */ -.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.codehilite .gt { color: #0044DD } /* Generic.Traceback */ -.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.codehilite .kp { color: #008000 } /* Keyword.Pseudo */ -.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.codehilite .kt { color: #B00040 } /* Keyword.Type */ -.codehilite .m { color: #666666 } /* Literal.Number */ -.codehilite .s { color: #BA2121 } /* Literal.String */ -.codehilite .na { color: #7D9029 } /* Name.Attribute */ -.codehilite .nb { color: #008000 } /* Name.Builtin */ -.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -.codehilite .no { color: #880000 } /* Name.Constant */ -.codehilite .nd { color: #AA22FF } /* Name.Decorator */ -.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */ -.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -.codehilite .nf { color: #0000FF } /* Name.Function */ -.codehilite .nl { color: #A0A000 } /* Name.Label */ -.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */ -.codehilite .nv { color: #19177C } /* Name.Variable */ -.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -.codehilite .w { color: #bbbbbb } /* Text.Whitespace */ -.codehilite .mb { color: #666666 } /* Literal.Number.Bin */ -.codehilite .mf { color: #666666 } /* Literal.Number.Float */ -.codehilite .mh { color: #666666 } /* Literal.Number.Hex */ -.codehilite .mi { color: #666666 } /* Literal.Number.Integer */ -.codehilite .mo { color: #666666 } /* Literal.Number.Oct */ -.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */ -.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */ -.codehilite .sc { color: #BA2121 } /* Literal.String.Char */ -.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */ -.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ -.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */ -.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */ -.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -.codehilite .sx { color: #008000 } /* Literal.String.Other */ -.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */ -.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */ -.codehilite .ss { color: #19177C } /* Literal.String.Symbol */ -.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */ -.codehilite .fm { color: #0000FF } /* Name.Function.Magic */ -.codehilite .vc { color: #19177C } /* Name.Variable.Class */ -.codehilite .vg { color: #19177C } /* Name.Variable.Global */ -.codehilite .vi { color: #19177C } /* Name.Variable.Instance */ -.codehilite .vm { color: #19177C } /* Name.Variable.Magic */ -.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/docs/dynamic-values.md b/docs/dynamic-values.md new file mode 100644 index 000000000..2f5114435 --- /dev/null +++ b/docs/dynamic-values.md @@ -0,0 +1,334 @@ +# Dynamic Values + +Dynamic Values are runtime-evaluated parameters that provide flexible, context-aware configurations for your CloudFormation templates. These values are evaluated during taskcat execution and can pull data from your AWS environment, generate random values, or provide contextual information about your test run. + +## Overview + +Dynamic Values solve common testing challenges: + +- **Environment-specific values** - Pull actual values from your AWS environment +- **Unique resource names** - Generate random strings to avoid naming conflicts +- **Context awareness** - Access current region, project name, and test information +- **Security** - Generate secure passwords and retrieve secrets safely +- **Flexibility** - Reference other parameters and create complex configurations + +## Syntax + +Dynamic Values use the syntax: `$[taskcat_function_name]` or `$[taskcat_function_name_parameter]` + +```yaml +parameters: + DatabasePassword: $[taskcat_genpass_16S] + S3BucketName: $[taskcat_autobucket] + CurrentRegion: $[taskcat_current_region] + AvailabilityZones: $[taskcat_genaz_2] +``` + +## Complete Dynamic Values Reference + +### Random Value Generation + +| Dynamic Value | Description | Example Output | Use Case | +|---------------|-------------|----------------|----------| +| `$[taskcat_random-string]` | Generate 20-character random string | `kj8s9dkf7h3m2n4p5q6r` | Unique resource identifiers | +| `$[taskcat_random-numbers]` | Generate 20-digit random number | `12345678901234567890` | Unique numeric identifiers | +| `$[taskcat_genuuid]` | Generate UUID v1 | `550e8400-e29b-41d4-a716-446655440000` | Globally unique identifiers | + +### Password Generation + +| Dynamic Value | Description | Example | Use Case | +|---------------|-------------|---------|----------| +| `$[taskcat_genpass_8]` | 8-character alphanumeric password | `aB3dE7gH` | Simple passwords | +| `$[taskcat_genpass_16S]` | 16-character password with special chars | `aB3!dE7@gH9#kL2$` | Secure passwords | +| `$[taskcat_genpass_32A]` | 32-character alphanumeric password | `aB3dE7gH9kL2mN4pQ6rS8tU0vW2xY4zA` | Long secure passwords | + +**Password Types:** +- No suffix: Alphanumeric only +- `S`: Includes special characters (!@#$%^&*) +- `A`: Alphanumeric only (explicit) + +### AWS Environment Values + +| Dynamic Value | Description | Example Output | Use Case | +|---------------|-------------|----------------|----------| +| `$[taskcat_current_region]` | Current AWS region | `us-east-1` | Region-specific configurations | +| `$[taskcat_genaz_2]` | 2 availability zones | `us-east-1a,us-east-1b` | Multi-AZ deployments | +| `$[taskcat_genaz_3]` | 3 availability zones | `us-east-1a,us-east-1b,us-east-1c` | High availability setups | +| `$[taskcat_gensingleaz_1]` | Single AZ (1st available) | `us-east-1a` | Single AZ deployments | +| `$[taskcat_gensingleaz_2]` | Single AZ (2nd available) | `us-east-1b` | Specific AZ selection | + +### S3 and Storage + +| Dynamic Value | Description | Example Output | Use Case | +|---------------|-------------|----------------|----------| +| `$[taskcat_autobucket]` | Auto-generated S3 bucket name | `tcat-myproject-us-east-1-123456789` | Template artifacts | +| `$[taskcat_autobucket_prefix]` | S3 bucket prefix | `myproject-us-east-1-123456789` | Custom bucket naming | + +### Context Information + +| Dynamic Value | Description | Example Output | Use Case | +|---------------|-------------|----------------|----------| +| `$[taskcat_project_name]` | Current project name | `my-cloudformation-project` | Tagging and naming | +| `$[taskcat_test_name]` | Current test name | `production-test` | Test identification | +| `$[taskcat_git_branch]` | Current Git branch | `feature/new-feature` | Branch-specific configs | + +### Parameter References + +| Dynamic Value | Description | Example | Use Case | +|---------------|-------------|---------|----------| +| `$[taskcat_getval_ParameterName]` | Reference another parameter | `$[taskcat_getval_DatabasePassword]` | Parameter dependencies | + +### AWS Services Integration + +| Dynamic Value | Description | Example | Use Case | +|---------------|-------------|---------|----------| +| `$[taskcat_ssm_/path/to/parameter]` | Retrieve SSM Parameter | `$[taskcat_ssm_/app/database/host]` | Configuration management | +| `$[taskcat_secretsmanager_secret-name]` | Retrieve Secrets Manager value | `$[taskcat_secretsmanager_prod/db/password]` | Secure credential retrieval | + +### Legacy/Specialized Values + +| Dynamic Value | Description | Example Output | Use Case | +|---------------|-------------|----------------|----------| +| `$[taskcat_getkeypair]` | Default key pair name | `cikey` | EC2 key pair reference | +| `$[taskcat_getlicensebucket]` | License bucket placeholder | `override_this` | License content storage | +| `$[taskcat_getmediabucket]` | Media bucket placeholder | `override_this` | Media content storage | + +## Advanced Examples + +### Multi-Tier Application + +```yaml +project: + name: multi-tier-app + regions: + - us-east-1 + - us-west-2 + - eu-west-1 + +global: + parameters: + ProjectName: $[taskcat_project_name] + Environment: production + +tests: + vpc-infrastructure: + template: templates/vpc.yaml + parameters: + VpcName: $[taskcat_project_name]-vpc-$[taskcat_current_region] + AvailabilityZones: $[taskcat_genaz_3] + + database-tier: + template: templates/rds.yaml + parameters: + DBInstanceIdentifier: $[taskcat_project_name]-db-$[taskcat_random-string] + MasterUsername: admin + MasterUserPassword: $[taskcat_genpass_32S] + DBSubnetGroupName: $[taskcat_getval_VpcName]-db-subnets + + application-tier: + template: templates/app.yaml + parameters: + ApplicationName: $[taskcat_project_name]-app + InstanceType: m5.large + KeyName: $[taskcat_getkeypair] + S3Bucket: $[taskcat_autobucket] + DatabaseEndpoint: $[taskcat_getval_DBInstanceIdentifier] + + monitoring: + template: templates/monitoring.yaml + parameters: + DashboardName: $[taskcat_project_name]-$[taskcat_test_name]-dashboard + LogGroupName: /aws/lambda/$[taskcat_project_name] + AlertEmail: $[taskcat_ssm_/notifications/email] +``` + +### Environment-Specific Configuration + +```yaml +project: + name: environment-configs + regions: + - us-east-1 + +tests: + development: + template: templates/app.yaml + parameters: + Environment: dev + InstanceType: t3.micro + DatabasePassword: $[taskcat_genpass_16] + S3Bucket: $[taskcat_project_name]-dev-$[taskcat_current_region] + + staging: + template: templates/app.yaml + parameters: + Environment: staging + InstanceType: t3.small + DatabasePassword: $[taskcat_secretsmanager_staging/db/password] + S3Bucket: $[taskcat_project_name]-staging-$[taskcat_current_region] + + production: + template: templates/app.yaml + parameters: + Environment: prod + InstanceType: m5.large + DatabasePassword: $[taskcat_secretsmanager_prod/db/password] + S3Bucket: $[taskcat_project_name]-prod-$[taskcat_current_region] + BackupRetention: 30 + MonitoringEnabled: true +``` + +### Security-Focused Configuration + +```yaml +project: + name: secure-app + regions: + - us-east-1 + - us-west-2 + +tests: + secure-deployment: + template: templates/secure-app.yaml + parameters: + # Generate unique, secure passwords + DatabaseMasterPassword: $[taskcat_genpass_32S] + ApplicationSecret: $[taskcat_genpass_24S] + + # Use AWS Secrets Manager for production secrets + ApiKey: $[taskcat_secretsmanager_prod/api/key] + CertificateArn: $[taskcat_ssm_/ssl/certificate/arn] + + # Generate unique resource names + KMSKeyAlias: $[taskcat_project_name]-key-$[taskcat_genuuid] + S3BucketName: $[taskcat_autobucket] + + # Context-aware naming + LogGroupName: /aws/lambda/$[taskcat_project_name]-$[taskcat_current_region] + + # Reference other parameters + DatabasePasswordConfirm: $[taskcat_getval_DatabaseMasterPassword] +``` + +### Multi-Region Deployment + +```yaml +project: + name: global-app + regions: + - us-east-1 + - us-west-2 + - eu-west-1 + - ap-southeast-1 + +tests: + global-infrastructure: + template: templates/global-app.yaml + parameters: + # Region-specific configurations + PrimaryRegion: us-east-1 + CurrentRegion: $[taskcat_current_region] + + # Generate region-specific AZs + AvailabilityZones: $[taskcat_genaz_2] + + # Unique naming per region + S3BucketName: $[taskcat_project_name]-$[taskcat_current_region]-$[taskcat_random-numbers] + + # Global unique identifiers + DeploymentId: $[taskcat_genuuid] + + # Branch-specific configurations + GitBranch: $[taskcat_git_branch] + + # Environment from SSM + Environment: $[taskcat_ssm_/global/environment] +``` + +## Best Practices + +### 1. Use Appropriate Value Types + +```yaml +# ✅ Good: Use specific types for specific purposes +parameters: + DatabasePassword: $[taskcat_genpass_16S] # Secure password + ResourceId: $[taskcat_genuuid] # Globally unique + BucketName: $[taskcat_autobucket] # S3-compliant naming + +# ❌ Avoid: Using generic values for specific purposes +parameters: + DatabasePassword: $[taskcat_random-string] # Not secure enough + ResourceId: $[taskcat_random-numbers] # May not be unique +``` + +### 2. Leverage Parameter References + +```yaml +# ✅ Good: Reference parameters to maintain consistency +parameters: + MasterPassword: $[taskcat_genpass_20S] + PasswordConfirm: $[taskcat_getval_MasterPassword] + +# ❌ Avoid: Generating separate values for related parameters +parameters: + MasterPassword: $[taskcat_genpass_20S] + PasswordConfirm: $[taskcat_genpass_20S] # Different values! +``` + +### 3. Use Context-Aware Naming + +```yaml +# ✅ Good: Include context in resource names +parameters: + LogGroup: /aws/lambda/$[taskcat_project_name]-$[taskcat_current_region] + S3Bucket: $[taskcat_project_name]-logs-$[taskcat_current_region] + +# ❌ Avoid: Generic naming that may conflict +parameters: + LogGroup: /aws/lambda/myapp + S3Bucket: myapp-logs +``` + +### 4. Secure Credential Management + +```yaml +# ✅ Good: Use AWS services for production secrets +parameters: + DatabasePassword: $[taskcat_secretsmanager_prod/db/password] + ApiKey: $[taskcat_ssm_/app/api/key] + +# ✅ Good: Generate secure passwords for testing +parameters: + TestPassword: $[taskcat_genpass_16S] + +# ❌ Avoid: Hardcoded secrets +parameters: + DatabasePassword: "hardcoded-password" +``` + +## Troubleshooting + +### Common Issues + +**Dynamic Value not replaced:** +- Check syntax: `$[taskcat_function_name]` +- Verify function name spelling +- Ensure proper parameter placement + +**AWS service integration fails:** +- Verify IAM permissions for SSM/Secrets Manager +- Check parameter/secret exists in target region +- Validate parameter path format + +**AZ generation fails:** +- Check if region has enough AZs +- Verify region is enabled in your account +- Consider AZ exclusions in configuration + +**Parameter reference fails:** +- Ensure referenced parameter exists +- Check parameter name spelling +- Verify parameter is defined before reference + +For more troubleshooting help, see the [Troubleshooting Guide](troubleshooting.md). diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 000000000..352a9890c --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,653 @@ +# Examples + +Explore real-world taskcat configurations and learn from practical implementations. These examples demonstrate best practices, advanced features, and common use cases. + +## Basic Examples + +### Simple S3 Bucket Test + +```yaml +# .taskcat.yml +project: + name: simple-s3-test + regions: + - us-east-1 + +tests: + basic: + template: s3-bucket.yaml + parameters: + BucketName: $[taskcat_autobucket] +``` + +```yaml +# s3-bucket.yaml +AWSTemplateFormatVersion: '2010-09-09' +Description: Simple S3 bucket + +Parameters: + BucketName: + Type: String + +Resources: + TestBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Ref BucketName + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + +Outputs: + BucketName: + Value: !Ref TestBucket + BucketArn: + Value: !GetAtt TestBucket.Arn +``` + +### Multi-Region VPC Test + +```yaml +# .taskcat.yml +project: + name: vpc-multi-region + regions: + - us-east-1 + - us-west-2 + - eu-west-1 + +tests: + vpc-test: + template: vpc.yaml + parameters: + VpcCidr: 10.0.0.0/16 + AvailabilityZones: $[taskcat_genaz_2] + Environment: test +``` + +## Intermediate Examples + +### Web Application with Database + +```yaml +# .taskcat.yml +project: + name: web-app-with-db + regions: + - us-east-1 + - us-west-2 + parameters: + ProjectName: web-application + Environment: staging + +tests: + vpc-infrastructure: + template: templates/vpc.yaml + parameters: + VpcCidr: 10.0.0.0/16 + AvailabilityZones: $[taskcat_genaz_3] + + database: + template: templates/rds.yaml + parameters: + DatabaseName: webapp + DatabaseUsername: admin + DatabasePassword: $[taskcat_genpass_16S] + DatabaseInstanceClass: db.t3.micro + + web-application: + template: templates/web-app.yaml + parameters: + InstanceType: t3.medium + MinSize: 2 + MaxSize: 6 + KeyName: $[taskcat_getkeypair] + S3Bucket: $[taskcat_autobucket] +``` + +### Serverless Application + +```yaml +# .taskcat.yml +project: + name: serverless-api + regions: + - us-east-1 + - us-west-2 + lambda_source_path: src/functions + lambda_zip_path: dist/functions + package_lambda: true + +tests: + api-gateway: + template: templates/api-gateway.yaml + parameters: + ApiName: $[taskcat_project_name]-api + StageName: $[taskcat_test_name] + + lambda-functions: + template: templates/lambda.yaml + parameters: + FunctionName: $[taskcat_project_name]-function + Runtime: python3.9 + MemorySize: 256 + Timeout: 30 + S3Bucket: $[taskcat_autobucket] + + dynamodb-table: + template: templates/dynamodb.yaml + parameters: + TableName: $[taskcat_project_name]-table + BillingMode: PAY_PER_REQUEST +``` + +## Advanced Examples + +### Multi-Environment Enterprise Application + +```yaml +# .taskcat.yml +project: + name: enterprise-app + owner: platform-team@company.com + s3_regional_buckets: true + package_lambda: true + +general: + parameters: + ProjectName: enterprise-application + Owner: platform-team + tags: + CostCenter: "1001" + Department: Engineering + +tests: + development: + template: templates/main.yaml + regions: + - us-east-1 + parameters: + Environment: dev + InstanceType: t3.micro + DatabaseInstanceClass: db.t3.micro + MinSize: 1 + MaxSize: 2 + EnableMonitoring: false + BackupRetentionPeriod: 1 + + staging: + template: templates/main.yaml + regions: + - us-east-1 + - us-west-2 + parameters: + Environment: staging + InstanceType: t3.medium + DatabaseInstanceClass: db.t3.small + MinSize: 2 + MaxSize: 4 + EnableMonitoring: true + BackupRetentionPeriod: 7 + DatabasePassword: $[taskcat_genpass_20S] + + production: + template: templates/main.yaml + regions: + - us-east-1 + - us-west-2 + - eu-west-1 + parameters: + Environment: prod + InstanceType: m5.large + DatabaseInstanceClass: db.r5.large + MinSize: 3 + MaxSize: 10 + EnableMonitoring: true + EnableEncryption: true + MultiAZ: true + BackupRetentionPeriod: 30 + DatabasePassword: $[taskcat_secretsmanager_prod/db/password] + SSLCertificateArn: $[taskcat_ssm_/ssl/certificate/arn] + auth: + us-east-1: production-profile + us-west-2: production-profile + eu-west-1: europe-profile +``` + +### Cross-Account Deployment + +```yaml +# .taskcat.yml +project: + name: cross-account-app + +tests: + shared-services-account: + template: templates/shared-services.yaml + regions: + - us-east-1 + auth: + default: shared-services-profile + parameters: + Environment: shared + VpcCidr: 10.0.0.0/16 + + development-account: + template: templates/application.yaml + regions: + - us-east-1 + auth: + default: dev-account-profile + parameters: + Environment: dev + SharedServicesVpcId: $[taskcat_ssm_/shared/vpc/id] + InstanceType: t3.micro + + production-account: + template: templates/application.yaml + regions: + - us-east-1 + - us-west-2 + auth: + default: prod-account-profile + parameters: + Environment: prod + SharedServicesVpcId: $[taskcat_ssm_/shared/vpc/id] + InstanceType: m5.large + DatabasePassword: $[taskcat_secretsmanager_prod/db/password] +``` + +### Microservices Architecture + +```yaml +# .taskcat.yml +project: + name: microservices-platform + regions: + - us-east-1 + - us-west-2 + lambda_source_path: services + package_lambda: true + +general: + parameters: + Platform: microservices + Environment: production + tags: + Architecture: microservices + ManagedBy: taskcat + +tests: + infrastructure: + template: templates/infrastructure.yaml + parameters: + VpcCidr: 10.0.0.0/16 + AvailabilityZones: $[taskcat_genaz_3] + ClusterName: $[taskcat_project_name]-cluster + + user-service: + template: templates/microservice.yaml + parameters: + ServiceName: user-service + ContainerImage: user-service:latest + ContainerPort: 8080 + DesiredCount: 3 + DatabaseName: users + DatabasePassword: $[taskcat_genpass_20S] + + order-service: + template: templates/microservice.yaml + parameters: + ServiceName: order-service + ContainerImage: order-service:latest + ContainerPort: 8081 + DesiredCount: 2 + DatabaseName: orders + DatabasePassword: $[taskcat_genpass_20S] + + notification-service: + template: templates/lambda-service.yaml + parameters: + ServiceName: notification-service + Runtime: python3.9 + MemorySize: 512 + Timeout: 60 + QueueName: $[taskcat_project_name]-notifications + + api-gateway: + template: templates/api-gateway.yaml + parameters: + ApiName: $[taskcat_project_name]-api + StageName: v1 + UserServiceEndpoint: $[taskcat_getval_UserServiceEndpoint] + OrderServiceEndpoint: $[taskcat_getval_OrderServiceEndpoint] +``` + +### Data Pipeline + +```yaml +# .taskcat.yml +project: + name: data-pipeline + regions: + - us-east-1 + parameters: + DataBucket: $[taskcat_autobucket] + Environment: production + +tests: + data-ingestion: + template: templates/data-ingestion.yaml + parameters: + KinesisStreamName: $[taskcat_project_name]-stream + KinesisShardCount: 2 + FirehoseDeliveryStreamName: $[taskcat_project_name]-firehose + S3Bucket: $[taskcat_getval_DataBucket] + + data-processing: + template: templates/data-processing.yaml + parameters: + GlueJobName: $[taskcat_project_name]-etl + GlueJobScript: s3://$[taskcat_getval_DataBucket]/scripts/etl.py + DatabaseName: $[taskcat_project_name]_db + TableName: processed_data + + data-analytics: + template: templates/data-analytics.yaml + parameters: + RedshiftClusterIdentifier: $[taskcat_project_name]-cluster + RedshiftDatabaseName: analytics + RedshiftMasterUsername: admin + RedshiftMasterPassword: $[taskcat_genpass_20S] + RedshiftNodeType: dc2.large + RedshiftNumberOfNodes: 2 +``` + +## Specialized Examples + +### Security-Focused Deployment + +```yaml +# .taskcat.yml +project: + name: secure-application + regions: + - us-east-1 + - us-west-2 + +tests: + security-baseline: + template: templates/security-baseline.yaml + parameters: + EnableCloudTrail: true + EnableGuardDuty: true + EnableSecurityHub: true + EnableConfig: true + CloudTrailS3Bucket: $[taskcat_autobucket] + + encrypted-application: + template: templates/encrypted-app.yaml + parameters: + KMSKeyAlias: $[taskcat_project_name]-key + DatabasePassword: $[taskcat_secretsmanager_prod/db/password] + SSLCertificateArn: $[taskcat_ssm_/ssl/certificate/arn] + EnableEncryptionAtRest: true + EnableEncryptionInTransit: true + InstanceType: m5.large + + compliance-monitoring: + template: templates/compliance.yaml + parameters: + ComplianceFramework: SOC2 + LogRetentionPeriod: 2557 # 7 years in days + EnableLogEncryption: true + MonitoringS3Bucket: $[taskcat_autobucket] +``` + +### Disaster Recovery Setup + +```yaml +# .taskcat.yml +project: + name: disaster-recovery + +tests: + primary-region: + template: templates/primary-infrastructure.yaml + regions: + - us-east-1 + parameters: + Environment: production + IsPrimaryRegion: true + DatabaseInstanceClass: db.r5.xlarge + MultiAZ: true + BackupRetentionPeriod: 35 + CrossRegionBackupEnabled: true + ReplicationTargetRegion: us-west-2 + + disaster-recovery-region: + template: templates/dr-infrastructure.yaml + regions: + - us-west-2 + parameters: + Environment: production + IsDRRegion: true + DatabaseInstanceClass: db.r5.large + ReadReplicaSourceRegion: us-east-1 + AutomatedBackupRetentionPeriod: 35 + + failover-automation: + template: templates/failover-automation.yaml + regions: + - us-east-1 + - us-west-2 + parameters: + PrimaryRegion: us-east-1 + DRRegion: us-west-2 + Route53HealthCheckUrl: https://api.example.com/health + FailoverThreshold: 3 +``` + +## Testing Patterns + +### Blue-Green Deployment Testing + +```yaml +# .taskcat.yml +project: + name: blue-green-deployment + +tests: + blue-environment: + template: templates/application.yaml + parameters: + Environment: blue + Version: v1.0.0 + TrafficWeight: 100 + InstanceType: m5.large + + green-environment: + template: templates/application.yaml + parameters: + Environment: green + Version: v1.1.0 + TrafficWeight: 0 + InstanceType: m5.large + + traffic-shifting: + template: templates/traffic-manager.yaml + parameters: + BlueEnvironmentArn: $[taskcat_getval_BlueEnvironmentArn] + GreenEnvironmentArn: $[taskcat_getval_GreenEnvironmentArn] + InitialTrafficPercentage: 10 +``` + +### A/B Testing Infrastructure + +```yaml +# .taskcat.yml +project: + name: ab-testing-platform + +tests: + variant-a: + template: templates/application-variant.yaml + parameters: + VariantName: A + FeatureFlags: feature-a-enabled + InstanceType: m5.large + TrafficPercentage: 50 + + variant-b: + template: templates/application-variant.yaml + parameters: + VariantName: B + FeatureFlags: feature-b-enabled + InstanceType: m5.large + TrafficPercentage: 50 + + analytics-infrastructure: + template: templates/analytics.yaml + parameters: + KinesisStreamName: $[taskcat_project_name]-events + ElasticsearchDomain: $[taskcat_project_name]-analytics + KibanaDashboardName: ab-testing-dashboard +``` + +## Best Practices Examples + +### Parameterized and Reusable + +```yaml +# .taskcat.yml - Good example of reusable configuration +project: + name: reusable-infrastructure + parameters: + # Common parameters + ProjectName: $[taskcat_project_name] + Owner: platform-team + +general: + parameters: + # Global defaults + Environment: test + EnableMonitoring: true + tags: + ManagedBy: taskcat + Project: $[taskcat_project_name] + +tests: + # Small deployment for development + small: + template: templates/scalable-app.yaml + parameters: + Size: small + InstanceType: t3.micro + MinSize: 1 + MaxSize: 2 + DatabaseInstanceClass: db.t3.micro + + # Medium deployment for staging + medium: + template: templates/scalable-app.yaml + parameters: + Size: medium + InstanceType: t3.medium + MinSize: 2 + MaxSize: 4 + DatabaseInstanceClass: db.t3.small + + # Large deployment for production + large: + template: templates/scalable-app.yaml + parameters: + Size: large + InstanceType: m5.large + MinSize: 3 + MaxSize: 10 + DatabaseInstanceClass: db.r5.large + EnableEncryption: true + MultiAZ: true +``` + +### Security Best Practices + +```yaml +# .taskcat.yml - Security-focused configuration +project: + name: secure-by-design + +tests: + security-compliant: + template: templates/secure-application.yaml + parameters: + # Use Secrets Manager for sensitive data + DatabasePassword: $[taskcat_secretsmanager_prod/db/password] + ApiKey: $[taskcat_secretsmanager_prod/api/key] + + # Use SSM for configuration + DatabaseEndpoint: $[taskcat_ssm_/app/database/endpoint] + CacheEndpoint: $[taskcat_ssm_/app/cache/endpoint] + + # Generate unique, secure values + EncryptionKey: $[taskcat_genuuid] + S3Bucket: $[taskcat_autobucket] + + # Security settings + EnableEncryption: true + EnableLogging: true + EnableMonitoring: true + RestrictPublicAccess: true +``` + +## Integration Examples + +### CI/CD Pipeline Integration + +```yaml +# .taskcat.yml for CI/CD +project: + name: cicd-integration + +tests: + pull-request: + template: templates/app.yaml + regions: + - us-east-1 + parameters: + Environment: pr-$[taskcat_git_branch] + InstanceType: t3.micro + + staging-deployment: + template: templates/app.yaml + regions: + - us-east-1 + - us-west-2 + parameters: + Environment: staging + InstanceType: t3.medium + GitCommit: $[taskcat_git_branch] + + production-deployment: + template: templates/app.yaml + regions: + - us-east-1 + - us-west-2 + - eu-west-1 + parameters: + Environment: production + InstanceType: m5.large + GitCommit: $[taskcat_git_branch] + DatabasePassword: $[taskcat_secretsmanager_prod/db/password] +``` + +These examples demonstrate the flexibility and power of taskcat for testing CloudFormation templates across various scenarios, from simple single-resource tests to complex multi-tier applications and enterprise deployments. + +## Next Steps + +- [Configuration Guide](configuration.md) - Detailed configuration options +- [Dynamic Values](dynamic-values.md) - Runtime-evaluated parameters +- [Parameter Overrides](parameter-overrides.md) - Advanced parameter techniques +- [Schema Reference](schema.md) - Complete configuration reference diff --git a/docs/examples/advanced.md b/docs/examples/advanced.md new file mode 100644 index 000000000..702e3fd96 --- /dev/null +++ b/docs/examples/advanced.md @@ -0,0 +1,86 @@ +# Advanced Examples + +This page covers more complex taskcat configurations and use cases. + +## Multi-Test Configuration + +```yaml +# .taskcat.yml +project: + name: enterprise-app + regions: + - us-east-1 + - us-west-2 + - eu-west-1 + +global: + parameters: + Environment: testing + Owner: devops-team + +tests: + infrastructure: + template: templates/infrastructure.yaml + parameters: + VpcCidr: 10.0.0.0/16 + AvailabilityZones: $[taskcat_genaz_3] + + application: + template: templates/application.yaml + parameters: + InstanceType: t3.medium + DatabasePassword: $[taskcat_genpass_16S] + + monitoring: + template: templates/monitoring.yaml + regions: + - us-east-1 # Only deploy monitoring in primary region +``` + +## Using AWS Service Integration + +```yaml +tests: + app-with-secrets: + template: templates/app.yaml + parameters: + # Get AMI ID from SSM Parameter Store + LatestAMI: $[taskcat_ssm_/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2] + + # Get database credentials from Secrets Manager + DatabaseCredentials: $[taskcat_secretsmanager_prod/database/master] + + # Use current region for region-specific resources + DeploymentRegion: $[taskcat_current_region] + + # Generate unique identifiers + UniqueId: $[taskcat_genuuid] +``` + +## Parameter Validation + +```yaml +tests: + parameter-validation: + template: templates/app.yaml + parameters: + # Password with confirmation + AdminPassword: $[taskcat_genpass_12S] + ConfirmPassword: $[taskcat_getval_AdminPassword] + + # Consistent naming + ProjectName: $[taskcat_project_name] + TestName: $[taskcat_test_name] +``` + +## Custom Authentication + +```yaml +project: + name: multi-account-test + auth: + us-east-1: production-profile + us-west-2: staging-profile + eu-west-1: development-profile + default: default-profile +``` diff --git a/docs/examples/basic.md b/docs/examples/basic.md new file mode 100644 index 000000000..d6b8771f2 --- /dev/null +++ b/docs/examples/basic.md @@ -0,0 +1,73 @@ +# Basic Usage Examples + +This page provides simple, practical examples to help you get started with taskcat. + +## Simple S3 Bucket Test + +```yaml +# .taskcat.yml +project: + name: simple-s3-test + regions: + - us-east-1 + - us-west-2 + +tests: + s3-bucket: + template: templates/s3-bucket.yaml + parameters: + BucketName: $[taskcat_autobucket] +``` + +```yaml +# templates/s3-bucket.yaml +AWSTemplateFormatVersion: '2010-09-09' +Description: Simple S3 bucket + +Parameters: + BucketName: + Type: String + Description: Name of the S3 bucket + +Resources: + TestBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Ref BucketName + +Outputs: + BucketName: + Value: !Ref TestBucket + Description: Name of the created bucket +``` + +## Multi-AZ VPC Test + +```yaml +# .taskcat.yml +project: + name: vpc-test + regions: + - us-east-1 + - eu-west-1 + +tests: + vpc-multi-az: + template: templates/vpc.yaml + parameters: + AvailabilityZones: $[taskcat_genaz_2] + VpcCidr: 10.0.0.0/16 +``` + +## Running the Tests + +```bash +# Run all tests +taskcat test run + +# Run specific test +taskcat test run --test-names s3-bucket + +# Run with custom output directory +taskcat test run --output-directory ./my-results +``` diff --git a/docs/examples/index.md b/docs/examples/index.md new file mode 100644 index 000000000..90fcdbb8a --- /dev/null +++ b/docs/examples/index.md @@ -0,0 +1,116 @@ +# Examples + +Explore real-world taskcat configurations and learn from practical implementations. These examples demonstrate best practices, advanced features, and common use cases. + +## Quick Reference + +
Complex multi-tier applications and enterprise-grade configurations.
+ Explore Advanced +Multiple installation methods including pip, Docker, and from source.
+ Install taskcat +Run your first test in under 5 minutes with our step-by-step guide.
+ Quick Start +
+ Test your AWS CloudFormation templates across multiple regions with confidence. taskcat automates the deployment and validation of your infrastructure as code, ensuring your templates work reliably everywhere.
+ +Deploy and test your CloudFormation templates across multiple AWS regions simultaneously to ensure global compatibility and resilience.
+Comprehensive automated testing with detailed pass/fail reporting, stack validation, and resource verification.
+Runtime-evaluated parameters that pull values from your AWS environment, generate random data, and provide context-aware configurations.
+Generate detailed HTML reports with deployment status, logs, and visual dashboards to track your testing results.
+Seamlessly integrate with your continuous integration pipelines using GitHub Actions, Jenkins, or AWS CodePipeline.
+Comprehensive guides, tutorials, and API reference to help you get the most out of taskcat.
+ Browse Docs +Join our community discussions, ask questions, and share your taskcat experiences.
+ Join Community +Report bugs, request features, or contribute to the taskcat project on GitHub.
+ Report Issue +taskcat - Making CloudFormation testing simple, reliable, and scalable.
+Built with ❤️ by the AWS Solutions Architecture Team
+