Manic tools for manipulating sets of tagged resources in AWS.
Project description
Tagmania
Manic tools for manipulating sets of tagged resources in AWS.
Pipeline Artifacts
Reports are published to GitHub Pages on every release to
main.
| Report | Link |
|---|---|
| API Documentation | svange.github.io/tagmania |
| Test Report | tests/test-report.html |
| Coverage Report | coverage/ |
| Security Scan | security/security-reports.html |
| License Compliance | compliance/license-report.html |
| PyPI | pypi.org/project/tagmania |
Per-run downloadable artifacts (bandit-report.json, pip-audit-report.json, coverage.xml, test-report.html, license-report.json, built dist/ on release) are available under the Actions tab > select a run > scroll to "Artifacts".
What This Does
Tagmania is a command-line toolkit for managing groups of AWS EC2 instances that share a Cluster tag. You point it at a cluster name and it can start, stop, snapshot, or restore every instance in that cluster as a single unit. It's useful if you run dev/test environments on EC2 and want a simple way to pause them overnight, back them up before risky changes, or roll an entire cluster back to a known-good state.
It operates only on resources it's been told to manage (via a SNAPSHOT_MANAGER automation tag), so it won't accidentally touch unrelated resources in your account.
Getting Started
This project uses AI-assisted development. You do not need to memorize git commands or CI configuration -- your AI agent handles that.
Prerequisites
- Python 3.12 or higher (
python --version) - AWS CLI profile configured via
aws configureor~/.aws/credentials - EC2 instances tagged with a
Clustertag identifying their membership - IAM permissions -- see Minimum IAM Policy below
First-time setup
pip install tagmania
# or, with uv
uv tool install tagmania
For production, pin to an exact version:
pip install tagmania==2.6.1
Running locally
cluster-start my-cluster # boot all instances in my-cluster
cluster-stop my-cluster # stop all instances in my-cluster
cluster-snap --backup my-cluster # snapshot every attached EBS volume
cluster-snap --restore my-cluster # restore volumes from most recent snapshot
cluster-snap --list my-cluster # list snapshots for the cluster
All commands accept --profile <aws-profile> for credential selection. See Available Commands and Advanced Features below for more. Additional end-to-end walkthroughs live in EXAMPLES.md.
Minimum IAM Policy
The AWS identity running Tagmania needs the following permissions. Replace my-cluster with your actual Cluster tag value (or use a wildcard list if you manage multiple clusters).
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EC2Read",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeSnapshots",
"ec2:DescribeVolumes",
"ec2:DescribeImages",
"ec2:DescribeAvailabilityZones"
],
"Resource": "*"
},
{
"Sid": "InstanceStartStop",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*",
"Condition": {
"StringEquals": { "ec2:ResourceTag/Cluster": ["my-cluster"] }
}
},
{
"Sid": "VolumeLifecycleTagged",
"Effect": "Allow",
"Action": [
"ec2:DeleteVolume",
"ec2:AttachVolume",
"ec2:DetachVolume",
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "*",
"Condition": {
"StringEquals": { "ec2:ResourceTag/Cluster": ["my-cluster"] }
}
},
{
"Sid": "VolumeCreate",
"Effect": "Allow",
"Action": ["ec2:CreateVolume"],
"Resource": "*"
},
{
"Sid": "SnapshotLifecycle",
"Effect": "Allow",
"Action": [
"ec2:CreateSnapshot",
"ec2:DeleteSnapshot",
"ec2:CreateTags"
],
"Resource": "*"
}
]
}
The tagged conditions restrict the blast radius of start/stop and volume-modifying calls to instances that carry the matching Cluster tag. CreateVolume and snapshot create/delete are not tag-conditioned because AWS doesn't support that tag condition during resource creation.
The template.yaml in this repo uses the same policy shape for integration-test infrastructure.
How to Contribute
Contributions are made through AI agents (Claude Code, Copilot, etc.). You describe what you want changed in plain language; the agent handles branching, coding, testing, and submitting a pull request.
- Open Claude Code (or your AI agent) in this repo.
- Describe the change you want -- a bug fix, a new feature, a doc update.
- The agent will:
- Create a feature branch
- Make the changes
- Run pre-commit checks and tests
- Open a pull request
- Review the PR when the agent is done. CI runs automatically.
- Merge once CI is green.
If you need to work manually, see the full contributor guide.
Architecture
Tagmania is a thin layer on top of boto3. Every CLI entry point instantiates a ClusterSet, which owns an EC2 resource + client and exposes tag-scoped operations on instances, volumes, and snapshots.
flowchart LR
CLI["CLI entry points<br/>cluster-start / cluster-stop / cluster-snap"]
CS["ClusterSet<br/>(src/tagmania/iac_tools/clusterset.py)"]
subgraph boto3[boto3]
EC2R["EC2 resource"]
EC2C["EC2 client"]
end
TS["TagSet<br/>[{Key, Value}, ...]"]
FS["FilterSet<br/>[{Name, Values}, ...]"]
CLI --> CS
CS --> EC2R
CS --> EC2C
CS --> TS
CS --> FS
- ClusterSet is the only class that issues AWS API calls. It enforces a
_MAX_ITEMS = 150safety cap and only touches resources tagged with itsAUTOMATION_KEY = "SNAPSHOT_MANAGER". - TagSet and FilterSet are tiny wrappers around the two shapes of list-of-dicts that AWS uses (
[{Key, Value}]for tags,[{Name, Values}]for filters). - Snapshot / volume lifecycles run sequentially inside
ClusterSet.create_snapshotsandcreate_volumes. Targeted variants (*_targeted) filter by regex against the instanceNametag for partial cluster operations.
AWS Cost Warning
⚠️ Important: This tool operates on AWS infrastructure and can incur costs:
- EBS snapshot storage charges apply for all created snapshots
- Data transfer costs may apply when creating/restoring snapshots
- Test infrastructure in
template.yamlwill create billable EC2 instances - Always clean up test resources after use to avoid ongoing charges
For testing, consider using AWS Free Tier eligible instance types and remember to delete snapshots when no longer needed.
Available Commands
cluster-start- Start all instances in a clustercluster-stop- Stop all instances in a clustercluster-snap- Create, restore, delete, and list snapshots
Quick Start
Starting and Stopping Clusters
# Start all instances in a cluster
cluster-start production-cluster
# Stop all instances in a cluster
cluster-stop production-cluster
# Use specific AWS profile
cluster-start --profile myprofile production-cluster
Creating Snapshots
# Create a snapshot backup of entire cluster
cluster-snap --backup production-cluster
# Create a named snapshot
cluster-snap --backup --name daily-backup production-cluster
Restoring from Snapshots
# Restore entire cluster from default snapshot
cluster-snap --restore production-cluster
# Restore from named snapshot
cluster-snap --restore --name daily-backup production-cluster
Advanced Features
Targeted Restore
Restore specific instances within a cluster using regex pattern matching against instance "Name" tags:
# Restore only web servers
cluster-snap --restore --target ".*-web-.*" production-cluster
# Restore specific instance
cluster-snap --restore --target "server-01" --name daily-backup production-cluster
Common Targeting Patterns:
".*-web-.*"- All instances with "web" in the name"server-[0-9]+"- Instances named server-1, server-2, etc."prod-api-.*"- All production API servers"backup-db"- Specific instance named "backup-db"
Snapshot Management
# List all snapshots for a cluster
cluster-snap --list production-cluster
# List specific labeled snapshots
cluster-snap --list --name daily-backup production-cluster
# Delete specific snapshot set
cluster-snap --delete --name daily-backup production-cluster
# Delete all snapshots for cluster
cluster-snap --delete production-cluster
How It Works
Backup Process
- Stops all cluster instances
- Creates EBS snapshots of all attached volumes
- Tags snapshots with cluster and label information
- Instances remain stopped after backup (use
cluster-startto restart)
Restore Process
- Stops all cluster instances (or targeted instances)
- Detaches and deletes current EBS volumes
- Creates new volumes from snapshots
- Attaches new volumes to instances
- Instances remain stopped after restore (use
cluster-startto restart)
Targeted Restore Process
- Validates regex pattern
- Filters instances by Name tag matching pattern
- Displays matched instances for confirmation
- Performs restore only on matched instances
- Other instances in cluster remain unchanged
Safety Features
- Confirmation Required: All destructive operations require "yes" confirmation
- Cluster Isolation: Operations only affect instances with matching "Cluster" tag
- Automation Tracking: Uses "SNAPSHOT_MANAGER" key to track managed resources
- Regex Validation: Targeted operations validate regex patterns before execution
- Item Limits: Maximum 150 items processed per operation for performance protection
Version Management and Stability
To ensure consistent and stable deployments, it is critical to pin Tagmania to specific versions rather than using floating version numbers.
Recommended Installation Methods
pip with version pinning:
pip install tagmania==2.6.1
Poetry (recommended for projects):
[tool.poetry.dependencies]
tagmania = "2.6.1"
Requirements.txt:
tagmania==2.6.1
Version Selection Strategy
Production Environments:
- Always use exact version pinning (e.g.,
==2.6.1) - Test new versions in development/staging before production deployment
- Document version upgrade procedures and rollback plans
- Monitor release notes for breaking changes
Development Environments:
- Use compatible version ranges for feature development (e.g.,
~=2.6.1) - Pin to exact versions when reproducing production issues
- Update regularly to stay current with security patches
Checking Installed Version
pip show tagmania
Or within Python:
import tagmania
print(tagmania.__version__)
Upgrade Planning
# Create backup of current environment
pip freeze > requirements-backup.txt
# Upgrade to specific version
pip install tagmania==2.6.1
# Test functionality
cluster-snap --list test-cluster
# If issues occur, rollback
pip install tagmania==2.5.0
Troubleshooting
No instances found: TheClustertag doesn't match any running or stopped instance. Tags are case-sensitive; verify withaws ec2 describe-instances --filters Name=tag:Cluster,Values=my-cluster.UnauthorizedOperation/AccessDenied: The AWS identity is missing one of the required permissions. See the Minimum IAM Policy -- most permission errors come from the conditionedec2:StartInstances/ec2:StopInstances/ volume actions when the caller'sClustertag restriction doesn't include the cluster you're operating on.Invalid regex pattern: Targeted restore (--target) validates its regex before running. Test patterns with a quick--listorpython -c "import re; re.compile('...')"before passing to--restore.- Snapshot completes but restore hangs: Large EBS volumes (>1TB) can exceed the default 60-minute waiter timeout. The waiter polls every 5s for up to 720 attempts; watch the log for the
create_snapshots took Xstiming line to gauge duration. InvalidSnapshot.NotFound: The snapshot label doesn't exist for this cluster. List labels withcluster-snap --list my-cluster.- Python compatibility: Requires Python 3.12 or higher (see
pyproject.toml).
Support
License
This project is licensed under the terms specified in the LICENSE file.
Sponsor
If you find this project useful, please consider sponsoring its development.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tagmania-2.7.1.tar.gz.
File metadata
- Download URL: tagmania-2.7.1.tar.gz
- Upload date:
- Size: 25.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11b44710a30bf11b6a19623985c444475645e4fb902295995881d0017d2faeb0
|
|
| MD5 |
9e9901650dd99c18e16bc537054dca2a
|
|
| BLAKE2b-256 |
ef316c76293b6b3eda680baa0e7a039c84f50d7898020a4384018341e1cbab3a
|
Provenance
The following attestation bundles were made for tagmania-2.7.1.tar.gz:
Publisher:
pipeline.yaml on svange/tagmania
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tagmania-2.7.1.tar.gz -
Subject digest:
11b44710a30bf11b6a19623985c444475645e4fb902295995881d0017d2faeb0 - Sigstore transparency entry: 1363886070
- Sigstore integration time:
-
Permalink:
svange/tagmania@378ff61e0f1eace8d567c7710f39d5e39212da9d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/svange
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pipeline.yaml@378ff61e0f1eace8d567c7710f39d5e39212da9d -
Trigger Event:
push
-
Statement type:
File details
Details for the file tagmania-2.7.1-py3-none-any.whl.
File metadata
- Download URL: tagmania-2.7.1-py3-none-any.whl
- Upload date:
- Size: 31.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77f2d62257fce1d6b23cefa7e3ba2606580915ad85c52f14e85d312af1116b24
|
|
| MD5 |
16007b9f461dbaa3e893802f2f6d3176
|
|
| BLAKE2b-256 |
c26ad4b1b2da6641210ef68220d81a7b341218dfcee4cca92e1419c863fcadb9
|
Provenance
The following attestation bundles were made for tagmania-2.7.1-py3-none-any.whl:
Publisher:
pipeline.yaml on svange/tagmania
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tagmania-2.7.1-py3-none-any.whl -
Subject digest:
77f2d62257fce1d6b23cefa7e3ba2606580915ad85c52f14e85d312af1116b24 - Sigstore transparency entry: 1363886075
- Sigstore integration time:
-
Permalink:
svange/tagmania@378ff61e0f1eace8d567c7710f39d5e39212da9d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/svange
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pipeline.yaml@378ff61e0f1eace8d567c7710f39d5e39212da9d -
Trigger Event:
push
-
Statement type: