Skip to content

Commit 76790dc

Browse files
committed
Initial commit
0 parents  commit 76790dc

File tree

8 files changed

+467
-0
lines changed

8 files changed

+467
-0
lines changed

.gitignore

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
dist/
11+
build/
12+
*.egg-info/
13+
*.egg
14+
15+
# Virtual environments
16+
venv/
17+
env/
18+
.env/
19+
.venv/
20+
ENV/
21+
22+
# IDE specific files
23+
.idea/
24+
.vscode/
25+
*.swp
26+
*.swo
27+
.DS_Store
28+
29+
# Unit test / coverage reports
30+
htmlcov/
31+
.tox/
32+
.nox/
33+
.coverage
34+
.coverage.*
35+
.cache
36+
nosetests.xml
37+
coverage.xml
38+
*.cover
39+
*.py,cover
40+
.hypothesis/
41+
.pytest_cache/
42+
43+
# Jupyter Notebook
44+
.ipynb_checkpoints
45+
46+
# pyenv
47+
.python-version
48+
49+
# Logs
50+
*.log
51+
52+
# Local development settings
53+
.env
54+
.env.local
55+
.env.*.local
56+
57+
# Database files
58+
*.db
59+
*.sqlite3
60+
*.sqlite
61+
62+
# Documentation
63+
docs/_build/
64+
65+
# mypy
66+
.mypy_cache/
67+
.dmypy.json
68+
dmypy.json
69+
70+
# Rope project settings
71+
.ropeproject
72+
73+
# mkdocs documentation
74+
/site
75+
76+
# pipenv
77+
Pipfile.lock
78+
79+
# poetry
80+
poetry.lock

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# TFSumPy - Terraform Plan Analyzer
2+
3+
TFSumPy is a Python-based tool that analyzes Terraform plan files to provide a clear summary of infrastructure changes and identify potential risks. It helps DevOps teams review infrastructure changes more effectively by:
4+
5+
- Summarizing resource changes (create, update, delete)
6+
- Identifying high and medium risk changes
7+
- Automatically redacting sensitive information
8+
- Providing detailed resource-level reporting
9+
10+
## Features
11+
12+
- 🔍 Analyzes Terraform plan JSON output
13+
- ⚠️ Identifies high-risk changes (deletions of critical resources, security group modifications)
14+
- 🔒 Automatically redacts sensitive information (credentials, IPs, resource names)
15+
- 📊 Provides clear summary statistics
16+
- 🛡️ Supports both pre and post Terraform 0.12 plan formats
17+
18+
## Installation
19+
20+
Currently, TFSumPy can only be installed from source:
21+
22+
```bash
23+
git clone https://github.com/notry-cloud/tfsumpy.git
24+
cd tfsumpy
25+
pip install .
26+
```
27+
28+
## Usage
29+
30+
```bash
31+
terraform plan -out=tfplan
32+
terraform show -json tfplan > plan.json
33+
````
34+
35+
```bash
36+
tfsumpy -i plan.json
37+
38+
Infrastructure Change Analysis
39+
==============================
40+
Total Changes: 5
41+
Create: 2
42+
Update: 2
43+
Delete: 1
44+
45+
Risk Assessment:
46+
47+
High Risks:
48+
- High risk: Security-related configuration change
49+
Medium Risks:
50+
- Medium risk: Version change could cause compatibility issues
51+
Resource Details:
52+
- CREATE aws_s3_bucket: project-storage-[REDACTED]
53+
- UPDATE aws_security_group: app-sg-[REDACTED]
54+
- UPDATE aws_ecs_service: api-service
55+
- DELETE aws_iam_role: legacy-role
56+
- CREATE aws_lambda_function: processor-function
57+
58+
```
59+
60+
## Requirements
61+
62+
- Python 3.7 or higher
63+
- Terraform 0.12 or higher (for plan generation)
64+
65+
## Contributing
66+
67+
Contributions are welcome! Please feel free to submit a Pull Request.
68+
69+
## License
70+
71+
This project is licensed under the MIT License - see the LICENSE file for details.

samples/sample1.json

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"format_version": "1.1",
3+
"terraform_version": "1.5.0",
4+
"planned_values": {
5+
"root_module": {
6+
"resources": [
7+
{
8+
"address": "aws_s3_bucket.example",
9+
"mode": "managed",
10+
"type": "aws_s3_bucket",
11+
"name": "example",
12+
"provider_name": "registry.terraform.io/hashicorp/aws",
13+
"schema_version": 0,
14+
"values": {
15+
"bucket": "my-test-bucket",
16+
"force_destroy": false,
17+
"tags": {
18+
"Environment": "Dev",
19+
"Name": "My bucket"
20+
}
21+
}
22+
},
23+
{
24+
"address": "aws_instance.web_server",
25+
"mode": "managed",
26+
"type": "aws_instance",
27+
"name": "web_server",
28+
"provider_name": "registry.terraform.io/hashicorp/aws",
29+
"schema_version": 1,
30+
"values": {
31+
"ami": "ami-0c55b159cbfafe1f0",
32+
"instance_type": "t2.micro",
33+
"tags": {
34+
"Name": "WebServer"
35+
}
36+
}
37+
}
38+
]
39+
}
40+
},
41+
"resource_changes": [
42+
{
43+
"address": "aws_s3_bucket.example",
44+
"mode": "managed",
45+
"type": "aws_s3_bucket",
46+
"name": "example",
47+
"provider_name": "registry.terraform.io/hashicorp/aws",
48+
"change": {
49+
"actions": [
50+
"create"
51+
],
52+
"before": null,
53+
"after": {
54+
"bucket": "my-test-bucket",
55+
"force_destroy": false,
56+
"tags": {
57+
"Environment": "Dev",
58+
"Name": "My bucket"
59+
}
60+
}
61+
}
62+
},
63+
{
64+
"address": "aws_instance.web_server",
65+
"mode": "managed",
66+
"type": "aws_instance",
67+
"name": "web_server",
68+
"provider_name": "registry.terraform.io/hashicorp/aws",
69+
"change": {
70+
"actions": [
71+
"update"
72+
],
73+
"before": {
74+
"ami": "ami-0c55b159cbfafe1f0",
75+
"instance_type": "t2.nano",
76+
"tags": {
77+
"Name": "WebServer"
78+
}
79+
},
80+
"after": {
81+
"ami": "ami-0c55b159cbfafe1f0",
82+
"instance_type": "t2.micro",
83+
"tags": {
84+
"Name": "WebServer"
85+
}
86+
}
87+
}
88+
},
89+
{
90+
"address": "aws_security_group.obsolete",
91+
"mode": "managed",
92+
"type": "aws_security_group",
93+
"name": "obsolete",
94+
"provider_name": "registry.terraform.io/hashicorp/aws",
95+
"change": {
96+
"actions": [
97+
"delete"
98+
],
99+
"before": {
100+
"description": "Obsolete security group",
101+
"name": "obsolete-sg",
102+
"tags": {
103+
"Name": "ObsoleteSG"
104+
}
105+
},
106+
"after": null
107+
}
108+
}
109+
],
110+
"configuration": {
111+
"provider_config": {
112+
"aws": {
113+
"name": "aws",
114+
"version_constraint": "~> 4.0"
115+
}
116+
}
117+
}
118+
}

setup.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from setuptools import setup, find_packages
2+
3+
setup(
4+
name='tfsumpy',
5+
version='0.0.1-alpha',
6+
description='A Python tool for Terraform state summary and analysis',
7+
long_description=open('README.md').read(),
8+
long_description_content_type='text/markdown',
9+
author='Notry',
10+
author_email='[email protected]',
11+
url='https://github.com/notry-cloud/tfsumpy',
12+
packages=find_packages(),
13+
entry_points={
14+
'console_scripts': [
15+
'tfsumpy=tfsumpy.__main__:main'
16+
]
17+
},
18+
python_requires='>=3.10',
19+
install_requires=[
20+
# Add your dependencies here
21+
],
22+
classifiers=[
23+
'Development Status :: 3 - Alpha',
24+
'Intended Audience :: Developers',
25+
'License :: OSI Approved :: MIT License',
26+
'Programming Language :: Python :: 3.10',
27+
'Programming Language :: Python :: 3.11',
28+
'Programming Language :: Python :: 3.12',
29+
'Topic :: Software Development :: Build Tools',
30+
'Topic :: System :: Systems Administration',
31+
],
32+
keywords='terraform, infrastructure, cloud, DevOps',
33+
)

tfsumpy/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from .plan_analyzer import LocalPlanAnalyzer
2+
from .resource import ResourceChange
3+
4+
__version__ = '0.1.0'
5+
6+
__all__ = ['LocalPlanAnalyzer', 'ResourceChange']

tfsumpy/__main__.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import logging
2+
import argparse
3+
from .plan_analyzer import LocalPlanAnalyzer
4+
5+
# Configure logging
6+
logging.basicConfig(level=logging.INFO)
7+
logger = logging.getLogger(__name__)
8+
9+
def main():
10+
# Add argument parser
11+
parser = argparse.ArgumentParser(description='Analyze Terraform plan file')
12+
parser.add_argument('-i', '--input',
13+
required=True,
14+
help='Path to the plan file to analyze')
15+
16+
args = parser.parse_args()
17+
18+
analyzer = LocalPlanAnalyzer()
19+
try:
20+
report = analyzer.generate_report(args.input)
21+
analyzer.print_report(report)
22+
except FileNotFoundError:
23+
logger.error("Plan file not found")
24+
except Exception as e:
25+
logger.error(f"Processing failed: {str(e)}")
26+
27+
if __name__ == "__main__":
28+
main()

0 commit comments

Comments
 (0)