tf-starter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +421 -0
- package/bin/tf-starter.js +88 -0
- package/package.json +43 -0
- package/scripts/postinstall.js +105 -0
- package/setup.py +32 -0
- package/tf_starter/__init__.py +3 -0
- package/tf_starter/__main__.py +6 -0
- package/tf_starter/cli.py +379 -0
- package/tf_starter/generator.py +171 -0
- package/tf_starter/template_engine.py +80 -0
- package/tf_starter/templates/aws/environments/backend.tf.j2 +16 -0
- package/tf_starter/templates/aws/environments/main.tf.j2 +85 -0
- package/tf_starter/templates/aws/environments/terraform.tfvars.j2 +52 -0
- package/tf_starter/templates/aws/environments/variables.tf.j2 +127 -0
- package/tf_starter/templates/aws/github/terraform.yml.j2 +133 -0
- package/tf_starter/templates/aws/misc/Makefile.j2 +60 -0
- package/tf_starter/templates/aws/misc/README.md.j2 +445 -0
- package/tf_starter/templates/aws/misc/init.sh.j2 +110 -0
- package/tf_starter/templates/aws/misc/pre-commit-config.yaml.j2 +34 -0
- package/tf_starter/templates/aws/modules/apigateway/main.tf.j2 +224 -0
- package/tf_starter/templates/aws/modules/apigateway/outputs.tf.j2 +28 -0
- package/tf_starter/templates/aws/modules/apigateway/variables.tf.j2 +69 -0
- package/tf_starter/templates/aws/modules/compute/main.tf.j2 +245 -0
- package/tf_starter/templates/aws/modules/compute/outputs.tf.j2 +38 -0
- package/tf_starter/templates/aws/modules/compute/variables.tf.j2 +68 -0
- package/tf_starter/templates/aws/modules/database/main.tf.j2 +122 -0
- package/tf_starter/templates/aws/modules/database/outputs.tf.j2 +33 -0
- package/tf_starter/templates/aws/modules/database/variables.tf.j2 +63 -0
- package/tf_starter/templates/aws/modules/kubernetes/main.tf.j2 +167 -0
- package/tf_starter/templates/aws/modules/kubernetes/outputs.tf.j2 +33 -0
- package/tf_starter/templates/aws/modules/kubernetes/variables.tf.j2 +64 -0
- package/tf_starter/templates/aws/modules/lambda/main.tf.j2 +215 -0
- package/tf_starter/templates/aws/modules/lambda/outputs.tf.j2 +38 -0
- package/tf_starter/templates/aws/modules/lambda/variables.tf.j2 +88 -0
- package/tf_starter/templates/aws/modules/messaging/main.tf.j2 +85 -0
- package/tf_starter/templates/aws/modules/messaging/outputs.tf.j2 +28 -0
- package/tf_starter/templates/aws/modules/messaging/variables.tf.j2 +41 -0
- package/tf_starter/templates/aws/modules/monitoring/main.tf.j2 +155 -0
- package/tf_starter/templates/aws/modules/monitoring/outputs.tf.j2 +23 -0
- package/tf_starter/templates/aws/modules/monitoring/variables.tf.j2 +39 -0
- package/tf_starter/templates/aws/modules/network/main.tf.j2 +147 -0
- package/tf_starter/templates/aws/modules/network/outputs.tf.j2 +33 -0
- package/tf_starter/templates/aws/modules/network/variables.tf.j2 +52 -0
- package/tf_starter/templates/aws/modules/storage/main.tf.j2 +88 -0
- package/tf_starter/templates/aws/modules/storage/outputs.tf.j2 +23 -0
- package/tf_starter/templates/aws/modules/storage/variables.tf.j2 +25 -0
- package/tf_starter/templates/aws/root/backend.tf.j2 +19 -0
- package/tf_starter/templates/aws/root/main.tf.j2 +219 -0
- package/tf_starter/templates/aws/root/outputs.tf.j2 +134 -0
- package/tf_starter/templates/aws/root/providers.tf.j2 +24 -0
- package/tf_starter/templates/aws/root/variables.tf.j2 +300 -0
- package/tf_starter/templates/aws/root/versions.tf.j2 +26 -0
- package/tf_starter/templates/azure/environments/backend.tf.j2 +11 -0
- package/tf_starter/templates/azure/environments/main.tf.j2 +57 -0
- package/tf_starter/templates/azure/environments/terraform.tfvars.j2 +14 -0
- package/tf_starter/templates/azure/environments/variables.tf.j2 +30 -0
- package/tf_starter/templates/azure/github/terraform.yml.j2 +133 -0
- package/tf_starter/templates/azure/misc/Makefile.j2 +60 -0
- package/tf_starter/templates/azure/misc/README.md.j2 +426 -0
- package/tf_starter/templates/azure/misc/init.sh.j2 +110 -0
- package/tf_starter/templates/azure/misc/pre-commit-config.yaml.j2 +34 -0
- package/tf_starter/templates/azure/modules/apigateway/main.tf.j2 +125 -0
- package/tf_starter/templates/azure/modules/apigateway/outputs.tf.j2 +18 -0
- package/tf_starter/templates/azure/modules/apigateway/variables.tf.j2 +54 -0
- package/tf_starter/templates/azure/modules/compute/main.tf.j2 +114 -0
- package/tf_starter/templates/azure/modules/compute/outputs.tf.j2 +9 -0
- package/tf_starter/templates/azure/modules/compute/variables.tf.j2 +23 -0
- package/tf_starter/templates/azure/modules/database/main.tf.j2 +56 -0
- package/tf_starter/templates/azure/modules/database/outputs.tf.j2 +13 -0
- package/tf_starter/templates/azure/modules/database/variables.tf.j2 +38 -0
- package/tf_starter/templates/azure/modules/kubernetes/main.tf.j2 +50 -0
- package/tf_starter/templates/azure/modules/kubernetes/outputs.tf.j2 +19 -0
- package/tf_starter/templates/azure/modules/kubernetes/variables.tf.j2 +37 -0
- package/tf_starter/templates/azure/modules/lambda/main.tf.j2 +98 -0
- package/tf_starter/templates/azure/modules/lambda/outputs.tf.j2 +23 -0
- package/tf_starter/templates/azure/modules/lambda/variables.tf.j2 +53 -0
- package/tf_starter/templates/azure/modules/messaging/main.tf.j2 +29 -0
- package/tf_starter/templates/azure/modules/messaging/outputs.tf.j2 +14 -0
- package/tf_starter/templates/azure/modules/messaging/variables.tf.j2 +11 -0
- package/tf_starter/templates/azure/modules/monitoring/main.tf.j2 +31 -0
- package/tf_starter/templates/azure/modules/monitoring/outputs.tf.j2 +9 -0
- package/tf_starter/templates/azure/modules/monitoring/variables.tf.j2 +16 -0
- package/tf_starter/templates/azure/modules/network/main.tf.j2 +89 -0
- package/tf_starter/templates/azure/modules/network/outputs.tf.j2 +25 -0
- package/tf_starter/templates/azure/modules/network/variables.tf.j2 +25 -0
- package/tf_starter/templates/azure/modules/storage/main.tf.j2 +41 -0
- package/tf_starter/templates/azure/modules/storage/outputs.tf.j2 +17 -0
- package/tf_starter/templates/azure/modules/storage/variables.tf.j2 +16 -0
- package/tf_starter/templates/azure/root/backend.tf.j2 +11 -0
- package/tf_starter/templates/azure/root/main.tf.j2 +181 -0
- package/tf_starter/templates/azure/root/outputs.tf.j2 +45 -0
- package/tf_starter/templates/azure/root/providers.tf.j2 +18 -0
- package/tf_starter/templates/azure/root/variables.tf.j2 +114 -0
- package/tf_starter/templates/azure/root/versions.tf.j2 +16 -0
- package/tf_starter/templates/gcp/environments/backend.tf.j2 +9 -0
- package/tf_starter/templates/gcp/environments/main.tf.j2 +58 -0
- package/tf_starter/templates/gcp/environments/terraform.tfvars.j2 +12 -0
- package/tf_starter/templates/gcp/environments/variables.tf.j2 +21 -0
- package/tf_starter/templates/gcp/github/terraform.yml.j2 +133 -0
- package/tf_starter/templates/gcp/misc/Makefile.j2 +60 -0
- package/tf_starter/templates/gcp/misc/README.md.j2 +426 -0
- package/tf_starter/templates/gcp/misc/init.sh.j2 +110 -0
- package/tf_starter/templates/gcp/misc/pre-commit-config.yaml.j2 +34 -0
- package/tf_starter/templates/gcp/modules/apigateway/main.tf.j2 +67 -0
- package/tf_starter/templates/gcp/modules/apigateway/outputs.tf.j2 +18 -0
- package/tf_starter/templates/gcp/modules/apigateway/variables.tf.j2 +34 -0
- package/tf_starter/templates/gcp/modules/compute/main.tf.j2 +138 -0
- package/tf_starter/templates/gcp/modules/compute/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/compute/variables.tf.j2 +33 -0
- package/tf_starter/templates/gcp/modules/database/main.tf.j2 +62 -0
- package/tf_starter/templates/gcp/modules/database/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/database/variables.tf.j2 +29 -0
- package/tf_starter/templates/gcp/modules/kubernetes/main.tf.j2 +75 -0
- package/tf_starter/templates/gcp/modules/kubernetes/outputs.tf.j2 +14 -0
- package/tf_starter/templates/gcp/modules/kubernetes/variables.tf.j2 +38 -0
- package/tf_starter/templates/gcp/modules/lambda/main.tf.j2 +122 -0
- package/tf_starter/templates/gcp/modules/lambda/outputs.tf.j2 +18 -0
- package/tf_starter/templates/gcp/modules/lambda/variables.tf.j2 +77 -0
- package/tf_starter/templates/gcp/modules/messaging/main.tf.j2 +44 -0
- package/tf_starter/templates/gcp/modules/messaging/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/messaging/variables.tf.j2 +20 -0
- package/tf_starter/templates/gcp/modules/monitoring/main.tf.j2 +44 -0
- package/tf_starter/templates/gcp/modules/monitoring/outputs.tf.j2 +9 -0
- package/tf_starter/templates/gcp/modules/monitoring/variables.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/network/main.tf.j2 +103 -0
- package/tf_starter/templates/gcp/modules/network/outputs.tf.j2 +21 -0
- package/tf_starter/templates/gcp/modules/network/variables.tf.j2 +22 -0
- package/tf_starter/templates/gcp/modules/storage/main.tf.j2 +47 -0
- package/tf_starter/templates/gcp/modules/storage/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/storage/variables.tf.j2 +16 -0
- package/tf_starter/templates/gcp/root/backend.tf.j2 +12 -0
- package/tf_starter/templates/gcp/root/main.tf.j2 +210 -0
- package/tf_starter/templates/gcp/root/outputs.tf.j2 +61 -0
- package/tf_starter/templates/gcp/root/providers.tf.j2 +18 -0
- package/tf_starter/templates/gcp/root/variables.tf.j2 +140 -0
- package/tf_starter/templates/gcp/root/versions.tf.j2 +23 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
# {{ project_name }}
|
|
2
|
+
|
|
3
|
+
> Infrastructure-as-Code project generated by **tf-starter** for **{{ provider | upper }}**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
{% if provider == "aws" %}
|
|
10
|
+
```
|
|
11
|
+
{% if "kubernetes" in services %}
|
|
12
|
+
Internet
|
|
13
|
+
|
|
|
14
|
+
+---------------+
|
|
15
|
+
| Route 53 |
|
|
16
|
+
+---------------+
|
|
17
|
+
|
|
|
18
|
+
+---------------+
|
|
19
|
+
{% if "compute" in services %}
|
|
20
|
+
| ALB |
|
|
21
|
+
+---------------+
|
|
22
|
+
|
|
|
23
|
+
+------------+------------+
|
|
24
|
+
| |
|
|
25
|
+
+-------+--------+ +----------+-------+
|
|
26
|
+
| EKS Cluster | | Auto Scaling EC2 |
|
|
27
|
+
+-------+--------+ +----------+-------+
|
|
28
|
+
{% else %}
|
|
29
|
+
| ALB |
|
|
30
|
+
+---------------+
|
|
31
|
+
|
|
|
32
|
+
+---------------+
|
|
33
|
+
| EKS Cluster |
|
|
34
|
+
+---------------+
|
|
35
|
+
{% endif %}
|
|
36
|
+
{% elif "compute" in services %}
|
|
37
|
+
Internet
|
|
38
|
+
|
|
|
39
|
+
+---------------+
|
|
40
|
+
| ALB |
|
|
41
|
+
+---------------+
|
|
42
|
+
|
|
|
43
|
+
+---------------+
|
|
44
|
+
| Auto Scaling |
|
|
45
|
+
| EC2 |
|
|
46
|
+
+---------------+
|
|
47
|
+
{% else %}
|
|
48
|
+
Internet
|
|
49
|
+
|
|
|
50
|
+
+---------------+
|
|
51
|
+
| VPC |
|
|
52
|
+
+---------------+
|
|
53
|
+
{% endif %}
|
|
54
|
+
{% if "database" in services %}
|
|
55
|
+
|
|
|
56
|
+
+---------------+
|
|
57
|
+
| RDS PostgreSQL|
|
|
58
|
+
| (Multi-AZ) |
|
|
59
|
+
+---------------+
|
|
60
|
+
{% endif %}
|
|
61
|
+
{% if "messaging" in services %}
|
|
62
|
+
|
|
|
63
|
+
+---------------+
|
|
64
|
+
| SQS Queue |
|
|
65
|
+
+---------------+
|
|
66
|
+
{% endif %}
|
|
67
|
+
{% if "storage" in services %}
|
|
68
|
+
|
|
|
69
|
+
+---------------+
|
|
70
|
+
| S3 Bucket |
|
|
71
|
+
+---------------+
|
|
72
|
+
{% endif %}
|
|
73
|
+
```
|
|
74
|
+
{% elif provider == "gcp" %}
|
|
75
|
+
```
|
|
76
|
+
{% if "kubernetes" in services %}
|
|
77
|
+
Internet
|
|
78
|
+
|
|
|
79
|
+
+------------------+
|
|
80
|
+
| Cloud Load Bal. |
|
|
81
|
+
+------------------+
|
|
82
|
+
|
|
|
83
|
+
+------------------+
|
|
84
|
+
| GKE Cluster |
|
|
85
|
+
+------------------+
|
|
86
|
+
{% elif "compute" in services %}
|
|
87
|
+
Internet
|
|
88
|
+
|
|
|
89
|
+
+------------------+
|
|
90
|
+
| Cloud Load Bal. |
|
|
91
|
+
+------------------+
|
|
92
|
+
|
|
|
93
|
+
+------------------+
|
|
94
|
+
| Managed Inst. |
|
|
95
|
+
| Group |
|
|
96
|
+
+------------------+
|
|
97
|
+
{% else %}
|
|
98
|
+
Internet
|
|
99
|
+
|
|
|
100
|
+
+------------------+
|
|
101
|
+
| VPC Network |
|
|
102
|
+
+------------------+
|
|
103
|
+
{% endif %}
|
|
104
|
+
{% if "database" in services %}
|
|
105
|
+
|
|
|
106
|
+
+------------------+
|
|
107
|
+
| Cloud SQL |
|
|
108
|
+
| PostgreSQL |
|
|
109
|
+
+------------------+
|
|
110
|
+
{% endif %}
|
|
111
|
+
{% if "messaging" in services %}
|
|
112
|
+
|
|
|
113
|
+
+------------------+
|
|
114
|
+
| Pub/Sub |
|
|
115
|
+
+------------------+
|
|
116
|
+
{% endif %}
|
|
117
|
+
{% if "storage" in services %}
|
|
118
|
+
|
|
|
119
|
+
+------------------+
|
|
120
|
+
| GCS Bucket |
|
|
121
|
+
+------------------+
|
|
122
|
+
{% endif %}
|
|
123
|
+
```
|
|
124
|
+
{% elif provider == "azure" %}
|
|
125
|
+
```
|
|
126
|
+
Internet
|
|
127
|
+
|
|
|
128
|
+
{% if "apigateway" in services %}
|
|
129
|
+
+------------------+
|
|
130
|
+
| API Management |
|
|
131
|
+
+------------------+
|
|
132
|
+
|
|
|
133
|
+
+------------------+
|
|
134
|
+
| Azure Functions |
|
|
135
|
+
+------------------+
|
|
136
|
+
{% elif "kubernetes" in services %}
|
|
137
|
+
+------------------+
|
|
138
|
+
| App Gateway |
|
|
139
|
+
+------------------+
|
|
140
|
+
|
|
|
141
|
+
+------------------+
|
|
142
|
+
| AKS Cluster |
|
|
143
|
+
+------------------+
|
|
144
|
+
{% elif "compute" in services %}
|
|
145
|
+
+------------------+
|
|
146
|
+
| App Gateway |
|
|
147
|
+
+------------------+
|
|
148
|
+
|
|
|
149
|
+
+------------------+
|
|
150
|
+
| VMSS |
|
|
151
|
+
+------------------+
|
|
152
|
+
{% elif "lambda" in services %}
|
|
153
|
+
+------------------+
|
|
154
|
+
| Azure Functions |
|
|
155
|
+
+------------------+
|
|
156
|
+
{% else %}
|
|
157
|
+
+------------------+
|
|
158
|
+
| VNet |
|
|
159
|
+
+------------------+
|
|
160
|
+
{% endif %}
|
|
161
|
+
{% if "database" in services %}
|
|
162
|
+
|
|
|
163
|
+
+------------------+
|
|
164
|
+
| Azure PostgreSQL |
|
|
165
|
+
| Flexible Server |
|
|
166
|
+
+------------------+
|
|
167
|
+
{% endif %}
|
|
168
|
+
{% if "messaging" in services %}
|
|
169
|
+
|
|
|
170
|
+
+------------------+
|
|
171
|
+
| Service Bus |
|
|
172
|
+
+------------------+
|
|
173
|
+
{% endif %}
|
|
174
|
+
{% if "storage" in services %}
|
|
175
|
+
|
|
|
176
|
+
+------------------+
|
|
177
|
+
| Storage Account |
|
|
178
|
+
+------------------+
|
|
179
|
+
{% endif %}
|
|
180
|
+
```
|
|
181
|
+
{% endif %}
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Project Overview
|
|
186
|
+
|
|
187
|
+
This project provisions cloud infrastructure on **{{ provider | upper }}** using Terraform.
|
|
188
|
+
It was generated using the `tf-starter` CLI tool and follows enterprise-grade
|
|
189
|
+
infrastructure-as-code best practices.
|
|
190
|
+
|
|
191
|
+
### Enabled Services
|
|
192
|
+
|
|
193
|
+
| Service | Status |
|
|
194
|
+
|---------|--------|
|
|
195
|
+
| Network | Enabled (always) |
|
|
196
|
+
{% for svc in services %}
|
|
197
|
+
{% if svc != "network" %}
|
|
198
|
+
| {{ svc | capitalize }} | Enabled |
|
|
199
|
+
{% endif %}
|
|
200
|
+
{% endfor %}
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Folder Structure
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
{{ project_name }}/
|
|
208
|
+
├── environments/ # Per-environment configurations
|
|
209
|
+
{% for env in environments %}
|
|
210
|
+
│ ├── {{ env }}/
|
|
211
|
+
│ │ ├── main.tf
|
|
212
|
+
│ │ ├── variables.tf
|
|
213
|
+
│ │ ├── terraform.tfvars
|
|
214
|
+
{% if enable_backend %}
|
|
215
|
+
│ │ └── backend.tf
|
|
216
|
+
{% endif %}
|
|
217
|
+
{% endfor %}
|
|
218
|
+
├── modules/ # Reusable Terraform modules
|
|
219
|
+
{% for svc in services %}
|
|
220
|
+
│ ├── {{ svc }}/
|
|
221
|
+
{% endfor %}
|
|
222
|
+
├── main.tf # Root module composition
|
|
223
|
+
├── providers.tf # Provider configuration
|
|
224
|
+
├── variables.tf # Input variables
|
|
225
|
+
├── outputs.tf # Output values
|
|
226
|
+
├── versions.tf # Terraform & provider versions
|
|
227
|
+
{% if enable_backend %}
|
|
228
|
+
├── backend.tf # Remote state backend
|
|
229
|
+
{% endif %}
|
|
230
|
+
├── Makefile # Automation targets
|
|
231
|
+
├── init.sh # Bootstrap script
|
|
232
|
+
└── README.md # This file
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Environments
|
|
238
|
+
|
|
239
|
+
| Environment | Description |
|
|
240
|
+
|-------------|-------------|
|
|
241
|
+
{% for env in environments %}
|
|
242
|
+
{% if env == "prod" %}
|
|
243
|
+
| **{{ env }}** | Production — HA enabled, deletion protection on, extended backups |
|
|
244
|
+
{% elif env == "staging" %}
|
|
245
|
+
| **{{ env }}** | Staging — mirrors production at reduced scale for pre-release testing |
|
|
246
|
+
{% elif env == "dev" %}
|
|
247
|
+
| **{{ env }}** | Development — minimal resources, fast iteration |
|
|
248
|
+
{% else %}
|
|
249
|
+
| **{{ env }}** | Custom environment |
|
|
250
|
+
{% endif %}
|
|
251
|
+
{% endfor %}
|
|
252
|
+
|
|
253
|
+
Each environment has its own `terraform.tfvars` file. Edit these to customize
|
|
254
|
+
resource sizing, networking CIDRs, and service-specific parameters.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
{% if enable_backend %}
|
|
259
|
+
## Remote Backend
|
|
260
|
+
|
|
261
|
+
This project uses a remote backend for Terraform state:
|
|
262
|
+
|
|
263
|
+
{% if provider == "aws" %}
|
|
264
|
+
- **State storage:** S3 bucket (`{{ project_name }}-terraform-state`)
|
|
265
|
+
- **State locking:** DynamoDB table (`{{ project_name }}-terraform-lock`)
|
|
266
|
+
{% elif provider == "gcp" %}
|
|
267
|
+
- **State storage:** GCS bucket (`{{ project_name }}-terraform-state`)
|
|
268
|
+
{% elif provider == "azure" %}
|
|
269
|
+
- **State storage:** Azure Storage Account
|
|
270
|
+
{% endif %}
|
|
271
|
+
|
|
272
|
+
> **Important:** You must create the backend resources before running `terraform init`.
|
|
273
|
+
> Use the `init.sh` script to bootstrap them.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
{% endif %}
|
|
277
|
+
|
|
278
|
+
## Deployment
|
|
279
|
+
|
|
280
|
+
### Prerequisites
|
|
281
|
+
|
|
282
|
+
- [Terraform](https://www.terraform.io/downloads) >= 1.6.0
|
|
283
|
+
{% if provider == "aws" %}
|
|
284
|
+
- [AWS CLI](https://aws.amazon.com/cli/) configured with credentials
|
|
285
|
+
{% elif provider == "gcp" %}
|
|
286
|
+
- [Google Cloud SDK](https://cloud.google.com/sdk) with `gcloud auth application-default login`
|
|
287
|
+
{% elif provider == "azure" %}
|
|
288
|
+
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/) with `az login`
|
|
289
|
+
{% endif %}
|
|
290
|
+
|
|
291
|
+
### Quick Start
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# 1. Navigate to your target environment
|
|
295
|
+
cd environments/dev
|
|
296
|
+
|
|
297
|
+
# 2. Initialize Terraform
|
|
298
|
+
terraform init
|
|
299
|
+
|
|
300
|
+
# 3. Review the execution plan
|
|
301
|
+
terraform plan
|
|
302
|
+
|
|
303
|
+
# 4. Apply the changes
|
|
304
|
+
terraform apply
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Using the Makefile
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
# Initialize
|
|
311
|
+
make init
|
|
312
|
+
|
|
313
|
+
# Plan changes
|
|
314
|
+
make plan
|
|
315
|
+
|
|
316
|
+
# Apply changes
|
|
317
|
+
make apply
|
|
318
|
+
|
|
319
|
+
# Format code
|
|
320
|
+
make fmt
|
|
321
|
+
|
|
322
|
+
# Validate configuration
|
|
323
|
+
make validate
|
|
324
|
+
|
|
325
|
+
# Destroy infrastructure
|
|
326
|
+
make destroy
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Destroy Instructions
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# Review what will be destroyed
|
|
335
|
+
terraform plan -destroy
|
|
336
|
+
|
|
337
|
+
# Destroy all resources
|
|
338
|
+
terraform destroy
|
|
339
|
+
|
|
340
|
+
# Or use Makefile
|
|
341
|
+
make destroy
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
> **Warning:** Destroying production infrastructure is irreversible. Ensure you
|
|
345
|
+
> have backups and have communicated with your team before proceeding.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Security Considerations
|
|
350
|
+
|
|
351
|
+
- All data-at-rest is encrypted
|
|
352
|
+
{% if "database" in services %}
|
|
353
|
+
- Database credentials are managed via Terraform (consider using Vault or Secrets Manager)
|
|
354
|
+
- Database is deployed in private subnets only
|
|
355
|
+
{% endif %}
|
|
356
|
+
{% if "storage" in services %}
|
|
357
|
+
- S3/GCS/Blob public access is blocked by default
|
|
358
|
+
{% endif %}
|
|
359
|
+
- Security groups follow the principle of least privilege
|
|
360
|
+
- All resources are tagged for cost allocation and ownership tracking
|
|
361
|
+
{% if enable_backend %}
|
|
362
|
+
- Terraform state is encrypted at rest
|
|
363
|
+
{% endif %}
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Scaling
|
|
368
|
+
|
|
369
|
+
{% if "compute" in services %}
|
|
370
|
+
### Compute
|
|
371
|
+
Adjust `asg_min_size`, `asg_max_size`, and `asg_desired_capacity` in
|
|
372
|
+
your environment's `terraform.tfvars` to scale horizontally.
|
|
373
|
+
{% endif %}
|
|
374
|
+
|
|
375
|
+
{% if "kubernetes" in services %}
|
|
376
|
+
### Kubernetes
|
|
377
|
+
Adjust `eks_node_min_size`, `eks_node_max_size`, and `eks_node_desired_size`
|
|
378
|
+
to control the cluster node pool. Consider enabling Cluster Autoscaler.
|
|
379
|
+
{% endif %}
|
|
380
|
+
|
|
381
|
+
{% if "database" in services %}
|
|
382
|
+
### Database
|
|
383
|
+
- Vertical scaling: change `db_instance_class`
|
|
384
|
+
- Storage auto-scaling is enabled (up to 2x allocated storage)
|
|
385
|
+
- Production uses Multi-AZ for high availability
|
|
386
|
+
{% endif %}
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Adding New Modules
|
|
391
|
+
|
|
392
|
+
1. Create a new directory under `modules/`:
|
|
393
|
+
```bash
|
|
394
|
+
mkdir -p modules/my-module
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
2. Add `main.tf`, `variables.tf`, and `outputs.tf` inside it.
|
|
398
|
+
|
|
399
|
+
3. Reference it in the root `main.tf`:
|
|
400
|
+
```hcl
|
|
401
|
+
module "my_module" {
|
|
402
|
+
source = "./modules/my-module"
|
|
403
|
+
# pass variables
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
4. Add corresponding variables to `variables.tf` and outputs to `outputs.tf`.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Customizing Variables
|
|
412
|
+
|
|
413
|
+
1. Open the relevant environment's `terraform.tfvars` file.
|
|
414
|
+
2. Override any variable defined in `variables.tf`.
|
|
415
|
+
3. Run `terraform plan` to preview changes.
|
|
416
|
+
4. Run `terraform apply` to apply.
|
|
417
|
+
|
|
418
|
+
For sensitive values, use environment variables:
|
|
419
|
+
```bash
|
|
420
|
+
export TF_VAR_db_username="admin"
|
|
421
|
+
terraform plan
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
*Generated by [tf-starter](https://github.com/tf-starter) v1.0.0*
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
3
|
+
# Bootstrap script for {{ project_name }}
|
|
4
|
+
# Creates remote backend resources (if enabled) and initializes Terraform.
|
|
5
|
+
# Generated by tf-starter
|
|
6
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
PROJECT_NAME="{{ project_name }}"
|
|
11
|
+
REGION="{{ region }}"
|
|
12
|
+
|
|
13
|
+
echo "============================================="
|
|
14
|
+
echo " {{ project_name }} — Infrastructure Bootstrap"
|
|
15
|
+
echo "============================================="
|
|
16
|
+
echo ""
|
|
17
|
+
|
|
18
|
+
{% if enable_backend %}
|
|
19
|
+
{% if provider == "aws" %}
|
|
20
|
+
# ----- Create S3 bucket for Terraform state -----
|
|
21
|
+
|
|
22
|
+
BUCKET_NAME="${PROJECT_NAME}-terraform-state"
|
|
23
|
+
TABLE_NAME="${PROJECT_NAME}-terraform-lock"
|
|
24
|
+
|
|
25
|
+
echo "Creating S3 bucket for Terraform state: ${BUCKET_NAME}"
|
|
26
|
+
if aws s3api head-bucket --bucket "${BUCKET_NAME}" 2>/dev/null; then
|
|
27
|
+
echo " Bucket already exists. Skipping."
|
|
28
|
+
else
|
|
29
|
+
aws s3api create-bucket \
|
|
30
|
+
--bucket "${BUCKET_NAME}" \
|
|
31
|
+
--region "${REGION}" \
|
|
32
|
+
$([ "${REGION}" != "us-east-1" ] && echo "--create-bucket-configuration LocationConstraint=${REGION}")
|
|
33
|
+
|
|
34
|
+
aws s3api put-bucket-versioning \
|
|
35
|
+
--bucket "${BUCKET_NAME}" \
|
|
36
|
+
--versioning-configuration Status=Enabled
|
|
37
|
+
|
|
38
|
+
aws s3api put-bucket-encryption \
|
|
39
|
+
--bucket "${BUCKET_NAME}" \
|
|
40
|
+
--server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
|
|
41
|
+
|
|
42
|
+
aws s3api put-public-access-block \
|
|
43
|
+
--bucket "${BUCKET_NAME}" \
|
|
44
|
+
--public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
|
|
45
|
+
|
|
46
|
+
echo " Bucket created."
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# ----- Create DynamoDB table for state locking -----
|
|
50
|
+
|
|
51
|
+
echo "Creating DynamoDB table for state locking: ${TABLE_NAME}"
|
|
52
|
+
if aws dynamodb describe-table --table-name "${TABLE_NAME}" --region "${REGION}" >/dev/null 2>&1; then
|
|
53
|
+
echo " Table already exists. Skipping."
|
|
54
|
+
else
|
|
55
|
+
aws dynamodb create-table \
|
|
56
|
+
--table-name "${TABLE_NAME}" \
|
|
57
|
+
--attribute-definitions AttributeName=LockID,AttributeType=S \
|
|
58
|
+
--key-schema AttributeName=LockID,KeyType=HASH \
|
|
59
|
+
--billing-mode PAY_PER_REQUEST \
|
|
60
|
+
--region "${REGION}"
|
|
61
|
+
|
|
62
|
+
echo " Table created."
|
|
63
|
+
fi
|
|
64
|
+
{% elif provider == "gcp" %}
|
|
65
|
+
BUCKET_NAME="${PROJECT_NAME}-terraform-state"
|
|
66
|
+
|
|
67
|
+
echo "Creating GCS bucket for Terraform state: ${BUCKET_NAME}"
|
|
68
|
+
if gsutil ls -b "gs://${BUCKET_NAME}" 2>/dev/null; then
|
|
69
|
+
echo " Bucket already exists. Skipping."
|
|
70
|
+
else
|
|
71
|
+
gsutil mb -l "${REGION}" "gs://${BUCKET_NAME}"
|
|
72
|
+
gsutil versioning set on "gs://${BUCKET_NAME}"
|
|
73
|
+
echo " Bucket created."
|
|
74
|
+
fi
|
|
75
|
+
{% elif provider == "azure" %}
|
|
76
|
+
RESOURCE_GROUP="${PROJECT_NAME}-tfstate-rg"
|
|
77
|
+
STORAGE_ACCOUNT=$(echo "${PROJECT_NAME}tfstate" | tr -d '-' | head -c 24)
|
|
78
|
+
CONTAINER_NAME="tfstate"
|
|
79
|
+
|
|
80
|
+
echo "Creating Azure Storage for Terraform state..."
|
|
81
|
+
az group create --name "${RESOURCE_GROUP}" --location "${REGION}" || true
|
|
82
|
+
|
|
83
|
+
az storage account create \
|
|
84
|
+
--resource-group "${RESOURCE_GROUP}" \
|
|
85
|
+
--name "${STORAGE_ACCOUNT}" \
|
|
86
|
+
--sku Standard_LRS \
|
|
87
|
+
--encryption-services blob 2>/dev/null || echo " Storage account already exists."
|
|
88
|
+
|
|
89
|
+
az storage container create \
|
|
90
|
+
--name "${CONTAINER_NAME}" \
|
|
91
|
+
--account-name "${STORAGE_ACCOUNT}" 2>/dev/null || echo " Container already exists."
|
|
92
|
+
{% endif %}
|
|
93
|
+
|
|
94
|
+
echo ""
|
|
95
|
+
{% endif %}
|
|
96
|
+
|
|
97
|
+
# ----- Initialize Terraform -----
|
|
98
|
+
|
|
99
|
+
echo "Initializing Terraform..."
|
|
100
|
+
for env_dir in environments/*/; do
|
|
101
|
+
env_name=$(basename "${env_dir}")
|
|
102
|
+
echo " Initializing environment: ${env_name}"
|
|
103
|
+
(cd "${env_dir}" && terraform init)
|
|
104
|
+
done
|
|
105
|
+
|
|
106
|
+
echo ""
|
|
107
|
+
echo "============================================="
|
|
108
|
+
echo " Bootstrap complete!"
|
|
109
|
+
echo " Run 'make plan ENV=dev' to preview changes."
|
|
110
|
+
echo "============================================="
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Pre-commit configuration for {{ project_name }}
|
|
2
|
+
# Install: pip install pre-commit && pre-commit install
|
|
3
|
+
# Generated by tf-starter
|
|
4
|
+
|
|
5
|
+
repos:
|
|
6
|
+
- repo: https://github.com/antonbabenko/pre-commit-terraform
|
|
7
|
+
rev: v1.88.0
|
|
8
|
+
hooks:
|
|
9
|
+
- id: terraform_fmt
|
|
10
|
+
name: Terraform fmt
|
|
11
|
+
description: Rewrites Terraform config to canonical format
|
|
12
|
+
|
|
13
|
+
- id: terraform_validate
|
|
14
|
+
name: Terraform validate
|
|
15
|
+
description: Validates Terraform configuration
|
|
16
|
+
args:
|
|
17
|
+
- --hook-config=--retry-once-with-cleanup=true
|
|
18
|
+
|
|
19
|
+
- id: terraform_tflint
|
|
20
|
+
name: Terraform tflint
|
|
21
|
+
description: Lints Terraform configuration
|
|
22
|
+
|
|
23
|
+
- id: terraform_docs
|
|
24
|
+
name: Terraform docs
|
|
25
|
+
description: Generates documentation from Terraform modules
|
|
26
|
+
|
|
27
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
28
|
+
rev: v4.5.0
|
|
29
|
+
hooks:
|
|
30
|
+
- id: trailing-whitespace
|
|
31
|
+
- id: end-of-file-fixer
|
|
32
|
+
- id: check-yaml
|
|
33
|
+
- id: check-merge-conflict
|
|
34
|
+
- id: detect-private-key
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# API GATEWAY MODULE — Azure API Management
|
|
3
|
+
# Project: {{ project_name }}
|
|
4
|
+
# Generated by tf-starter
|
|
5
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
locals {
|
|
8
|
+
name_prefix = "${var.project_name}-${var.environment}"
|
|
9
|
+
apim_name = "${local.name_prefix}-apim"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
13
|
+
# API MANAGEMENT INSTANCE
|
|
14
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
resource "azurerm_api_management" "main" {
|
|
17
|
+
name = local.apim_name
|
|
18
|
+
resource_group_name = var.resource_group_name
|
|
19
|
+
location = var.location
|
|
20
|
+
publisher_name = var.publisher_name
|
|
21
|
+
publisher_email = var.publisher_email
|
|
22
|
+
sku_name = var.sku_name
|
|
23
|
+
|
|
24
|
+
identity {
|
|
25
|
+
type = "SystemAssigned"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
tags = merge(var.tags, {
|
|
29
|
+
Name = local.apim_name
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
34
|
+
# API DEFINITION
|
|
35
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
resource "azurerm_api_management_api" "main" {
|
|
38
|
+
name = "${local.name_prefix}-api"
|
|
39
|
+
resource_group_name = var.resource_group_name
|
|
40
|
+
api_management_name = azurerm_api_management.main.name
|
|
41
|
+
revision = "1"
|
|
42
|
+
display_name = "${var.project_name} API"
|
|
43
|
+
path = "api"
|
|
44
|
+
protocols = ["https"]
|
|
45
|
+
|
|
46
|
+
subscription_required = false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
50
|
+
# API OPERATION — catch-all proxy to Function App
|
|
51
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
resource "azurerm_api_management_api_operation" "proxy" {
|
|
54
|
+
operation_id = "proxy"
|
|
55
|
+
api_name = azurerm_api_management_api.main.name
|
|
56
|
+
api_management_name = azurerm_api_management.main.name
|
|
57
|
+
resource_group_name = var.resource_group_name
|
|
58
|
+
display_name = "Proxy"
|
|
59
|
+
method = "POST"
|
|
60
|
+
url_template = "/{path}"
|
|
61
|
+
|
|
62
|
+
template_parameter {
|
|
63
|
+
name = "path"
|
|
64
|
+
required = true
|
|
65
|
+
type = "string"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
70
|
+
# BACKEND — Function App
|
|
71
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
resource "azurerm_api_management_backend" "function" {
|
|
74
|
+
name = "${local.name_prefix}-backend"
|
|
75
|
+
resource_group_name = var.resource_group_name
|
|
76
|
+
api_management_name = azurerm_api_management.main.name
|
|
77
|
+
protocol = "http"
|
|
78
|
+
url = "https://${var.function_app_hostname}/api"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
82
|
+
# CORS POLICY
|
|
83
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
resource "azurerm_api_management_api_policy" "cors" {
|
|
86
|
+
api_name = azurerm_api_management_api.main.name
|
|
87
|
+
api_management_name = azurerm_api_management.main.name
|
|
88
|
+
resource_group_name = var.resource_group_name
|
|
89
|
+
|
|
90
|
+
xml_content = <<-XML
|
|
91
|
+
<policies>
|
|
92
|
+
<inbound>
|
|
93
|
+
<base />
|
|
94
|
+
<cors allow-credentials="false">
|
|
95
|
+
<allowed-origins>
|
|
96
|
+
<origin>*</origin>
|
|
97
|
+
</allowed-origins>
|
|
98
|
+
<allowed-methods>
|
|
99
|
+
<method>GET</method>
|
|
100
|
+
<method>POST</method>
|
|
101
|
+
<method>PUT</method>
|
|
102
|
+
<method>DELETE</method>
|
|
103
|
+
<method>OPTIONS</method>
|
|
104
|
+
</allowed-methods>
|
|
105
|
+
<allowed-headers>
|
|
106
|
+
<header>*</header>
|
|
107
|
+
</allowed-headers>
|
|
108
|
+
</cors>
|
|
109
|
+
<set-backend-service backend-id="${local.name_prefix}-backend" />
|
|
110
|
+
</inbound>
|
|
111
|
+
<backend>
|
|
112
|
+
<base />
|
|
113
|
+
</backend>
|
|
114
|
+
<outbound>
|
|
115
|
+
<base />
|
|
116
|
+
</outbound>
|
|
117
|
+
<on-error>
|
|
118
|
+
<base />
|
|
119
|
+
</on-error>
|
|
120
|
+
</policies>
|
|
121
|
+
XML
|
|
122
|
+
|
|
123
|
+
### MUST EDIT THIS ###
|
|
124
|
+
# For production, restrict allowed-origins to your domain.
|
|
125
|
+
}
|