├── .dockerignore ├── .drone.yml ├── .gitignore ├── .gitmodules ├── .terraform-docs.yml ├── .terraformignore ├── Dockerfile ├── LICENSE ├── README.md ├── Taskfile.yml ├── assets └── .gitkeep ├── config ├── aws-filter.yaml └── gcp-filter.yaml ├── docs ├── .dockerignore ├── Dockerfile ├── build.yml ├── build │ └── .gitkeep ├── docker-compose.yml ├── md │ ├── 404.md │ ├── _toc.md │ ├── docs │ │ ├── code-features.md │ │ ├── development │ │ │ ├── contact.md │ │ │ ├── contributions.md │ │ │ ├── guidelines.md │ │ │ ├── prs.md │ │ │ ├── roadmap.md │ │ │ └── tests.md │ │ ├── intro │ │ │ ├── about.md │ │ │ ├── legal.md │ │ │ ├── next-steps.md │ │ │ ├── terms.md │ │ │ ├── thanks.md │ │ │ └── what-is.md │ │ ├── providers │ │ │ ├── amnzaws.md │ │ │ ├── gcloud.md │ │ │ ├── msazure.md │ │ │ └── oracle.md │ │ └── setup │ │ │ ├── environment.md │ │ │ ├── first-run.md │ │ │ ├── getting-started.md │ │ │ ├── installing.md │ │ │ ├── management.md │ │ │ ├── requirements.md │ │ │ └── resources.md │ └── index.md └── vercel.json ├── examples ├── aws │ ├── e2e │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ └── unit │ │ ├── ec2 │ │ ├── README.md │ │ ├── main.tf │ │ └── variables.tf │ │ └── rds │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf ├── azure │ ├── e2e │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ └── unit │ │ ├── compute │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ │ └── db │ │ ├── main.tf │ │ └── variables.tf └── gcp │ ├── e2e │ ├── README.md │ ├── main.tf │ ├── terraform.tfvars.example │ └── variables.tf │ └── unit │ ├── compute │ ├── README.md │ ├── main.tf │ ├── terraform.tfvars.example │ └── variables.tf │ ├── storage │ ├── README.md │ ├── main.tf │ ├── terraform.tfvars.example │ └── variables.tf │ └── vpc │ ├── README.md │ ├── main.tf │ ├── terraform.tfvars.example │ └── variables.tf ├── main.tf ├── modules ├── aws │ ├── README.md │ ├── ec2 │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── firewall │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── gateway │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── main.tf │ ├── outputs.tf │ ├── rds │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── variables.tf │ └── vpc │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf ├── azure │ ├── README.md │ ├── compute │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── db │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── vpc │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf └── gcp │ ├── README.md │ ├── compute │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ ├── firewall │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ ├── main.tf │ ├── outputs.tf │ ├── storage │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf │ ├── variables.tf │ └── vpc │ ├── README.md │ ├── main.tf │ └── variables.tf ├── outputs.tf ├── renovate.json ├── scripts ├── entrypoint.sh ├── plan.sh ├── requirements.txt ├── slim.yml └── test.sh ├── tasks ├── aws.yaml ├── clean.yaml ├── docker.yaml └── gcp.yaml ├── test ├── aws │ ├── README.md │ ├── ec2_test.go │ ├── network_test.go │ └── rds_test.go ├── azure │ └── azure_integrated_test.go ├── docker │ └── dockerfile_test.go └── gcp │ ├── compute_test.go │ ├── gcp_test.go │ ├── storage_test.go │ └── vpc_test.go ├── variables.tf └── versions.tf /.dockerignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | *.tfstate 4 | *.tfstate.* 5 | crash.log 6 | override.tf 7 | override.tf.json 8 | *_override.tf 9 | *_override.tf.json 10 | **/.terraform.lock.hcl/* 11 | .terraform.lock.hcl 12 | .terraform 13 | *tfplan* 14 | terraform.tfvars 15 | graph.json 16 | graph.svg 17 | *.tfvars 18 | terraform.tfvars 19 | terraform.env.tfvars 20 | *.tfstate.* 21 | graph.png 22 | plan.json 23 | plan.out 24 | graph.html 25 | index.html 26 | 27 | # credentials 28 | aws.json 29 | aws.pub 30 | **/gcp.json/* 31 | gcp.json 32 | *.pub 33 | **/id_rsa.pub/* 34 | id_rsa.* 35 | **/id_rsa/* 36 | 37 | # Documentation / Node.js 38 | docs/dist/* 39 | docs/*.html 40 | */*.html 41 | *.html 42 | logs 43 | *.log 44 | *.js 45 | *.meta.json 46 | *.css 47 | npm-debug.log* 48 | yarn-debug.log* 49 | yarn-error.log* 50 | lerna-debug.log* 51 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 52 | pids 53 | *.pid 54 | *.seed 55 | *.pid.lock 56 | lib-cov 57 | coverage 58 | *.lcov 59 | .nyc_output 60 | .grunt 61 | bower_components 62 | .lock-wscript 63 | build/Release 64 | node_modules/ 65 | jspm_packages/ 66 | typings/ 67 | *.tsbuildinfo 68 | .npm 69 | .eslintcache 70 | .rpt2_cache/ 71 | .rts2_cache_cjs/ 72 | .rts2_cache_es/ 73 | .rts2_cache_umd/ 74 | .node_repl_history 75 | *.tgz 76 | .yarn-integrity 77 | .env 78 | .env.test 79 | .cache 80 | index.html 81 | .next 82 | .nuxt 83 | dist 84 | .cache/ 85 | .vuepress/dist 86 | .serverless/ 87 | .fusebox/ 88 | .dynamodb/ 89 | .tern-por 90 | *.json 91 | *.lock.hcl 92 | 93 | # .vscode 94 | .vscode 95 | 96 | # Artifacts docker-slim 97 | slim.report.json 98 | Dockerfile.fat 99 | creport.jsondiff 100 | *.report.json 101 | 102 | # Terraform Visual 103 | terraform-visual-report 104 | terraform-visual-report/* 105 | 106 | # Blast Radius 107 | blast/* 108 | blast -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: pipeline 3 | type: docker 4 | name: Basic testing 5 | trigger: 6 | event: 7 | include: 8 | - push 9 | exclude: 10 | - pull_request 11 | 12 | node: 13 | server: home 14 | arm: no 15 | docker: yes 16 | platform: 17 | os: linux 18 | arch: amd64 19 | 20 | steps: 21 | - name: Build Image 22 | image: plugins/docker 23 | settings: 24 | dockerfile: Dockerfile 25 | pull_images: true 26 | repo: ghcr.io/gruberdev/freetf 27 | cache_from: ghcr.io/gruberdev/freetf 28 | registry: ghcr.io 29 | username: gruberdev 30 | password: 31 | from_secret: gh_token 32 | 33 | - name: Terraform Plan 34 | image: ghcr.io/gruberdev/freetf:latest 35 | commands: 36 | - mkdir -p ~/.ssh-temp 37 | - chmod 700 ~/.ssh-temp 38 | - ssh-keygen -t rsa -b 4096 -C "example@gmail.com" -N 'test' -f ~/.ssh-temp/id_rsa 39 | - touch key.json && echo $$GOOGLE_CREDENTIALS >> key.json 40 | - export GOOGLE_APPLICATION_CREDENTIAL=key.json 41 | - terraform init -upgrade -reconfigure -force-copy 42 | - terraform plan 43 | environment: 44 | ARM_CLIENT_ID: 45 | from_secret: arm_id 46 | ARM_CLIENT_CERTIFICATE_PATH: 47 | from secret: azure_path 48 | ARM_CLIENT_CERTIFICATE_PASSWORD: 49 | from_secret: cte_password 50 | ARM_SUBSCRIPTION_ID: 51 | from_secret: azure_sub_id 52 | ARM_TENANT_ID: 53 | from_secret: azure_tenant_id 54 | GOOGLE_CREDENTIALS: 55 | from_secret: gcp_json 56 | GOOGLE_PROJECT: 57 | from_secret: google_cloud_projectid 58 | AWS_DEFAULT_REGION: 59 | from_secret: aws_default_region 60 | AWS_SECRET_ACCESS_KEY: 61 | from_secret: aws_account_secret 62 | AWS_ACCESS_KEY_ID: 63 | from_secret: aws_account_id 64 | depends_on: 65 | - Build Image 66 | 67 | - name: Finished testing 68 | image: ghcr.io/gruberdev/freetf:latest 69 | commands: 70 | - echo "Finished basic setup!" 71 | depends_on: 72 | - Terraform Plan 73 | - Build Image 74 | 75 | # - name: tfsec 76 | # image: tfsec/tfsec 77 | # commands: 78 | # - tfsec . -e GCP003,AWS044,GEN003 79 | # when: 80 | # status: 81 | # - success 82 | # - failure 83 | # event: 84 | # - push 85 | # - pull_request 86 | # environment: 87 | # GOOGLE_PROJECT: 88 | # from_secret: gcp_project_id 89 | # GOOGLE_KEY: 90 | # from_secret: gcp_default 91 | # AWS_DEFAULT_REGION: 92 | # from_secret: aws_region 93 | # AWS_SECRET_ACCESS_KEY: 94 | # from_secret: aws_key 95 | # AWS_ACCESS_KEY_ID: 96 | # from_secret: aws_id 97 | # - name: terrascan 98 | # image: accurics/terrascan 99 | # commands: 100 | # - terrascan scan 101 | # when: 102 | # status: 103 | # - success 104 | # - failure 105 | # event: 106 | # - push 107 | # - pull_request 108 | # - rollback 109 | # environment: 110 | # GOOGLE_PROJECT: 111 | # from_secret: gcp_project_id 112 | # GOOGLE_KEY: 113 | # from_secret: gcp_default 114 | # AWS_DEFAULT_REGION: 115 | # from_secret: aws_region 116 | # AWS_SECRET_ACCESS_KEY: 117 | # from_secret: aws_key 118 | # AWS_ACCESS_KEY_ID: 119 | # from_secret: aws_id 120 | # --- 121 | # kind: pipeline 122 | # type: docker 123 | # name: Amazon Web Services (AWS) 124 | # platform: 125 | # arch: amd64 126 | # depends_on: 127 | # - Basic testing 128 | # - Kickoff 129 | # trigger: 130 | # exclude: 131 | # - pull_request 132 | # include: 133 | # - push 134 | # branch: 135 | # exclude: 136 | # - renovate/* 137 | # include: 138 | # - main 139 | # - feature/aws_* 140 | # steps: 141 | # - name: Setup AWS 142 | # image: golang:1.16.6-alpine 143 | # commands: 144 | # - apk update && apk add curl && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 145 | # - task init-drone 146 | # - task aws-init 147 | # environment: 148 | # AWS_DEFAULT_REGION: 149 | # from_secret: aws_region 150 | # AWS_SECRET_ACCESS_KEY: 151 | # from_secret: aws_key 152 | # AWS_ACCESS_KEY_ID: 153 | # from_secret: aws_id 154 | # - name: Unit Test EC2 155 | # image: golang:1.16.6-alpine 156 | # commands: 157 | # - apk update && apk add curl && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 158 | # - task init-drone 159 | # - task unit-ec2-aws 160 | # depends_on: 161 | # - Setup AWS 162 | # environment: 163 | # AWS_DEFAULT_REGION: 164 | # from_secret: aws_region 165 | # AWS_SECRET_ACCESS_KEY: 166 | # from_secret: aws_key 167 | # AWS_ACCESS_KEY_ID: 168 | # from_secret: aws_id 169 | # - name: Unit Test RDS 170 | # image: golang:1.16.6-alpine 171 | # commands: 172 | # - apk update && apk add curl && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 173 | # - task init-drone 174 | # - task unit-rds-aws 175 | # depends_on: 176 | # - Setup AWS 177 | # - Unit Test EC2 178 | # environment: 179 | # AWS_DEFAULT_REGION: 180 | # from_secret: aws_region 181 | # AWS_SECRET_ACCESS_KEY: 182 | # from_secret: aws_key 183 | # AWS_ACCESS_KEY_ID: 184 | # from_secret: aws_id 185 | # --- 186 | # kind: pipeline 187 | # type: docker 188 | # name: Google Cloud Provider (GCP) 189 | # platform: 190 | # arch: amd64 191 | # depends_on: 192 | # - Basic testing 193 | # - Kickoff 194 | # trigger: 195 | # exclude: 196 | # - pull_request 197 | # include: 198 | # - push 199 | # branch: 200 | # exclude: 201 | # - renovate/* 202 | # include: 203 | # - main 204 | # - feature/gcp_* 205 | # steps: 206 | # - name: Setup 207 | # image: golang:1.16.6-alpine 208 | # commands: 209 | # - apk update && apk add curl && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 210 | # - task init-drone 211 | # environment: 212 | # GOOGLE_CREDENTIALS: 213 | # from_secret: gcp_key 214 | # GOOGLE_PROJECT: 215 | # from_secret: gcp_project_id 216 | 217 | # - name: GCP Start Notification 218 | # image: appleboy/drone-discord 219 | # settings: 220 | # webhook_id: 221 | # from_secret: discord_id 222 | # webhook_token: 223 | # from_secret: discord_token 224 | # message: |- 225 | # Started GCP Pipeline on Drone CI. 226 | # Build number: {{build.number}} 227 | 228 | # - name: Unit Compute 229 | # image: golang:1.16.6-alpine 230 | # commands: 231 | # - apk update && apk add curl && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 232 | # - task init-drone 233 | # - task unit-compute-gcp 234 | # depends_on: 235 | # - Setup 236 | # environment: 237 | # GOOGLE_CREDENTIALS: 238 | # from_secret: gcp_key 239 | # GOOGLE_PROJECT: 240 | # from_secret: gcp_project_id 241 | 242 | # - name: Unit Networking 243 | # image: golang:1.16.6-alpine 244 | # commands: 245 | # - apk update && apk add curl && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 246 | # - task init-drone 247 | # - task unit-network-gcp 248 | # depends_on: 249 | # - Setup 250 | # environment: 251 | # GOOGLE_CREDENTIALS: 252 | # from_secret: gcp_key 253 | # GOOGLE_PROJECT: 254 | # from_secret: gcp_project_id 255 | 256 | # # - name: Unit Bucket Storage 257 | # # image: golang:1.16.5-alpine 258 | # # commands: 259 | # # - apk update && apk add curl && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 260 | # # - task init-drone 261 | # # - task unit-storage-gcp 262 | # # depends_on: 263 | # # - Setup 264 | # # - Unit Networking 265 | # # - Unit Compute 266 | # # environment: 267 | # # GOOGLE_CREDENTIALS: 268 | # # from_secret: gcp_key 269 | # # GOOGLE_PROJECT: 270 | # # from_secret: gcp_project_id 271 | 272 | # - name: Testing has been sucessful 273 | # image: golang:1.16.6-alpine 274 | # commands: 275 | # - echo "Finished." 276 | # depends_on: 277 | # - Unit Networking 278 | # - Unit Compute 279 | # - Setup 280 | # environment: 281 | # GOOGLE_CREDENTIALS: 282 | # from_secret: gcp_key 283 | # GOOGLE_PROJECT: 284 | # from_secret: gcp_project_id 285 | 286 | # --- 287 | # kind: pipeline 288 | # type: docker 289 | # name: Success Webhook Notification 290 | # platform: 291 | # arch: amd64 292 | # depends_on: 293 | # - Basic testing 294 | # - Kickoff 295 | # - Google Cloud Provider (GCP) 296 | # - Amazon Web Services (AWS) 297 | # trigger: 298 | # event: 299 | # include: 300 | # - push 301 | # exclude: 302 | # - pull_request 303 | # status: 304 | # - success 305 | # steps: 306 | # - name: Notification Webhook 307 | # image: appleboy/drone-discord 308 | # settings: 309 | # webhook_id: 310 | # from_secret: discord_id 311 | # webhook_token: 312 | # from_secret: discord_token 313 | # message: |- 314 | # Pipeline {{build.number}} has been sucessfully completed. 315 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | *.tfstate 4 | *.tfstate.* 5 | crash.log 6 | override.tf 7 | override.tf.json 8 | *_override.tf 9 | *_override.tf.json 10 | **/.terraform.lock.hcl/* 11 | .terraform.lock.hcl 12 | .terraform 13 | *tfplan* 14 | graph.json 15 | graph.svg 16 | *.tfvars 17 | terraform.tfvars 18 | terraform.env.tfvars 19 | *.tfstate.* 20 | graph.png 21 | plan.json 22 | plan.out 23 | graph.html 24 | index.html 25 | backend.tf 26 | 27 | # Terraform Backend 28 | .terraform.tfstate.lock.info 29 | 30 | # Go project-related 31 | test/*/go.sum 32 | test/*/go.mod 33 | test/gcp/go.mod 34 | test/gcp/go.sum 35 | test/aws/go.sum 36 | test/aws/go.mod 37 | test/go.mod 38 | test/go.sum 39 | test/docker/go.mod 40 | test/docker/go.sum 41 | 42 | # credentials 43 | aws.json 44 | aws.pub 45 | **/gcp.json/* 46 | gcp.json 47 | *.pub 48 | **/id_rsa.pub/* 49 | id_rsa.* 50 | **/id_rsa/* 51 | 52 | # Documentation / Node.js 53 | docs/dist/* 54 | docs/*.html 55 | */*.html 56 | *.html 57 | *.json 58 | logs 59 | *.log 60 | *.js 61 | *.meta.json 62 | *.css 63 | npm-debug.log* 64 | yarn-debug.log* 65 | yarn-error.log* 66 | lerna-debug.log* 67 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 68 | pids 69 | *.pid 70 | *.seed 71 | *.pid.lock 72 | lib-cov 73 | coverage 74 | *.lcov 75 | .nyc_output 76 | .grunt 77 | bower_components 78 | .lock-wscript 79 | build/Release 80 | node_modules/ 81 | jspm_packages/ 82 | typings/ 83 | *.tsbuildinfo 84 | .npm 85 | .eslintcache 86 | .rpt2_cache/ 87 | .rts2_cache_cjs/ 88 | .rts2_cache_es/ 89 | .rts2_cache_umd/ 90 | .node_repl_history 91 | *.tgz 92 | .yarn-integrity 93 | .env 94 | .env.test 95 | .cache 96 | index.html 97 | .next 98 | .nuxt 99 | dist 100 | .cache/ 101 | .vuepress/dist 102 | .serverless/ 103 | .fusebox/ 104 | .dynamodb/ 105 | .tern-port 106 | docs/.public/* 107 | 108 | # Docker 109 | 110 | # .vscode 111 | .vscode 112 | 113 | # Artifacts docker-slim 114 | slim.report.json 115 | Dockerfile.fat 116 | creport.jsondiff 117 | *.report.json 118 | 119 | # Terraform Visual 120 | terraform-visual-report 121 | terraform-visual-report/* 122 | 123 | # Blast Radius 124 | blast/* 125 | blast -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "setup"] 2 | path = setup 3 | url = https://github.com/gruberdev/setup 4 | -------------------------------------------------------------------------------- /.terraform-docs.yml: -------------------------------------------------------------------------------- 1 | formatter: markdown 2 | 3 | sections: 4 | show: 5 | - inputs 6 | - outputs 7 | - modules 8 | 9 | output: 10 | file: README.md 11 | mode: inject 12 | template: |- 13 | 14 | {{ .Content }} 15 | 16 | 17 | sort: 18 | enabled: true 19 | by: name 20 | 21 | settings: 22 | anchor: false 23 | indent: 3 24 | color: true 25 | html: true 26 | escape: true 27 | default: true 28 | required: false 29 | type: true 30 | sensitive: true 31 | -------------------------------------------------------------------------------- /.terraformignore: -------------------------------------------------------------------------------- 1 | # Misc 2 | .DS_Store 3 | LICENSE.md 4 | README.md 5 | 6 | # Binaries 7 | .terraform/ 8 | *.exe 9 | *.tfstate 10 | *.backup 11 | *.bak 12 | *.info 13 | 14 | # Credentials 15 | *account.json 16 | sshkey* 17 | privkey* 18 | pubkey* 19 | id_rsa* 20 | .git/ 21 | .github/ 22 | .terraform/ 23 | .vscode/ 24 | doc/ 25 | dockerfiles/ 26 | kubernetes/ 27 | schemas/ 28 | templates/ 29 | tools/backend 30 | frontend 31 | .editorconfig 32 | .gitignore 33 | 34 | # Terraform 35 | **.terraform/ 36 | **.terraform.lock.hcl 37 | **.json 38 | *.json 39 | 40 | # Sensitive 41 | **policy_documents/ 42 | **trust_document/ 43 | 44 | # logs 45 | terraform.log 46 | 47 | # MacOS 48 | .DS_Store 49 | 50 | #Node modules 51 | node_modules/** 52 | 53 | # Coverage reports 54 | .nyc_output/** 55 | coverage/** 56 | 57 | # Build output folder 58 | dist/** -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Core Docker Packages Versioning 2 | ARG GO_VERSION=1.19.0 3 | ARG TF_CLI_VERSION="1.2.6" 4 | ARG TFSEC_VERSION="1.13.2" 5 | ARG TFDOCS_VERSION="0.9.1" 6 | 7 | # CLIs Dockerized Providers 8 | FROM hashicorp/terraform:${TF_CLI_VERSION} as build-tf-cli 9 | FROM tfsec/tfsec-alpine:v${TFSEC_VERSION}-amd64 as build-tfsec 10 | FROM cytopia/terraform-docs:${TFDOCS_VERSION} as build-terraform-docs 11 | # hadolint ignore=DL3007 12 | FROM accurics/terrascan:latest as build-tfscan 13 | 14 | ################################################################ 15 | 16 | # Base Image: Alpine & Environment Configuration 17 | FROM golang:$GO_VERSION-alpine 18 | 19 | # Image Labels for Metadata Configuration 20 | LABEL org.opencontainers.image.source = "https://github.com/gruberdev/tf-free.git" 21 | 22 | COPY --from=build-tf-cli /bin/terraform /usr/local/bin/terraform 23 | COPY --from=build-tfsec /usr/bin/tfsec /usr/local/bin/tfsec 24 | COPY --from=build-terraform-docs /usr/local/bin/terraform-docs /usr/local/bin/terraform-docs 25 | COPY --from=build-tfscan /go/bin/terrascan /usr/local/bin/tfscan 26 | 27 | # Architecture Metadata 28 | ENV ARCH=amd64 29 | ENV ARCH_86=x86_64 30 | ENV OS=linux 31 | ENV TASK_VERSION=3.14.1 32 | # hadolint ignore=SC2034 33 | RUN go env -w GOPRIVATE=github.com/gruberdev 34 | ENV \ 35 | LANG="${LANG:-$LANG_DEFAULT}" \ 36 | LC_ALL="${LC_ALL:-$LC_ALL_DEFAULT}" \ 37 | PATH="/usr/local/go/bin:${PATH}" \ 38 | GO111MODULE='on' \ 39 | SHELL="/bin/bash" \ 40 | HAS_ALLOW_UNSAFE=y \ 41 | GOCACHE=/go 42 | 43 | # Install Python and GCC dependencies 44 | # hadolint ignore=DL3018 45 | RUN apk add --update --no-cache \ 46 | bash gcc g++ git curl \ 47 | zlib libffi-dev binutils \ 48 | openssh-client rsync \ 49 | ca-certificates musl-dev 50 | 51 | # Configuring bash instead of sh 52 | SHELL ["/bin/bash", "-eo", "pipefail", "-c"] 53 | 54 | # Go-Critic 55 | RUN curl -sSfL "https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh" | sh -s '-- -b $(go env GOPATH)/bin' 56 | 57 | # Task / makefile Alternative 58 | RUN wget -q -O /tmp/task.tar.gz https://github.com/go-task/task/releases/download/v${TASK_VERSION}/task_${OS}_${ARCH}.tar.gz && \ 59 | tar -C /usr/bin/ -xvf /tmp/task.tar.gz && \ 60 | rm -rf /tmp/gotty.tar.gzln 61 | 62 | RUN echo "export PATH="/go/bin:/usr/local/go/bin:${PATH}"" >> "${HOME}/.bashrc" 63 | 64 | # Bootstrapping the project 65 | WORKDIR /project 66 | COPY . . 67 | RUN chmod +x /project/scripts/entrypoint.sh 68 | 69 | # Verifying dependencies existence within Dockerfile 70 | RUN curl -sL https://git.io/_has | bash -s git tfscan \ 71 | tfsec terraform-docs terraform go task bash 72 | 73 | CMD ["/bin/bash"] 74 | ENTRYPOINT ["/project/scripts/entrypoint.sh"] 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Logo Animation](https://readme-typing-svg.herokuapp.com?font=Major+Mono+Display&color=00E7F7&size=40&vCenter=true&width=800&height=200&lines=tf-free;cloud+for+free.)](https://free.terraform.gruber.dev.br) 2 | 3 | ![docs-img] ![drone-img] 4 | 5 | ## Objective 6 | 7 | > **Creating and managing all available resources offered by major cloud providers exclusively in free-tier plans. Using Terraform to create and manage all the resources in a simplified and centralized manner.** 8 | 9 | ## Motivation 10 | 11 | Every major cloud provider offers a free tier that allows for some kind of resource free of charge, still, learning every cloud and managing these resources can prove burdensome to most. 12 | 13 | The goal is to automate the management of these resources using Terraform as the centralizing tool. It also aims to provide resources for learning and improve your skills as a SRE/DevOps Engineer and as a Terraform user, even if you're developer that never touched cloud infrastructure, nowadays there's great value in learning these tools. 14 | 15 | ## List of free-tier resources 16 | 17 |
18 | 19 | 20 | Google Cloud Platform 21 | 22 | 23 | --- 24 | 25 | ## GCP Available Resources 26 | 27 | - **1x** [Virtual Private Cloud (VPC)][gcp-vpc-info] 28 | - **1x** [Firewall][gcp-firewall-info] attached to the VPC 29 | - **1x** [Google Compute Engine][gcp-compute-info] `f1-micro` [(1 shared vCPU - 0.2 dedicatd vCPU][gcp-shared-vcpus] - and 0.6GB of Memory) attached to the `VPC` 30 | - **1x** 5GB of [regional storage][gcp-regional-storage] on [Cloud Storage][gcp-cloud-storage] 31 | - **1x** 1GB of storage in a [Firestore NoSQL Database][gcp-firestore-storage] 32 | 33 | More information at the [provider's documentation page][tf-free-gcp-resources]. 34 | 35 | --- 36 | 37 |
38 | 39 |
40 | 41 | Amazon Web Services 42 | 43 | 44 | 45 | --- 46 | 47 | ### AWS Available Resources 48 | 49 | - **2x** [Virtual Private Cloud (VPC)][aws-vpc-info] 50 | - **2x** [Sub-network][aws-sub-info] attached to the VPC 51 | - **2x** [Internet Gateway (IGW)][aws-igw-info] to provide access to the VPC 52 | - **1x** [Route Table][aws-route-info] integrating all `VPC`, `Subnet` and the `Internet Gateway (IGW)` 53 | - **1x** [EC2 Instance][aws-ec2-info] attached to the `Subnet` 54 | - **1x** [Relational Database (RDS)][aws-rds-info] of your choice (e.g. MySQL, PostgreSQL) 55 | - **1x** [S3 Storage Bucket][aws-s3-info] inside `Subnet`, configured to store the Terraform's backend state 56 | - **1x** [DynamoDB Database][aws-dynamodb-info], mainly used for preventing that running multiple instances of this Terraform chart corrupt each other. 57 | 58 | More information at the [provider's documentation page][tf-free-aws-resources]. 59 | 60 | --- 61 | 62 |
63 |
64 | 65 | 66 | Microsoft Azure (has limited testing) 67 | 68 | 69 | --- 70 | 71 | ### Available Resources 72 | 73 | - **1x** [Linux Virtual machine, B1S Standard tier][azure-vm-info] 74 | - **1x** [Windows Virtual machine, B1S Standard tier][azure-vm-info] 75 | - **1x** [Cloud Storage (LRS File Storage)][azure-storage-info] 76 | - **1x** [250GB MySQL Managed Database Instance][azure-sql-free-info] 77 | 78 | More information at the [provider's documentation page][tf-free-azure-resources]. 79 | 80 | --- 81 | 82 | ##
83 | 84 | 85 |
86 | 87 | 88 | Oracle Cloud (not available) 89 | 90 | 91 | --- 92 | 93 | ### Available Resources 94 | 95 | - **2x** [AMD based VM, 1/8 shared CPU and 1GB RAM][oracle-compute-info] 96 | - **2x** [Oracle NoSQL Database with 20GB][oracle-database-info] 97 | - **1x** [10GB Object Storage Capacity][oracle-storage-info] 98 | 99 | More information at the [provider's documentation page][tf-free-oracle-resources]. 100 | 101 | --- 102 | 103 |
104 | 105 | --- 106 | 107 | ## [❯ Getting started][getting-started] 108 | 109 | ```bash 110 | terraform init 111 | terraform apply 112 | ``` 113 | 114 | If you rather use a containerized environment: 115 | 116 | ```bash 117 | git clone https://github.com/gruberdev/tf-free.git && \ 118 | cd tf-free && \ 119 | docker run -v $(pwd):/project -it ghcr.io/gruberdev/freetf:latest 120 | ``` 121 | 122 |
123 | 124 | Terraform Module documentation (Click to expand) 125 | 126 | 127 | --- 128 | 129 | 130 | ### Modules 131 | 132 | | Name | Source | Version | 133 | |------|--------|---------| 134 | | aws | ./modules/aws | n/a | 135 | | google\_cloud | ./modules/gcp | n/a | 136 | | terraform\_state\_backend | cloudposse/tfstate-backend/aws | 0.38.1 | 137 | 138 | ### Inputs 139 | 140 | | Name | Description | Type | Default | 141 | |------|-------------|------|---------| 142 | | aws\_default\_region | Your default region for AWS resources creation. [Available regions for Google Compute on Free Tier.](https://free.terraform.gruber.dev.br/docs/resources/providers/aws#options) | `string` | `"us-east-1"` | 143 | | backend\_destroy | Allows destroying all resourcesinside the configured S3 Remote Backend. See more at [tf-free's Backend Documentation](https://free.terraform.gruber.dev.br/docs/setup/backend) | `string` | `"false"` | 144 | | backend\_stage | Stages possible for Backend. Set for a random string. | `string` | `"test"` | 145 | | ec2\_aws | Allow for the creation of EC2 instances on AWS. | `bool` | `true` | 146 | | gcp\_instance\_name | Your VM instance name. [Naming resources convention](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"gcp-machine"` | 147 | | gcp\_project\_id | Your static IP network nameP. [Naming resources convention](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"test"` | 148 | | gcp\_project\_region | Zone location of your instance, [see the list of available regions](https://cloud.google.com/compute/docs/regions-zones#available) - [Terraform provider documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#zone) | `string` | `"us-west1"` | 149 | | gcp\_storage\_permissions | See all available values for the parameter at [Predefined ACL's on GCS Permissions](https://cloud.google.com/storage/docs/access-control/lists#predefined-acl) | `string` | `"publicread"` | 150 | | prevents\_destroy | Prevents destroying the previously provisioned S3 Remote Backend. See more at [tf-free's Backend Documentation](https://free.terraform.gruber.dev.br/docs/setup/backend) | `bool` | `true` | 151 | | rds\_aws | Allow for the creation of a PostgreSQL database on AWS | `bool` | `true` | 152 | 153 | ### Outputs 154 | 155 | | Name | Description | 156 | |------|-------------| 157 | | aws\_ec2\_ipv6\_addresses | AWS EC2 IPv6 Public Address | 158 | | aws\_ec2\_password\_data | List of Base-64 encoded encrypted password data for AWS EC2 instances | 159 | | aws\_ec2\_private\_ip | AWS EC2 assigned Private IP | 160 | | aws\_ec2\_public\_ip | AWS EC2 IPv4 Public Address | 161 | | db\_backend\_name | Name of the resulting DynamoDB created for locking state files. | 162 | | gcp\_public\_ip | GCP VM Compute IPv4 Public Address | 163 | | s3\_backend\_bucket | ID of the resulting S3 bucket created on AWS as part of the backend infrastructure | 164 | | s3\_backend\_domain | Domain name of the S3 bucket created on AWS as part of the backend infrastructure | 165 | 166 | 167 |
168 | 169 | --- 170 | 171 | ## License 172 | 173 | The MIT license grant is not for Hashicorp's trademarks, which include the logo designs. [Hashicorp reserves all trademark and copyright rights in and to all Hashicorp trademarks][disclaimer]. 174 | 175 | This repository **is not** associated with any of the cloud providers or Hashicorp. Terraform®, Vault®, Hashicorp's logos and names are Hasicorp's registered Trademarks. When using Hashicorp's logos, be sure to follow their [community][guidelines] and [brand usage][brand] guidelines. 176 | Be sure to [read the terms][usage-terms] of usage to understand the responsabilities involved. 177 | 178 | 179 | 180 | [drone-img]: https://img.shields.io/drone/build/gruberdev/tf-free?server=https%3A%2F%2Fdrone.gruber.dev.br&logo=drone&labelColor=1F1F1F&logoColor=41dde8&style=flat-square&label=Drone%20CI 181 | [docs-img]: https://img.shields.io/badge/read%20available%20documentation-online?style=flat-square&logo=zeit&color=black 182 | 183 | 184 | 185 | [brand]: https://www.hashicorp.com/brand 186 | [disclaimer]: https://www.hashicorp.com/trademark-policy 187 | [guidelines]: https://www.hashicorp.com/community-guidelines 188 | [free-aws]: https://aws.amazon.com/free/?all-free-tier 189 | [free-gcp]: https://cloud.google.com/free 190 | [kis-approach]: https://en.wikipedia.org/wiki/KISS_principle 191 | [free-docs-gcp]: https://cloud.google.com/free/docs/gcp-free-tier 192 | [free-azure]: https://azure.microsoft.com/en-us/free/ 193 | [azure-faq]: https://azure.microsoft.com/en-us/free/free-account-faq/ 194 | [usage-terms]: https://free.terraform.gruber.dev.br/docs/resources/providers/gcp#resources 195 | [azure-full-terms]: https://azure.microsoft.com/en-us/offers/ms-azr-0044p/ 196 | [aws-faq]: https://aws.amazon.com/free/free-tier-faqs/ 197 | [docs-repo-url]: https://github.com/CONNECT-platform/codedoc 198 | [aws-key-info]: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys 199 | [aws-key-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/ 200 | [aws-account-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/ 201 | [aws-vpc-info]: https://aws.amazon.com/vpc/?vpc-blogs.sort-by=item.additionalFields.createdDate&vpc-blogs.sort-order=desc 202 | [aws-igw-info]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html 203 | [aws-ec2-info]: https://aws.amazon.com/ec2/ 204 | [aws-s3-info]: https://aws.amazon.com/s3/ 205 | [aws-rds-info]: https://aws.amazon.com/rds/ 206 | [aws-sub-info]: https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html 207 | [aws-tf-provider]: https://registry.terraform.io/providers/hashicorp/aws/latest/ 208 | [aws-regions]: https://aws.amazon.com/about-aws/global-infrastructure/ 209 | [aws-terms]: https://aws.amazon.com/free/terms/ 210 | [aws-prevent-charges]: https://aws.amazon.com/premiumsupport/knowledge-center/free-tier-charges/ 211 | [aws-alarms-free]: https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/tracking-free-tier-usage.html#free-budget 212 | [aws-sorted-list]: https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=tier%23always-free%7Ctier%2312monthsfree&awsf.Free%20Tier%20Categories=*all 213 | [aws-dynamodb-info]: https://aws.amazon.com/dynamodb/ 214 | [remote-tfstate-url]: https://github.com/cloudposse/terraform-aws-tfstate-backend 215 | [tf-free-docs-cli]: https://free.terraform.gruber.dev.br/docs/setup/installing#cli 216 | [tf-free-gcp-resources]: https://free.terraform.gruber.dev.br/docs/resources/providers/gcp#resources 217 | [tf-free-aws-resources]: https://free.terraform.gruber.dev.br/docs/resources/providers/aws#resources 218 | [tf-free-azure-resources]: https://free.terraform.gruber.dev.br/docs/resources/providers/azure#resources 219 | [guidelines]: https://www.hashicorp.com/community-guidelines 220 | [free-gcp]: https://cloud.google.com/free 221 | [free-docs-gcp]: https://cloud.google.com/free/docs/gcp-free-tier 222 | [free-tier-limits]: https://cloud.google.com/free/docs/gcp-free-tier/#free-tier-usage-limits 223 | [free-tier-restrictions]: https://cloud.google.com/free/docs/gcp-free-tier/#free-tier 224 | [google-free-docs]: https://cloud.google.com/free/docs/gcp-free-tier/ 225 | [google-free-landing]: https://cloud.google.com/free 226 | [unique-gcp-docs]: https://cloud.google.com/free/docs/what-makes-google-cloud-platform-different 227 | [why-google]: https://cloud.google.com/why-google-cloud 228 | [gcp-price-list]: https://cloud.google.com/pricing/list 229 | [gcp-comparison-docs]: https://cloud.google.com/free/docs/aws-azure-gcp-service-comparison 230 | [pricing-gcp-calculator]: https://cloud.google.com/products/calculator 231 | [no-free-ip]: https://cloud.google.com/free/docs/gcp-free-tier#always-free-usage-limits 232 | [pricing-egress]: https://cloud.google.com/vpc/network-pricing#internet_egress 233 | [usage-egress-gcp]: https://cloud.google.com/vpc/network-pricing#vpc-pricing 234 | [gcp-compute-info]: https://cloud.google.com/compute/docs 235 | [gcp-shared-vcpus]: https://cloud.google.com/compute/vm-instance-pricing#cpu-bursting 236 | [gcp-cloud-storage]: https://cloud.google.com/storage 237 | [gcp-vpc-info]: https://cloud.google.com/storage 238 | [gcp-firewall-info]: https://cloud.google.com/storage 239 | [gcp-regional-storage]: https://cloud.google.com/storage/docs/storage-classes#legacy 240 | [gcp-firestore-storage]: https://cloud.google.com/firestore/docs 241 | [gcp-regions]: https://cloud.google.com/compute/docs/regions-zones 242 | [brand]: https://www.hashicorp.com/brand 243 | [disclaimer]: https://www.hashicorp.com/trademark-policy 244 | [guidelines]: https://www.hashicorp.com/community-guidelines 245 | [free-aws]: https://aws.amazon.com/free/?all-free-tier 246 | [free-gcp]: https://cloud.google.com/free 247 | [free-docs-gcp]: https://cloud.google.com/free/docs/gcp-free-tier 248 | [free-azure]: https://azure.microsoft.com/en-us/free/ 249 | [azure-faq]: https://azure.microsoft.com/en-us/free/free-account-faq/ 250 | [azure-full-terms]: https://azure.microsoft.com/en-us/offers/ms-azr-0044p/ 251 | [aws-faq]: https://aws.amazon.com/free/free-tier-faqs/ 252 | [go-color-url]: https://github.com/fatih/color 253 | [go-releaser-url]: https://github.com/goreleaser/goreleaser 254 | [go-cobra-url]: https://github.com/spf13/cobra 255 | [shell-has-url]: https://github.com/kdabir/has 256 | [go-prompt-url]: https://github.com/c-bata/go-prompt 257 | [go-task-url]: https://github.com/go-task/task 258 | [go-tfexec-url]: https://github.com/hashicorp/terraform-exec 259 | [docs-repo-url]: https://github.com/CONNECT-platform/codedoc 260 | [aws-key-info]: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys 261 | [aws-key-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/ 262 | [aws-account-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/ 263 | [aws-vpc-info]: https://aws.amazon.com/vpc/?vpc-blogs.sort-by=item.additionalFields.createdDate&vpc-blogs.sort-order=desc 264 | [aws-igw-info]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html 265 | [aws-ec2-info]: https://aws.amazon.com/ec2/ 266 | [aws-s3-info]: https://aws.amazon.com/s3/ 267 | [aws-rds-info]: https://aws.amazon.com/rds/ 268 | [aws-route-info]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Route_Tables.html 269 | [aws-sub-info]: https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html 270 | [aws-tf-provider]: https://registry.terraform.io/providers/hashicorp/aws/latest/ 271 | [aws-regions]: https://aws.amazon.com/about-aws/global-infrastructure/ 272 | [aws-terms]: https://aws.amazon.com/free/terms/ 273 | [aws-prevent-charges]: https://aws.amazon.com/premiumsupport/knowledge-center/free-tier-charges/ 274 | [aws-alarms-free]: https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/tracking-free-tier-usage.html#free-budget 275 | [aws-sorted-list]: https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=tier%23always-free%7Ctier%2312monthsfree&awsf.Free%20Tier%20Categories=*all 276 | [aws-dynamodb-info]: https://aws.amazon.com/dynamodb/ 277 | [remote-tfstate-url]: https://github.com/cloudposse/terraform-aws-tfstate-backend 278 | [azure-sql-free-info]: https://azure.microsoft.com/en-us/products/azure-sql/database/ 279 | [azure-vm-info]: https://azure.microsoft.com/en-us/services/virtual-machines/ 280 | [azure-storage-info]: https://azure.microsoft.com/en-us/services/storage/files/ 281 | [oracle-compute-info]: https://www.oracle.com/cloud/compute/ 282 | [oracle-database-info]: https://www.oracle.com/database/ 283 | [oracle-storage-info]: https://www.oracle.com/cloud/storage/ 284 | [tf-free-oracle-resources]: https://free.terraform.gruber.dev.br/docs/resources/providers/oracle#resources 285 | [tf-free-oracle-resources]: https://free.terraform.gruber.dev.br/docs/resources/providers/oracle#resources 286 | [project-taskfile]: https://github.com/gruberdev/tf-free/blob/main/Taskfile.yml 287 | [taskfile-website]: https://taskfile.dev 288 | [getting-started]: https://free.terraform.gruber.dev.br/docs/setup/getting-started -------------------------------------------------------------------------------- /Taskfile.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | includes: 4 | clean: ./tasks/clean.yaml 5 | aws: ./tasks/aws.yaml 6 | gcp: ./tasks/gcp.yaml 7 | 8 | tasks: 9 | docker:oneliner: 10 | deps: 11 | - docker-init 12 | - build 13 | - docker 14 | cmds: 15 | - "Loading container..." 16 | 17 | docker:init: 18 | desc: Create and cache your Docker container 19 | cmds: 20 | - docker volume rm cache_terraform || true 21 | - docker volume rm repository_results || true 22 | - docker volume create cache_terraform || true 23 | - docker volume create repository_results || true 24 | 25 | docker: 26 | desc: Create and cache your Docker container 27 | deps: 28 | - build 29 | cmds: 30 | - docker run -it --rm --name freetf freetf:latest 31 | 32 | build: 33 | desc: Create and cache your Docker container 34 | cmds: 35 | - docker build -t ghcr.io/gruberdev/freetf:latest -t docker.io/grubertech/freetf:latest --no-cache . 36 | 37 | run: 38 | cmds: 39 | - docker run -v $(pwd):/project -it ghcr.io/gruberdev/freetf:latest /bin/sh 40 | 41 | build:all: 42 | desc: Build executable binary with GoReleaser. 43 | cmds: 44 | - goreleaser --snapshot --skip-publish --rm-dist 45 | 46 | docs:gen: 47 | preconditions: 48 | - sh: 'which terraform-docs' 49 | msg: 'terraform-docs {{.PATH_ERROR}}' 50 | desc: Build documentation using Terraform-docs and the task command 51 | cmds: 52 | - terraform-docs markdown -c .terraform-docs.yml . --output-file README.md 53 | - terraform-docs markdown -c .terraform-docs.yml ./modules/aws --output-file README.md --header-from "header.md" 54 | - terraform-docs markdown -c .terraform-docs.yml ./modules/aws/ec2 --output-file README.md 55 | - terraform-docs markdown -c .terraform-docs.yml ./modules/aws/vpc --output-file README.md 56 | - terraform-docs markdown -c .terraform-docs.yml ./modules/aws/rds --output-file README.md 57 | - terraform-docs markdown -c .terraform-docs.yml ./modules/gcp --output-file README.md 58 | - terraform-docs markdown -c .terraform-docs.yml ./modules/gcp/compute --output-file README.md 59 | - terraform-docs markdown -c .terraform-docs.yml ./modules/gcp/firewall --output-file README.md 60 | - terraform-docs markdown -c .terraform-docs.yml ./modules/gcp/vpc --output-file README.md 61 | - terraform-docs markdown -c .terraform-docs.yml ./modules/azure --output-file README.md 62 | - terraform-docs markdown -c .terraform-docs.yml ./modules/azure/compute --output-file README.md 63 | - terraform-docs markdown -c .terraform-docs.yml ./modules/azure/db --output-file README.md 64 | - terraform-docs markdown -c .terraform-docs.yml ./modules/azure/vpc --output-file README.md 65 | - terraform-docs markdown -c .terraform-docs.yml ./modules/gcp/storage --output-file README.md 66 | - terraform-docs markdown -c .terraform-docs.yml ./examples/aws/e2e --output-file README.md 67 | - terraform-docs markdown -c .terraform-docs.yml ./examples/aws/unit/rds --output-file README.md 68 | - terraform-docs markdown -c .terraform-docs.yml ./examples/aws/unit/ec2 --output-file README.md 69 | 70 | docs: 71 | desc: Initialize module and build cache, and remake go.sum file on root directory. 72 | deps: 73 | - stop-docs 74 | cmds: 75 | - cd docs && docker build -t tf-free:docs . 76 | - cd docs && docker-compose up --build -d 77 | 78 | docs-deploy: 79 | desc: Initialize module and build cache, and remake go.sum file on root directory. 80 | deps: 81 | - stop-docs 82 | cmds: 83 | - cd docs && docker build -t tf-free:docs . 84 | - cd docs && docker-compose -f build.yml up --build 85 | - cd docs && rm -rf .public || true 86 | - cd docs && mkdir .public 87 | - cp -r docs/build/* docs/.public/ 88 | - cp docs/vercel.json docs/.public/ 89 | 90 | stop-docs: 91 | cmds: 92 | - cd docs && docker-compose down || true 93 | - cd docs && docker-compose -f build.yml down || true 94 | 95 | lint: 96 | desc: Linter built on Docker. 97 | cmds: 98 | - go mod verify 99 | - docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.40.1 golangci-lint run --enable gosec --timeout 3m0s ./... 100 | sources: 101 | - ./go.mod 102 | - "**/*.go" 103 | 104 | graph: 105 | desc: Create beautiful Terraform Graphs 106 | cmds: 107 | - go get github.com/pcasteran/terraform-graph-beautifier 108 | - terraform graph | terraform-graph-beautifier --exclude="module.root.provider" --output-type=cyto-html > graph.html 109 | 110 | full:test:local: 111 | desc: Terraform testing all providers. 112 | deps: 113 | - gcp-test 114 | - aws-test 115 | - docker-test 116 | cmds: 117 | - echo "Finished testing." 118 | 119 | apply:local: 120 | desc: Terraform standard local apply command 121 | cmds: 122 | - terraform init 123 | - terraform apply -auto-approve 124 | 125 | destroy:local: 126 | desc: Terraform standard local destroy command 127 | cmds: 128 | - terraform destroy -auto-approve 129 | 130 | init: 131 | desc: Terraform standard local init command 132 | cmds: 133 | - terraform init -upgrade 134 | 135 | init:apply: 136 | desc: Terraform standard initial apply command (w/ Backend) 137 | cmds: 138 | - terraform init -reconfigure 139 | - terraform apply -auto-approve 140 | - terraform init -force-copy 141 | 142 | init:docker: 143 | cmds: 144 | - cd test/docker && rm go.mod || true 145 | - cd test/docker && rm go.sum || true 146 | - cd test/docker && go mod init "github.com/gruberdev/tf-free" && go mod tidy 147 | 148 | docker:test: 149 | desc: Terraform standard initialization 150 | deps: 151 | - init-docker 152 | cmds: 153 | - cd test/docker && go test -v -timeout 45m -run TestDockerBuild 154 | 155 | lastdestroy: 156 | desc: Terraform standard initialization 157 | cmds: 158 | - terraform apply -var backend_destroy=true -var prevents_destroy=false -target module.terraform_state_backend -auto-approve 159 | - terraform init -force-copy 160 | - terraform destroy -target module.aws.module.rds.aws_db_instance.rds -auto-approve 161 | - terraform destroy -auto-approve 162 | 163 | docker:lint: 164 | desc: Terraform standard initialization 165 | cmds: 166 | - docker run --rm -i hadolint/hadolint < Dockerfile || true 167 | 168 | backend:enable: 169 | desc: How to transfer the backend to S3 (Remote) 170 | cmds: 171 | - terraform init -force-copy 172 | 173 | backend:disable: 174 | desc: How to destroy the backend stored in S3 175 | cmds: 176 | - terraform apply -target module.terraform_state_backend -auto-approve 177 | - terraform init -force-copy 178 | 179 | destroy:aws: 180 | desc: Terraform standard initialization 181 | cmds: 182 | - cd modules/aws && terraform destroy -auto-approve 183 | 184 | restart-aws: 185 | desc: Terraform standard initialization 186 | cmds: 187 | - cd modules/aws && terraform destroy -auto-approve 188 | - cd modules/aws && terraform apply -auto-approve 189 | 190 | heavy:artillery: 191 | desc: Destroy all resources but the S3 Backend and the DynamoDB instances on AWS. 192 | cmds: 193 | - terraform destroy -target module.google_cloud -auto-approve 194 | - terraform destroy -target module.aws -auto-approve 195 | 196 | tf:clean: 197 | desc: Terraform standard initialization 198 | cmds: 199 | - rm -rf ./.terraform || true 200 | - rm -rf ./.blast || true 201 | - rm terraform.tfstate || true 202 | - rm terraform.tfstate.backup || true 203 | - rm ./.terraform.lock.hcl || true 204 | - rm backend.tf || true 205 | - rm errored.tfstate || true 206 | - rm graph.html || true 207 | - rm index.html || true 208 | - rm plan.json || true 209 | - rm plan.out || true 210 | - rm gcp.json || true 211 | - cd modules && cd gcp && rm -rf ./.terraform && rm ./.terraform.lock.hcl || true 212 | - cd modules && cd gcp && cd vpc && rm -rf ./.terraform && rm ./.terraform.lock.hcl || true 213 | - cd modules && cd gcp && cd firewall && rm -rf ./.terraform && rm ./.terraform.lock.hcl || true 214 | - cd modules && cd gcp && cd compute && rm -rf ./.terraform && rm ./.terraform.lock.hcl || true 215 | - cd modules && cd aws && rm -rf ./.terraform && rm ./.terraform.lock.hcl || true 216 | - cd modules && cd aws && cd ec2 && rm -rf ./.terraform && rm ./.terraform.lock.hcl || true 217 | - cd modules && cd aws && cd rds && rm -rf ./.terraform && rm ./.terraform.lock.hcl || true 218 | - rm examples/aws/unit/ec2/.terraform.lock.hcl || true 219 | - rm -rf examples/aws/unit/ec2/.terraform || true 220 | - rm examples/aws/unit/ec2/terraform.tfstate || true 221 | - rm examples/aws/unit/ec2/terraform.tfstate.backup || true 222 | - rm examples/aws/unit/rds/.terraform.lock.hcl || true 223 | - rm -rf examples/aws/unit/rds/.terraform || true 224 | - rm examples/aws/unit/rds/terraform.tfstate || true 225 | - rm examples/aws/unit/rds/terraform.tfstate.backup || true 226 | 227 | drone:init: 228 | desc: Terraform standard initialization 229 | cmds: 230 | - apk add build-base git curl 231 | - apk add --no-cache terraform --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community 232 | 233 | blastradius: 234 | cmds: 235 | - docker run --rm -it -p 5013:5000 -v $(pwd):/data:ro -v $(pwd)/blast:/tmp/results --security-opt apparmor:unconfined --cap-add=SYS_ADMIN blastradius:local 236 | -------------------------------------------------------------------------------- /assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/assets/.gitkeep -------------------------------------------------------------------------------- /config/aws-filter.yaml: -------------------------------------------------------------------------------- 1 | aws_security_group: 2 | aws_iam_role: 3 | aws_instance: 4 | aws_ec2_transit_gateway_peering_attachment: 5 | aws_ec2_transit_gateway_route_table: 6 | aws_vpc: 7 | aws_subnet: 8 | aws_route_table: 9 | aws_vpc_peering_connection: 10 | aws_db_instance: 11 | aws_rds_cluster: 12 | aws_s3_bucket: 13 | -------------------------------------------------------------------------------- /config/gcp-filter.yaml: -------------------------------------------------------------------------------- 1 | compute.googleapis.com/Firewall: 2 | regex: ^default-.* 3 | listThese: false 4 | compute.googleapis.com/Subnetwork: 5 | regex: ^default.* 6 | listThese: false 7 | appengine.googleapis.com/Version: 8 | appengine.googleapis.com/Service: 9 | cloudfunctions.googleapis.com/CloudFunction: 10 | compute.googleapis.com/Address: 11 | compute.googleapis.com/Disk: 12 | compute.googleapis.com/BackendBucket: 13 | compute.googleapis.com/BackendService: 14 | compute.googleapis.com/ForwardingRule: 15 | compute.googleapis.com/GlobalForwardingRule: 16 | compute.googleapis.com/HealthCheck: 17 | compute.googleapis.com/Instance: 18 | compute.googleapis.com/TargetHttpProxy: 19 | compute.googleapis.com/TargetHttpsProxy: 20 | compute.googleapis.com/UrlMap: 21 | container.googleapis.com/Cluster: 22 | pubsub.googleapis.com/Subscription: 23 | pubsub.googleapis.com/Topic: 24 | storage.googleapis.com/Bucket: 25 | logging.googleapis.com/LogMetric: 26 | run.googleapis.com/Service: 27 | sqladmin.googleapis.com/Instance: 28 | -------------------------------------------------------------------------------- /docs/.dockerignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | *.tfstate 4 | *.tfstate.* 5 | crash.log 6 | override.tf 7 | override.tf.json 8 | *_override.tf 9 | *_override.tf.json 10 | **/.terraform.lock.hcl/* 11 | .terraform.lock.hcl 12 | *tfplan* 13 | gcp.json 14 | terraform.tfvars 15 | **/gcp.json/* 16 | graph.json 17 | graph.svg 18 | go.sum 19 | go.mod 20 | test/go.sum 21 | test/go.mod 22 | 23 | # Documentation / Node.js 24 | docs/dist/* 25 | docs/*.html 26 | logs 27 | *.log 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | lerna-debug.log* 32 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 33 | pids 34 | *.pid 35 | *.seed 36 | *.pid.lock 37 | lib-cov 38 | coverage 39 | *.lcov 40 | .nyc_output 41 | .grunt 42 | bower_components 43 | .lock-wscript 44 | build/Release 45 | node_modules/ 46 | jspm_packages/ 47 | typings/ 48 | *.tsbuildinfo 49 | .npm 50 | .eslintcache 51 | .rpt2_cache/ 52 | .rts2_cache_cjs/ 53 | .rts2_cache_es/ 54 | .rts2_cache_umd/ 55 | .node_repl_history 56 | *.tgz 57 | .yarn-integrity 58 | .env 59 | .env.test 60 | .cache 61 | index.html 62 | .next 63 | .nuxt 64 | dist 65 | .cache/ 66 | .vuepress/dist 67 | .serverless/ 68 | .fusebox/ 69 | .dynamodb/ 70 | .tern-port 71 | 72 | # Docker 73 | 74 | # .vscode 75 | .vscode 76 | renovate.json 77 | -------------------------------------------------------------------------------- /docs/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Start from Node 3 | # 4 | FROM node:17.4 5 | 6 | # 7 | # Install CODEDOC CLI (https://codedoc.cc/docs/cli) 8 | # 9 | RUN npm install -g @codedoc/cli 10 | 11 | # 12 | # Create the main Docs folder 13 | # 14 | # This folder should be mounted with the root repo folder, 15 | # but do not forget to exclude `.codedoc/node_modules` from that volume! 16 | # 17 | RUN mkdir -p /home/docs 18 | WORKDIR /home/docs 19 | 20 | # 21 | # Install and serve locally 22 | # 23 | CMD codedoc install && codedoc serve -------------------------------------------------------------------------------- /docs/build.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | docs: 4 | build: . 5 | ports: 6 | - 3000:3000 7 | # Volume root folder on `/home/blog`, 8 | # but exclude `/home/blog/.codedoc/node_modules" (since the container env should install its own modules). 9 | # 10 | volumes: 11 | - "..:/home/docs" 12 | - "/home/docs/.codedoc/node_modules/" 13 | command: codedoc install && codedoc build 14 | -------------------------------------------------------------------------------- /docs/build/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/build/.gitkeep -------------------------------------------------------------------------------- /docs/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | docs: 4 | build: . 5 | ports: 6 | - 3000:3000 7 | # Volume root folder on `/home/blog`, 8 | # but exclude `/home/blog/.codedoc/node_modules" (since the container env should install its own modules). 9 | # 10 | volumes: 11 | - "..:/home/docs" 12 | - "/home/docs/.codedoc/node_modules/" 13 | -------------------------------------------------------------------------------- /docs/md/404.md: -------------------------------------------------------------------------------- 1 | # 404 Error 2 | 3 | ### This page has not been found 4 | 5 | Please be advised of unknown paths ahead, [head back home here](/). 6 | -------------------------------------------------------------------------------- /docs/md/_toc.md: -------------------------------------------------------------------------------- 1 | [Home](/) 2 | 3 | [Getting started](/docs/setup/getting-started) 4 | 5 | > :Collapse label="Project Configuration" 6 | > 7 | > [Installing tools](/docs/setup/installing) 8 | > 9 | > [Environment setup](/docs/setup/environment) 10 | > 11 | > [First time running](/docs/setup/first-run) 12 | > 13 | > [Managing existent resources](/docs/setup/management) 14 | 15 | > :Collapse label=Cloud Providers 16 | > 17 | > [Overview](/docs/references) 18 | > 19 | > [Google Cloud Platform](/docs/providers/gcloud) 20 | > 21 | > [Amazon Web Services](/docs/providers/amznaws) 22 | > 23 | > [Microsoft Azure](/docs/providers/msazure) 24 | > 25 | > [Oracle Cloud](/docs/providers/oracle) 26 | 27 | > :Collapse label="About" 28 | > 29 | > [What is this project?](/docs/intro/what-is) 30 | > 31 | > [Whose was it made for?](/docs/intro/about) 32 | > 33 | > [Acknowledgments](/docs/intro/thanks) 34 | > 35 | > [Terms of use](/docs/intro/terms) 36 | > 37 | > [How can I contribute?](/docs/intro/contributions) 38 | > 39 | > [Copyright & Trademark](/docs/intro/legal) 40 | 41 | > :Collapse label="Development" 42 | > 43 | > [Repository Guidelines](/docs/development/guidelines) 44 | > 45 | > [Roadmap](/docs/development/roadmap) 46 | > 47 | > [Running tests](/docs/development/tests) 48 | > 49 | > [Pull Requests](/docs/development/prs) 50 | > 51 | > [Providing Feedback](/docs/development/contact) 52 | 53 |

54 | -------------------------------------------------------------------------------- /docs/md/docs/code-features.md: -------------------------------------------------------------------------------- 1 | # Code Features 2 | 3 | This is a quick overview of codedoc specific features at your disposal in markdown 4 | `code` elements. For a complete list, please checkout the [official documentation](https://codedoc.cc). 5 | You can also take a look at `docs/md/docs/code-features.md` to see the markdown behind this page. 6 | 7 | > :Buttons 8 | > > :Button label=Official Docs, url=https://codedoc.cc 9 | 10 |
11 | 12 | > ⚠️⚠️ 13 | > Do not forget to **REMOVE THIS PAGE** from your actual documentation! 14 | > ⚠️⚠️ 15 | 16 |
17 | 18 | ## Hints 19 | 20 | A comment with the following format will cause a hint to be displayed on-hover: 21 | 22 | > `// --> some hint here` 23 | 24 | ```tsx | index.tsx 25 | import { Renderer } from '@connectv/html'; // --> there is a hint on this line 26 | 27 | const MyComp = ({ name }, renderer) =>
Hellow {name}!
// --> there is also a hint on this line 28 | 29 | const renderer = new Renderer(); 30 | renderer.render( 31 | 32 | 33 | {/* --> also this is a hint */} 34 | 35 | ) 36 | .on(document.body); 37 | ``` 38 | 39 |
40 | 41 | The following syntax styles are supported: 42 | 43 | 44 | ```go 45 | "// --> standard one-liner" // --> standard one-liner 46 | ``` 47 | 48 | ```java 49 | "/* --> standard multi-liner */" /* --> standard multi-liner */ 50 | ``` 51 | 52 | ```py 53 | "# --> python/bash comments" # --> python/bash comments 54 | ``` 55 | 56 | ```md 57 | <‌!--> html comments --> html comments --> 58 | ``` 59 | 60 | 61 |
62 | 63 | ## References 64 | 65 | Add a comment with following format in the code will show a link on-hover over the line: 66 | 67 | > `// @see https://www.google.com` 68 | 69 | ```tsx 70 | import { Renderer } from '@connectv/html'; // @see https://github.com/CONNECT-platform/connective-html 71 | ``` 72 | 73 | You can also use the markdown link format to give your links a title: 74 | 75 | ````md | --no-wmbar 76 | ``` 77 | import { Renderer } from '@connectv/html'; // @see [CONNECTIVE HTML Docs](https://github.com/CONNECT-platform/connective-html) 78 | ``` 79 | ```` 80 | ```tsx 81 | import { Renderer } from '@connectv/html'; // @see [CONNECTIVE HTML Docs](https://github.com/CONNECT-platform/connective-html) 82 | ``` 83 | 84 | You can also use these references to refer to another tab in a tab-component: 85 | 86 | ```md | some-doc.md 87 | > :Tabs 88 | > > :Tab title=First Tab 89 | > > 90 | > > ```tsx 91 | > > import { func } from './other'; // @see tab:Second Tab 92 | > > 93 | > > func(); // --> good stuff will happen now 94 | > > ``` 95 | > 96 | > > :Tab title=Second Tab 97 | > > 98 | > > ```tsx 99 | > > export function func() { 100 | > > console.log('Good Stuff!'); 101 | > > } 102 | > > ``` 103 | ``` 104 |
105 | 106 | > :Tabs 107 | > > :Tab title=First Tab 108 | > > 109 | > > ```tsx 110 | > > import { func } from './other'; // @see tab:Second Tab 111 | > > 112 | > > func(); // --> good stuff will happen now 113 | > > ``` 114 | > 115 | > > :Tab title=Second Tab 116 | > > 117 | > > ```tsx 118 | > > export function func() { 119 | > > console.log('Good Stuff!'); 120 | > > } 121 | > > ``` 122 | 123 | Similar syntax styles to hints are supported for references as well: 124 | 125 | 126 | ```js 127 | "// @‌see [random stuff](https://www.randomlists.com/things)" // @see [random stuff](https://www.randomlists.com/things) 128 | ``` 129 | 130 | ```go 131 | "/* @‌see https://google.com */" /* @see https://google.com */ 132 | ``` 133 | 134 | ```python 135 | "#@see https://github.com" #@see https://github.com 136 | ``` 137 | 138 | ```html 139 | 140 | ``` 141 | 142 | 143 | > :ToCPrevNext -------------------------------------------------------------------------------- /docs/md/docs/development/contact.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/development/contact.md -------------------------------------------------------------------------------- /docs/md/docs/development/contributions.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/development/contributions.md -------------------------------------------------------------------------------- /docs/md/docs/development/guidelines.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/development/guidelines.md -------------------------------------------------------------------------------- /docs/md/docs/development/prs.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/development/prs.md -------------------------------------------------------------------------------- /docs/md/docs/development/roadmap.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/development/roadmap.md -------------------------------------------------------------------------------- /docs/md/docs/development/tests.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/development/tests.md -------------------------------------------------------------------------------- /docs/md/docs/intro/about.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/intro/about.md -------------------------------------------------------------------------------- /docs/md/docs/intro/legal.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/intro/legal.md -------------------------------------------------------------------------------- /docs/md/docs/intro/next-steps.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/intro/next-steps.md -------------------------------------------------------------------------------- /docs/md/docs/intro/terms.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/intro/terms.md -------------------------------------------------------------------------------- /docs/md/docs/intro/thanks.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/intro/thanks.md -------------------------------------------------------------------------------- /docs/md/docs/intro/what-is.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/intro/what-is.md -------------------------------------------------------------------------------- /docs/md/docs/providers/amnzaws.md: -------------------------------------------------------------------------------- 1 | # Amazon AWS 2 | 3 | ## Resources 4 | 5 | - **1x** [Virtual Private Cloud (VPC)](aws-vpc-info) 6 | - **1x** [Sub-network](aws-sub-info) attached to the VPC 7 | - **1x** [Internet Gateway (IGW)](aws-igw-info) to provide access to the VPC 8 | - **1x** [Route Table](aws-route-info) integrating all `VPC`, `Subnet` and the `Internet Gateway (IGW)` 9 | - **1x** [EC2 Instance](aws-ec2-info) attached to the `Subnet` 10 | - **1x** [Relational Database (RDS)](aws-rds-info) of your choice (e.g. MySQL, PostgreSQL) 11 | - **1x** [S3 Storage Bucket](aws-s3-info) inside `Subnet`, configured to store the Terraform's backend state 12 | - **1x** [DynamoDB Database](aws-dynamodb-info), mainly used for preventing that running multiple instances of this Terraform chart corrupt each other. 13 | 14 | #### Terms & Conditions for resource usage 15 | 16 | - Some resources are **only valid for 12 months** and not forever. Please [check the list of resources](aws-sorted-list) to verify each resource maximum usage within the Free-Tier plan. 17 | - EC2 Machines and RDS Databases are limited to `t3.micro` and `db.t2.micro` types respectively. 18 | - AWS provides the free-tier resource usage for all their [global regions](aws-regions) except China (Beijing). 19 | #### Requirements 20 | 21 | - **An active account on AWS** | See: \_[Getting started on AWS](aws-account-create) 22 | - **[Valid Access keys to AWS Account](aws-keys-info)** | See: _[Generating your access keys](aws-keys-create)_ 23 | 24 | ## Options 25 | 26 | ### Examples 27 | 28 | ### References 29 | 30 | - [AWS Free-Tier FAQ](aws-faq) 31 | - [AWS Free-Tier Homepage](free-aws) 32 | - [How to set alarms for your Free-Tier account](aws-alarms-free) 33 | - [Terraform AWS Official Provider Documentation](aws-tf-provider) 34 | - [How to prevent charges on your Free-Tier account](aws-prevent-charges) 35 | - [Extended terms and conditions](aws-terms) 36 | 37 | 38 | 39 | [brand]: https://www.hashicorp.com/brand 40 | [disclaimer]: https://www.hashicorp.com/trademark-policy 41 | [guidelines]: https://www.hashicorp.com/community-guidelines 42 | [free-aws]: https://aws.amazon.com/free/?all-free-tier 43 | [free-gcp]: https://cloud.google.com/free 44 | [free-docs-gcp]: https://cloud.google.com/free/docs/gcp-free-tier 45 | [free-azure]: https://azure.microsoft.com/en-us/free/ 46 | [azure-faq]: https://azure.microsoft.com/en-us/free/free-account-faq/ 47 | [azure-full-terms]: https://azure.microsoft.com/en-us/offers/ms-azr-0044p/ 48 | [aws-faq]: https://aws.amazon.com/free/free-tier-faqs/ 49 | [go-color-url]: https://github.com/fatih/color 50 | [go-releaser-url]: https://github.com/goreleaser/goreleaser 51 | [go-cobra-url]: https://github.com/spf13/cobra 52 | [shell-has-url]: https://github.com/kdabir/has 53 | [go-prompt-url]: https://github.com/c-bata/go-prompt 54 | [go-task-url]: https://github.com/go-task/task 55 | [go-tfexec-url]: https://github.com/hashicorp/terraform-exec 56 | [docs-repo-url]: https://github.com/CONNECT-platform/codedoc 57 | [aws-key-info]: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys 58 | [aws-key-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/ 59 | [aws-account-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/ 60 | [aws-vpc-info]: https://aws.amazon.com/vpc/?vpc-blogs.sort-by=item.additionalFields.createdDate&vpc-blogs.sort-order=desc 61 | [aws-igw-info]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html 62 | [aws-ec2-info]: https://aws.amazon.com/ec2/ 63 | [aws-s3-info]: https://aws.amazon.com/s3/ 64 | [aws-rds-info]: https://aws.amazon.com/rds/ 65 | [aws-route-info]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Route_Tables.html 66 | [aws-sub-info]: https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html 67 | [aws-tf-provider]: https://registry.terraform.io/providers/hashicorp/aws/latest/ 68 | [aws-regions]: https://aws.amazon.com/about-aws/global-infrastructure/ 69 | [aws-terms]: https://aws.amazon.com/free/terms/ 70 | [aws-prevent-charges]: https://aws.amazon.com/premiumsupport/knowledge-center/free-tier-charges/ 71 | [aws-alarms-free]: https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/tracking-free-tier-usage.html#free-budget 72 | [aws-sorted-list]: https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=tier%23always-free%7Ctier%2312monthsfree&awsf.Free%20Tier%20Categories=*all 73 | [aws-dynamodb-info]: https://aws.amazon.com/dynamodb/ 74 | [remote-tfstate-url]: https://github.com/cloudposse/terraform-aws-tfstate-backend 75 | -------------------------------------------------------------------------------- /docs/md/docs/providers/gcloud.md: -------------------------------------------------------------------------------- 1 | # Google Cloud Platform 2 | 3 | > :Tabs 4 | > 5 | > > :Tab title=Available resources 6 | > > 7 | > > - **1x** Virtual Private Cloud [VPC][gcp-vpc-info] 8 | > > - **1x** [Firewall][gcp-firewall-info] attached to the VPC 9 | > > - **1x** [Google Compute Engine][gcp-compute-info] `f1-micro` ([1 shared vCPU - 0.2 dedicatd vCPU][gcp-shared-vcpus] - and 0.6GB of Memory) attached to the `VPC` 10 | > > - **1x** 5GB of [regional storage][gcp-regional-storage] on [Cloud Storage][gcp-cloud-storage] 11 | > > - **1x** 1GB of storage in a [Firestore NoSQL Database][gcp-firestore-storage] 12 | > 13 | > > :Tab title=Terms & Conditions 14 | > > 15 | > > - [Compute Engine Instances ( `f1-micro` ) do not have an external **static** IP address on the free tier][no-free-ip] 16 | > > - You're (as a Free-Tier only) limited to 3 US-based exclusive [zones/regions][gcp-regions] for provisioning your instance. (`us-east1`, `us-west1`, and `us-central1`) 17 | > > - Cloud Storage follows similar rules to the Compute Engine terms, but is also limited to 5,000 Class A operations per month and 50,000 Class B operations per monnth maximum. 18 | > > 19 | > > _Reference:_ [Table of Free-Tier limits][free-tier-limits] 20 | > > 21 | > > - You're limited to 1GB of Egress (outgoing) traffic from North America to the rest of the world. 22 | > > 23 | > > _Related:_ [Pricing on egress rates.][pricing-egress] and [How Google calculates egress usage rates.][usage-egress-gcp] 24 | > 25 | > > :Tab title=More information and official links 26 | > > 27 | > > - [Main landing page on the Free-Tier plan][google-free-landing] 28 | > > - [Limits of the free-tier usage, from the official documentation][free-tier-limits] 29 | > > - [GCP's Free Programs Overview][google-free-docs] 30 | > > - [Eligibility for the Free Tier][free-tier-restrictions] 31 | > > - [Detailed price-list on paid products][gcp-price-list] 32 | 33 | ## Requirements 34 | 35 | ### APIs 36 | 37 | > - [Cloud Resource Manager API][resource-api-info] | [Enable it][resource-api-enable] 38 | > - [Identity and Access Management (IAM) API][iam-api-info] | [Enable it][iam-api-enable] 39 | > - [Cloud Deployment Manager V2 API][cloud-api-info] | [Enable it][cloud-api-enable] 40 | > - [Compute Engine API][compute-api-info] | [Enable it][compute-api-enable] 41 | > - [Cloud Firestore API][firestore-api-info] | [Enable it][firestore-enable-api] 42 | 43 | ## Options 44 | 45 | ### Examples 46 | 47 | ```hcl | /examples/gcp/e2e/main.tf 48 | provider "google" { 49 | region = "your_project_region" 50 | } 51 | provider "google-beta" { 52 | region = "your_project_region" 53 | } 54 | 55 | module "gcp_free" { 56 | source = "https://github.com/gruberdev/tf-free/tree/main/modules/gcp" 57 | gcp_project_id = "your_project_id" 58 | project_region = "your_project_region" 59 | instance_name = "your_resulting_instance_name" 60 | permissions = "permissions_configuration" 61 | bucket_name = "resulting_bucket_name" 62 | network_name = "resulting_network_name" 63 | } 64 | ``` 65 | 66 | 67 | 68 | [guidelines]: https://www.hashicorp.com/community-guidelines 69 | [free-gcp]: https://cloud.google.com/free 70 | [free-docs-gcp]: https://cloud.google.com/free/docs/gcp-free-tier 71 | [free-tier-limits]: https://cloud.google.com/free/docs/gcp-free-tier/#free-tier-usage-limits 72 | [free-tier-restrictions]: https://cloud.google.com/free/docs/gcp-free-tier/#free-tier 73 | [google-free-docs]: https://cloud.google.com/free/docs/gcp-free-tier/ 74 | [google-free-landing]: https://cloud.google.com/free 75 | [unique-gcp-docs]: https://cloud.google.com/free/docs/what-makes-google-cloud-platform-different 76 | [why-google]: https://cloud.google.com/why-google-cloud 77 | [gcp-price-list]: https://cloud.google.com/pricing/list 78 | [gcp-comparison-docs]: https://cloud.google.com/free/docs/aws-azure-gcp-service-comparison 79 | [pricing-egress]: https://cloud.google.com/vpc/network-pricing#internet_egress 80 | [usage-egress-gcp]: https://cloud.google.com/vpc/network-pricing#vpc-pricing 81 | [gcp-compute-info]: https://cloud.google.com/compute/docs 82 | [gcp-shared-vcpus]: https://cloud.google.com/compute/vm-instance-pricing#cpu-bursting 83 | [gcp-cloud-storage]: https://cloud.google.com/storage 84 | [gcp-vpc-info]: https://cloud.google.com/storage 85 | [gcp-firewall-info]: https://cloud.google.com/storage 86 | [gcp-firestore-storage]: https://cloud.google.com/firestore/docs 87 | [pricing-gcp-calculator]: https://cloud.google.com/products/calculator 88 | [no-free-ip]: https://cloud.google.com/free/docs/gcp-free-tier#always-free-usage-limits 89 | [pricing-egress]: https://cloud.google.com/vpc/network-pricing#internet_egress 90 | [usage-egress-gcp]: https://cloud.google.com/vpc/network-pricing#vpc-pricing 91 | [gcp-compute-info]: https://cloud.google.com/compute/docs 92 | [gcp-shared-vcpus]: https://cloud.google.com/compute/vm-instance-pricing#cpu-bursting 93 | [gcp-cloud-storage]: https://cloud.google.com/storage 94 | [gcp-regional-storage]: https://cloud.google.com/storage/docs/storage-classes#legacy 95 | [gcp-firestore-storage]: https://cloud.google.com/firestore/docs 96 | [gcp-regions]: https://cloud.google.com/compute/docs/regions-zones 97 | [firestore-api-info]: https://cloud.google.com/firestore/docs/reference/rest 98 | [firestore-enable-api]: https://console.cloud.google.com/apis/library/file.googleapis.com 99 | [resource-api-info]: https://cloud.google.com/resource-manager 100 | [resource-api-enable]: https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com 101 | [iam-api-info]: https://cloud.google.com/iam 102 | [iam-api-enable]: https://console.cloud.google.com/apis/library/iam.googleapis.com 103 | [compute-api-info]: https://cloud.google.com/compute 104 | [compute-api-enable]: https://console.cloud.google.com/apis/library/compute.googleapis.com 105 | [cloud-api-info]: https://cloud.google.com/deployment-manager 106 | [cloud-api-enable]: https://console.cloud.google.com/apis/library/deploymentmanager.googleapis.com 107 | -------------------------------------------------------------------------------- /docs/md/docs/providers/msazure.md: -------------------------------------------------------------------------------- 1 | # Microsoft Azure 2 | 3 | ## Available Resources 4 | 5 | - **1x** [Linux Virtual machine, B1S Standard tier][azure-vm-info] 6 | - **1x** [Windows Virtual machine, B1S Standard tier][azure-vm-info] 7 | - **1x** [Cloud Storage (LRS File Storage)][azure-storage-info] 8 | - **1x** [250GB MySQL Managed Database Instance][azure-sql-free-info] 9 | 10 | #### Terms & Conditions for resource usage 11 | 12 | - Some resources are **only valid for 12 months** and not forever. Please [check the list of resources](azure-free-resources) to verify each resource maximum usage within the Free-Tier plan. 13 | - Microsoft seems to provide very little data on how restricted the free accounts are in the terms of availability in regions around the world. 14 | 15 | ## Options 16 | 17 | ### Examples 18 | 19 | ### References 20 | 21 | - [Official free account Azure main page][azure-free-account] 22 | - [List of free resources][azure-free-resources] 23 | - [Azure Free Account FAQ][azure-free-faq] 24 | - [Azure Full Terms - Free Account][azure-full-terms] 25 | 26 | 27 | 28 | [azure-sql-free-info]: https://azure.microsoft.com/en-us/products/azure-sql/database/ 29 | [azure-free-resources]: https://azure.microsoft.com/en-us/free/#12-months-free 30 | [azure-free-account]: https://azure.microsoft.com/en-us/free/ 31 | [azure-vm-info]: https://azure.microsoft.com/en-us/services/virtual-machines/ 32 | [azure-storage-info]: https://azure.microsoft.com/en-us/services/storage/files/ 33 | [azure-full-terms]: https://azure.microsoft.com/en-us/offers/ms-azr-0044p/ 34 | [azure-free-faq]: https://azure.microsoft.com/en-us/free/free-account-faq/ 35 | -------------------------------------------------------------------------------- /docs/md/docs/providers/oracle.md: -------------------------------------------------------------------------------- 1 | # Oracle Cloud 2 | 3 | ## Resources 4 | 5 | ## Options 6 | 7 | ### Examples 8 | 9 | ### References 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/md/docs/setup/environment.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/setup/environment.md -------------------------------------------------------------------------------- /docs/md/docs/setup/first-run.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/setup/first-run.md -------------------------------------------------------------------------------- /docs/md/docs/setup/getting-started.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/setup/getting-started.md -------------------------------------------------------------------------------- /docs/md/docs/setup/installing.md: -------------------------------------------------------------------------------- 1 | ## CLI 2 | 3 | ### Running tests 4 | 5 | - Tests are available in `test` directory 6 | 7 | - In the test directory, run the below command 8 | 9 | ``` 10 | go test 11 | ``` 12 | 13 | ### Main Libraries used 14 | 15 | - [fatih/color](go-color-url) 16 | - [goreleaser/goreleaser](go-releaser-url) 17 | - [spf13/cobra](go-cobra-url) 18 | - [kdabir/has](shell-has-url) 19 | - [c-bata/go-prompt](go-prompt-url) 20 | - [go-task/task](go-task-url) 21 | - [hashicorp/terraform-exec](go-tfexec-url) 22 | - [CONNECT-platform/codedoc](docs-repo-url) 23 | - [cloudposse/terraform-aws-tfstate-backend](remote-tfstate-url) 24 | 25 | --- 26 | 27 | 28 | 29 | [go-color-url]: https://github.com/fatih/color 30 | [go-releaser-url]: https://github.com/goreleaser/goreleaser 31 | [go-cobra-url]: https://github.com/spf13/cobra 32 | [shell-has-url]: https://github.com/kdabir/has 33 | [go-prompt-url]: https://github.com/c-bata/go-prompt 34 | [go-task-url]: https://github.com/go-task/task 35 | [go-tfexec-url]: https://github.com/hashicorp/terraform-exec 36 | [docs-repo-url]: https://github.com/CONNECT-platform/codedoc 37 | [remote-tfstate-url]: https://github.com/cloudposse/terraform-aws-tfstate-backend 38 | -------------------------------------------------------------------------------- /docs/md/docs/setup/management.md: -------------------------------------------------------------------------------- 1 | # CLI 2 | -------------------------------------------------------------------------------- /docs/md/docs/setup/requirements.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/setup/requirements.md -------------------------------------------------------------------------------- /docs/md/docs/setup/resources.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/docs/md/docs/setup/resources.md -------------------------------------------------------------------------------- /docs/md/index.md: -------------------------------------------------------------------------------- 1 | [![Logo Animation](https://readme-typing-svg.herokuapp.com?font=Major+Mono+Display&color=00E7F7&size=40&vCenter=true&width=800&height=130&lines=tf-free;cloud+for+free.)](https://free.terraform.gruber.dev.br) 2 | 3 | --- 4 | 5 | # Introduction 6 | > **Creating all available resources offered by major cloud providers within free-tier plans, using Terraform to provide, manage and access these resources in a simplified and centralized manner.** 7 | 8 | ### Project's objective 9 | 10 | Every major cloud provider offers a free tier that allows for some kind of resource free of charge, still, learning every cloud and managing these resources can prove burdensome to most. 11 | 12 | The goal is to automate the management of these resources using Terraform as the centralizing tool. It also aims to provide resources for learning and improve your skills as a SRE/DevOps Engineer and as a Terraform user, even if you're developer that never touched cloud infrastructure, nowadays there's great value in learning these tools. 13 | 14 | A CLI tool is part of this project for those who wish a more [KIS][kis-approach]-like approach. 15 | 16 | --- 17 | 18 | # How to use these project's resources: 19 | 20 | There are three main ways to bootstrap this project: 21 | 22 | 1. Using the CLI tool (recommended) 23 | 2. Use Terraform's module directly (advanced) 24 | 25 | The second method exemplified below: 26 | 27 | ```bash | --no-wmbar 28 | terraform apply -auto-approve 29 | ``` 30 | 31 | > :Buttons 32 | > 33 | > > :CopyButton 34 | 35 | To visualize the available commands: 36 | 37 | ```bash | --no-wmbar 38 | sudo sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin 39 | task --list # Display help message 40 | > * gcp: Build executable binary with GoReleaser. 41 | > * gcp-boot: test 42 | > * gcp-init: Bootstrapping Google Cloud provider testing files 43 | > * gcp-test: Terraform testing (GCP provider) 44 | > * graph: Create beautiful Terraform Graphs 45 | > * heavy-artillery: Destroy all resources but the S3 Backend .and the DynamoDB instances on AWS. 46 | ``` 47 | 48 | > :Buttons 49 | > 50 | > > :CopyButton 51 | 52 | --- 53 | 54 | Now, if you want to explicitly call the core module, write a `main.tf` with this content: 55 | 56 | ```hcl | /example/main.tf 57 | // Create a main.tf file anywhere with Terraform installed and copy-paste this code 58 | 59 | module "tf-free" { 60 | source = "github.com/gruberdev/tf-free" 61 | 62 | /*!*/ enable_aws = true // @see [AWS documentation](/docs/providers/amznaws) 63 | /*!*/ enable_s3_backend = true // @see [using a remote S3 on AWS reference](/docs/setup/backend) 64 | aws_account_id = "your-aws-access-id" 65 | aws_account_key = "your-aws-secret-key" 66 | aws_default_region = "us-west1" 67 | 68 | /*!*/ enable_gcp = true // @see [GCP's documentation](/docs/providers/gcloud) 69 | gcp_project_id = "testing-project-1" 70 | gcp_project_region = "us-west-1" 71 | gcp_instance_name = "gcp-machine" 72 | 73 | /*!*/ enable_azure = true // @see [Azure's documentation](/docs/providers/msazure) 74 | 75 | /*!*/ enable_oracle = true // @see [Oracle's documentation](/docs/providers/msazure) 76 | } 77 | ``` 78 | 79 | > :Buttons 80 | > 81 | > > :CopyButton 82 | 83 |
84 | 85 | If you're unsure what your credentials are for each cloud provider, take a look at [Obtaining credentials](/docs/setup/first-run). 86 | 87 | > :Buttons 88 | > 89 | > > :Button icon=true, label=double_arrow, url=/docs/setup/getting-started 90 | 91 | --- 92 | 93 | 94 | 95 | [drone-img]: https://img.shields.io/drone/build/gruberdev/tf-free?label=Pipeline%20Status&color=46bac0&labelColor=1F1F1F&logo=Drone&style=for-the-badge&server=https%3A%2F%2Fdrone.gruber.dev.br 96 | [docs-img]: https://img.shields.io/badge/read%20documentation-online?style=flat-square&logo=zeit&color=black 97 | 98 | 99 | 100 | [brand]: https://www.hashicorp.com/brand 101 | [disclaimer]: https://www.hashicorp.com/trademark-policy 102 | [guidelines]: https://www.hashicorp.com/community-guidelines 103 | [free-aws]: https://aws.amazon.com/free/?all-free-tier 104 | [free-gcp]: https://cloud.google.com/free 105 | [free-docs-gcp]: https://cloud.google.com/free/docs/gcp-free-tier 106 | [free-azure]: https://azure.microsoft.com/en-us/free/ 107 | [azure-faq]: https://azure.microsoft.com/en-us/free/free-account-faq/ 108 | [azure-full-terms]: https://azure.microsoft.com/en-us/offers/ms-azr-0044p/ 109 | [aws-faq]: https://aws.amazon.com/free/free-tier-faqs/ 110 | [go-color-url]: https://github.com/fatih/color 111 | [go-releaser-url]: https://github.com/goreleaser/goreleaser 112 | [go-cobra-url]: https://github.com/spf13/cobra 113 | [shell-has-url]: https://github.com/kdabir/has 114 | [go-prompt-url]: https://github.com/c-bata/go-prompt 115 | [go-task-url]: https://github.com/go-task/task 116 | [go-tfexec-url]: https://github.com/hashicorp/terraform-exec 117 | [docs-repo-url]: https://github.com/CONNECT-platform/codedoc 118 | [aws-key-info]: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys 119 | [aws-key-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/ 120 | [aws-account-create]: https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/ 121 | [aws-vpc-info]: https://aws.amazon.com/vpc/?vpc-blogs.sort-by=item.additionalFields.createdDate&vpc-blogs.sort-order=desc 122 | [aws-igw-info]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html 123 | [aws-ec2-info]: https://aws.amazon.com/ec2/ 124 | [aws-s3-info]: https://aws.amazon.com/s3/ 125 | [aws-rds-info]: https://aws.amazon.com/rds/ 126 | [aws-route-info]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Route_Tables.html 127 | [aws-sub-info]: https://docs.aws.amazon.com/vpc/latest/userguide/working-with-vpcs.html 128 | [aws-tf-provider]: https://registry.terraform.io/providers/hashicorp/aws/latest/ 129 | [aws-regions]: https://aws.amazon.com/about-aws/global-infrastructure/ 130 | [aws-terms]: https://aws.amazon.com/free/terms/ 131 | [aws-prevent-charges]: https://aws.amazon.com/premiumsupport/knowledge-center/free-tier-charges/ 132 | [aws-alarms-free]: https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/tracking-free-tier-usage.html#free-budget 133 | [aws-sorted-list]: https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=tier%23always-free%7Ctier%2312monthsfree&awsf.Free%20Tier%20Categories=*all 134 | [aws-dynamodb-info]: https://aws.amazon.com/dynamodb/ 135 | [remote-tfstate-url]: https://github.com/cloudposse/terraform-aws-tfstate-backend 136 | -------------------------------------------------------------------------------- /docs/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "cleanUrls": true 3 | } -------------------------------------------------------------------------------- /examples/aws/e2e/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | No inputs. 9 | 10 | ### Outputs 11 | 12 | No outputs. 13 | 14 | -------------------------------------------------------------------------------- /examples/aws/e2e/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/aws/e2e/main.tf -------------------------------------------------------------------------------- /examples/aws/e2e/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/aws/e2e/outputs.tf -------------------------------------------------------------------------------- /examples/aws/e2e/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/aws/e2e/variables.tf -------------------------------------------------------------------------------- /examples/aws/unit/ec2/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | ec2 | ../../../../modules/aws/ec2 | n/a | 7 | | vpc | ../../../../modules/aws/vpc | n/a | 8 | 9 | ### Inputs 10 | 11 | | Name | Description | Type | Default | 12 | |------|-------------|------|---------| 13 | | ami\_id | n/a | `string` | n/a | 14 | | aws\_default\_region | n/a | `string` | n/a | 15 | | ec2\_enable | n/a | `bool` | `true` | 16 | | ssh\_name | n/a | `string` | n/a | 17 | | ssh\_public | n/a | `string` | n/a | 18 | | subnet\_region | n/a | `string` | n/a | 19 | 20 | ### Outputs 21 | 22 | | Name | Description | 23 | |------|-------------| 24 | | public\_ip | List of public IP addresses assigned to the instances, if applicable | 25 | 26 | -------------------------------------------------------------------------------- /examples/aws/unit/ec2/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.aws_default_region 3 | } 4 | 5 | module "vpc" { 6 | source = "../../../../modules/aws/vpc" 7 | region = var.aws_default_region 8 | } 9 | 10 | module "ec2" { 11 | source = "../../../../modules/aws/ec2" 12 | count = var.ec2_enable ? 1 : 0 13 | vpc_id = module.vpc.id 14 | public_subnet_id = module.vpc.public_subnets[0] 15 | ami = var.ami_id 16 | 17 | seed_data = < index.html 20 | nohup busybox httpd -f -p 80 & 21 | EOF 22 | ssh_name = var.ssh_name 23 | ssh_public = var.ssh_public 24 | depends_on = [ 25 | module.vpc.public_subnets 26 | ] 27 | } 28 | 29 | 30 | output "public_ip" { 31 | description = "List of public IP addresses assigned to the instances, if applicable" 32 | value = module.ec2.*.public_ip 33 | sensitive = true 34 | } 35 | 36 | -------------------------------------------------------------------------------- /examples/aws/unit/ec2/variables.tf: -------------------------------------------------------------------------------- 1 | variable "ssh_name" { 2 | type = string 3 | } 4 | variable "ssh_public" { 5 | type = string 6 | } 7 | variable "aws_default_region" { 8 | type = string 9 | } 10 | variable "subnet_region" { 11 | type = string 12 | } 13 | variable "ami_id" { 14 | type = string 15 | } 16 | variable "ec2_enable" { 17 | type = bool 18 | default = true 19 | } 20 | -------------------------------------------------------------------------------- /examples/aws/unit/rds/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | rds | ../../../../modules/aws/rds | n/a | 7 | | vpc | ../../../../modules/aws/vpc | n/a | 8 | 9 | ### Inputs 10 | 11 | | Name | Description | Type | Default | 12 | |------|-------------|------|---------| 13 | | allocated\_storage | n/a | `number` | `5` | 14 | | aws\_default\_region | n/a | `string` | n/a | 15 | | database\_name | n/a | `string` | `"newtable"` | 16 | | db\_port | n/a | `number` | `5432` | 17 | | engine\_name | n/a | `string` | n/a | 18 | | engine\_version | n/a | `string` | n/a | 19 | | instance\_class | n/a | `string` | n/a | 20 | | name | n/a | `string` | n/a | 21 | | password | n/a | `string` | n/a | 22 | | rds\_enable | n/a | `bool` | `true` | 23 | | username | n/a | `string` | n/a | 24 | 25 | ### Outputs 26 | 27 | | Name | Description | 28 | |------|-------------| 29 | | db\_id | List of key names of instances | 30 | | db\_port | List of public IP addresses assigned to the instances, if applicable | 31 | -------------------------------------------------------------------------------- /examples/aws/unit/rds/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.aws_default_region 3 | } 4 | 5 | module "vpc" { 6 | source = "../../../../modules/aws/vpc" 7 | region = var.aws_default_region 8 | } 9 | module "rds" { 10 | source = "../../../../modules/aws/rds" 11 | count = var.rds_enable ? 1 : 0 12 | db_user = var.username 13 | name = var.name 14 | db_engine = var.engine_name 15 | db_version = var.engine_version 16 | region = var.aws_default_region 17 | db_name = var.database_name 18 | db_password = var.password 19 | vpc_id = module.vpc.id 20 | vpc_cidr_block = module.vpc.cidr_block 21 | vpc_subnet_ids = ["${module.vpc.database_subnets[0]}", "${module.vpc.database_subnets[1]}"] 22 | } -------------------------------------------------------------------------------- /examples/aws/unit/rds/outputs.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | output "db_port" { 4 | description = "List of public IP addresses assigned to the instances, if applicable" 5 | value = concat(module.rds.*.db_default_instance_port, [""])[0] 6 | 7 | } 8 | output "db_id" { 9 | description = "List of key names of instances" 10 | value = concat(module.rds.*.db_default_instance_id, [""])[0] 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/aws/unit/rds/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_default_region" { 2 | type = string 3 | } 4 | variable "name" { 5 | type = string 6 | } 7 | variable "engine_name" { 8 | type = string 9 | } 10 | variable "engine_version" { 11 | type = string 12 | } 13 | variable "instance_class" { 14 | type = string 15 | } 16 | 17 | variable "rds_enable" { 18 | type = bool 19 | default = true 20 | } 21 | 22 | variable "username" { 23 | sensitive = true 24 | type = string 25 | } 26 | variable "password" { 27 | sensitive = true 28 | type = string 29 | } 30 | variable "allocated_storage" { 31 | type = number 32 | default = 5 33 | } 34 | 35 | variable "database_name" { 36 | type = string 37 | default = "newtable" 38 | } 39 | 40 | variable "db_port" { 41 | type = number 42 | default = 5432 43 | } 44 | -------------------------------------------------------------------------------- /examples/azure/e2e/main.tf: -------------------------------------------------------------------------------- 1 | provider "azurerm" { 2 | features {} 3 | } 4 | 5 | module "azure" { 6 | source = "../../../modules/azure" 7 | resource_group_name = var.resource_group_name 8 | location = var.location 9 | /* linux_hostname = var.linux_vm 10 | windows_hostname = var.windows_vm */ 11 | } 12 | -------------------------------------------------------------------------------- /examples/azure/e2e/outputs.tf: -------------------------------------------------------------------------------- 1 | /* output "linux_name" { 2 | 3 | } 4 | 5 | output "windows_name" { 6 | value = azure. 7 | } */ -------------------------------------------------------------------------------- /examples/azure/e2e/variables.tf: -------------------------------------------------------------------------------- 1 | variable "location" { 2 | type = string 3 | default = "East US" 4 | } 5 | variable "resource_group_name" { 6 | type = string 7 | default = "my-group" 8 | } 9 | /* variable "linux_vm" { 10 | type = string 11 | default = "my-linux" 12 | } 13 | variable "windows_vm" { 14 | type = string 15 | default = "my-windows" 16 | } */ -------------------------------------------------------------------------------- /examples/azure/unit/compute/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/azure/unit/compute/main.tf -------------------------------------------------------------------------------- /examples/azure/unit/compute/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/azure/unit/compute/outputs.tf -------------------------------------------------------------------------------- /examples/azure/unit/compute/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/azure/unit/compute/variables.tf -------------------------------------------------------------------------------- /examples/azure/unit/db/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/azure/unit/db/main.tf -------------------------------------------------------------------------------- /examples/azure/unit/db/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/examples/azure/unit/db/variables.tf -------------------------------------------------------------------------------- /examples/gcp/e2e/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/gcp/e2e/main.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | region = var.gcp_project_region 3 | } 4 | provider "google-beta" { 5 | region = var.gcp_project_region 6 | } 7 | 8 | module "google_cloud" { 9 | source = "../../../modules/gcp" 10 | gcp_project_id = var.gcp_project_id 11 | project_region = var.gcp_project_region 12 | instance_name = var.gcp_instance_name 13 | permissions = var.gcp_storage_permissions 14 | bucket_name = var.gcp_bucket_name 15 | network_name = var.gcp_network_name 16 | } 17 | 18 | output "gcp_public_ip" { 19 | value = module.google_cloud.machine_ip 20 | sensitive = true 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/gcp/e2e/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | gcp_instance_name = "example-machine" 2 | gcp_project_region = "" 3 | gcp_project_id = "" 4 | gcp_bucket_name = "" 5 | gcp_network_name = "" 6 | gcp_storage_permissions = "publicread" -------------------------------------------------------------------------------- /examples/gcp/e2e/variables.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_project_region" { 2 | type = string 3 | } 4 | 5 | variable "gcp_project_id" { 6 | type = string 7 | } 8 | 9 | variable "gcp_network_name" { 10 | type = string 11 | } 12 | 13 | variable "gcp_bucket_name" { 14 | type = string 15 | } 16 | 17 | variable "gcp_storage_permissions" { 18 | type = string 19 | default = "publicread" 20 | } 21 | 22 | variable "gcp_instance_name" { 23 | type = string 24 | } -------------------------------------------------------------------------------- /examples/gcp/unit/compute/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/gcp/unit/compute/main.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | region = var.gcp_project_region 3 | } 4 | provider "google-beta" { 5 | region = var.gcp_project_region 6 | } 7 | 8 | resource "google_compute_instance" "gcp_example" { 9 | name = var.gcp_instance_name 10 | machine_type = "f1-micro" 11 | zone = "${var.gcp_project_region}-b" 12 | 13 | boot_disk { 14 | initialize_params { 15 | image = "debian-cloud/debian-10" 16 | size = 30 17 | type = "pd-standard" 18 | } 19 | } 20 | 21 | network_interface { 22 | network = "default" 23 | access_config { 24 | } 25 | } 26 | tags = [ 27 | "web", 28 | "ssh" 29 | ] 30 | } 31 | 32 | output "instance_id" { 33 | value = google_compute_instance.gcp_example.instance_id 34 | } 35 | output "resulting_name" { 36 | value = google_compute_instance.gcp_example.name 37 | } 38 | output "resulting_type" { 39 | value = google_compute_instance.gcp_example.machine_type 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/gcp/unit/compute/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | gcp_instance_name = "example-machine" 2 | gcp_project_region = "" 3 | gcp_project_id = "" 4 | -------------------------------------------------------------------------------- /examples/gcp/unit/compute/variables.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_project_region" { 2 | type = string 3 | } 4 | variable "gcp_project_id" { 5 | type = string 6 | } 7 | variable "gcp_instance_name" { 8 | type = string 9 | } -------------------------------------------------------------------------------- /examples/gcp/unit/storage/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/gcp/unit/storage/main.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | region = var.gcp_project_region 3 | } 4 | provider "google-beta" { 5 | project = var.gcp_project_id 6 | region = var.gcp_project_region 7 | } 8 | 9 | module "gcp_vpc" { 10 | vpc_name = var.gcp_network_name 11 | source = "../../../../modules/gcp/vpc" 12 | google_project = var.gcp_project_id 13 | } 14 | 15 | module "gcp_storage" { 16 | depends_on = [ 17 | module.gcp_vpc.network_name, 18 | ] 19 | source = "../../../../modules/gcp/storage" 20 | project_id = var.gcp_project_id 21 | name = var.gcp_bucket_name 22 | permissions = var.gcp_bucket_permissions 23 | /* firestore_name = var.firestore_name */ 24 | region = var.gcp_project_region 25 | network_name = module.gcp_vpc.network_name 26 | } 27 | 28 | output "bucket_name" { 29 | description = "Name of the GCS bucket that will receive the objects." 30 | value = module.gcp_storage.bucket_name 31 | } 32 | -------------------------------------------------------------------------------- /examples/gcp/unit/storage/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | gcp_instance_name = "example-machine" 2 | gcp_project_region = "" 3 | gcp_project_id = "" 4 | gcp_bucket_name = "" 5 | gcp_network_name = "" 6 | gcp_storage_permissions = "publicread" -------------------------------------------------------------------------------- /examples/gcp/unit/storage/variables.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_project_region" { 2 | type = string 3 | } 4 | variable "gcp_project_id" { 5 | type = string 6 | } 7 | variable "gcp_network_name" { 8 | type = string 9 | } 10 | 11 | variable "gcp_bucket_name" { 12 | type = string 13 | } 14 | 15 | variable "gcp_bucket_permissions" { 16 | type = string 17 | default = "publicread" 18 | } -------------------------------------------------------------------------------- /examples/gcp/unit/vpc/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/gcp/unit/vpc/main.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | region = var.gcp_project_region 3 | } 4 | provider "google-beta" { 5 | project = var.gcp_project_id 6 | region = var.gcp_project_region 7 | } 8 | 9 | module "gcp_vpc" { 10 | vpc_name = var.gcp_network_name 11 | google_project = var.gcp_project_id 12 | source = "../../../../modules/gcp/vpc" 13 | } 14 | 15 | module "gcp_firewall" { 16 | depends_on = [ 17 | module.gcp_vpc.network_name 18 | ] 19 | source = "../../../../modules/gcp/firewall" 20 | network_name = module.gcp_vpc.network_name 21 | } 22 | -------------------------------------------------------------------------------- /examples/gcp/unit/vpc/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | gcp_network_name = "example-network" 2 | gcp_project_region = "" 3 | gcp_project_id = "" -------------------------------------------------------------------------------- /examples/gcp/unit/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_project_region" { 2 | type = string 3 | } 4 | variable "gcp_project_id" { 5 | type = string 6 | } 7 | variable "gcp_network_name" { 8 | type = string 9 | } -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "random_string" "namespace" { 3 | length = 2 4 | special = false 5 | number = false 6 | upper = false 7 | } 8 | 9 | resource "random_string" "s3_name" { 10 | length = 6 11 | special = false 12 | number = false 13 | upper = false 14 | } 15 | 16 | resource "random_string" "bucket_name" { 17 | length = 10 18 | special = false 19 | number = false 20 | upper = false 21 | } 22 | 23 | module "terraform_state_backend" { 24 | source = "cloudposse/tfstate-backend/aws" 25 | version = "0.38.1" 26 | namespace = random_string.namespace.result 27 | stage = var.backend_stage 28 | name = random_string.s3_name.result 29 | s3_bucket_name = random_string.bucket_name.result 30 | attributes = ["state"] 31 | terraform_backend_config_file_path = "." 32 | terraform_backend_config_file_name = "backend.tf" 33 | force_destroy = var.backend_destroy 34 | depends_on = [ 35 | null_resource.backend 36 | ] 37 | } 38 | 39 | resource "null_resource" "backend" { 40 | triggers = { 41 | backend_destroy = var.backend_destroy 42 | } 43 | lifecycle { 44 | prevent_destroy = true 45 | } 46 | } 47 | 48 | module "google_cloud" { 49 | source = "./modules/gcp" 50 | gcp_project_id = var.gcp_project_id 51 | project_region = var.gcp_project_region 52 | instance_name = var.gcp_instance_name 53 | permissions = var.gcp_storage_permissions 54 | 55 | depends_on = [ 56 | module.terraform_state_backend.dynamodb_table_name, 57 | module.terraform_state_backend.dynamodb_table_id, 58 | module.terraform_state_backend.terraform_backend_config 59 | ] 60 | } 61 | 62 | module "aws" { 63 | source = "./modules/aws" 64 | ec2_enable = var.ec2_aws 65 | rds_enable = var.rds_aws 66 | } 67 | 68 | // module "azure" { 69 | // source = "./modules/azure" 70 | // } -------------------------------------------------------------------------------- /modules/aws/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | ec2 | ./ec2 | n/a | 7 | | rds | ./rds | n/a | 8 | | vpc | ./vpc | n/a | 9 | 10 | ### Inputs 11 | 12 | | Name | Description | Type | Default | 13 | |------|-------------|------|---------| 14 | | ec2\_enable | AWS Profile | `bool` | `true` | 15 | | ec2\_ssh\_name | The SSH Key Name | `string` | `"free-tier-ec2-key"` | 16 | | ec2\_ssh\_public | The local path to the SSH Public Key | `string` | `"~/.ssh-temp/id_rsa.pub"` | 17 | | profile | AWS Profile | `string` | `"terraform"` | 18 | | rds\_enable | AWS Profile | `bool` | `true` | 19 | | rds\_password | Region for the RDS database | `string` | `"testingdatabase89372934279"` | 20 | | rds\_user | Region for AWS resources | `string` | `"testing"` | 21 | | region | Region for AWS resources | `string` | `"us-east-1"` | 22 | 23 | ### Outputs 24 | 25 | | Name | Description | 26 | |------|-------------| 27 | | db\_id | List of key names of instances | 28 | | ec2\_ipv6\_addresses | List of assigned IPv6 addresses of instances | 29 | | ec2\_key\_name | List of key names of instances | 30 | | ec2\_password\_data | List of Base-64 encoded encrypted password data for the instance | 31 | | ec2\_private\_ip | List of private IP addresses assigned to the instances | 32 | | ec2\_public\_ip | List of public IP addresses assigned to the instances, if applicable | 33 | 34 | 35 | ## Example 36 | 37 | ```hcl 38 | provider "aws" { 39 | region = var.aws_default_region 40 | access_key = var.aws_account_id 41 | secret_key = var.aws_account_key 42 | } 43 | 44 | module "vpc" { 45 | source = "../../../../modules/aws/vpc" 46 | name = "vpc-test-ec2" 47 | } 48 | 49 | module "public_subnet" { 50 | source = "../../../../modules/aws/subnet" 51 | name = "subnet-test-ec2" 52 | availability_zone = var.subnet_region 53 | vpc_id = module.vpc.id 54 | } 55 | 56 | module "internet_gateway" { 57 | source = "../../../../modules/aws/gateway" 58 | name = "igw-test-ec2" 59 | vpc_id = module.vpc.id 60 | } 61 | 62 | module "route_table" { 63 | source = "../../../../modules/aws/firewall" 64 | 65 | name = "table-test-ec2" 66 | vpc_id = module.vpc.id 67 | internet_gateway_id = module.internet_gateway.id 68 | public_subnet_id = module.public_subnet.id 69 | } 70 | 71 | module "ec2" { 72 | source = "../../../../modules/aws/ec2" 73 | name = "ec2-test-ec2" 74 | vpc_id = module.vpc.id 75 | ami = var.ami_id 76 | seed_data = < index.html 79 | nohup busybox httpd -f -p 80 & 80 | EOF 81 | public_subnet_id = module.public_subnet.id 82 | ssh_name = var.ssh_name 83 | ssh_public = var.ssh_public 84 | } 85 | 86 | ``` 87 | -------------------------------------------------------------------------------- /modules/aws/ec2/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | ami | The Amazon Machine Image | `string` | `"ami-04b9e92b5572fa0d1"` | 11 | | instance\_type | The EC2 Instance type | `string` | `"t2.micro"` | 12 | | name | The Name of the EC2 | `string` | `"Free Tier EC2"` | 13 | | public\_subnet\_id | The ID of the Public Subnet | `string` | n/a | 14 | | security\_group\_description | The Description of the EC2 Security Group | `string` | `"Free Tier EC2 Security Group"` | 15 | | security\_group\_name | The Name of the EC2 Security Group | `string` | `"Free Tier EC2 Security Group"` | 16 | | seed\_data | The local path to the SSH Public Key | `string` | `""` | 17 | | ssh\_name | The SSH Key Name | `string` | `"free-tier-ec2-key"` | 18 | | ssh\_public | The local path to the SSH Public Key | `string` | n/a | 19 | | vpc\_id | The ID of the VPC | `string` | n/a | 20 | 21 | ### Outputs 22 | 23 | | Name | Description | 24 | |------|-------------| 25 | | arn | The ARN of the EC2 | 26 | | id | The ID of the EC2 | 27 | | ipv6\_addresses | List of assigned IPv6 addresses of instances | 28 | | names | List of key names of instances | 29 | | password\_data | List of Base-64 encoded encrypted password data for the instance | 30 | | private\_ip | List of private IP addresses assigned to the instances | 31 | | public\_dns | List of public DNS names assigned to the instances. For EC2-VPC, this is only available if you've enabled DNS hostnames for your VPC | 32 | | public\_ip | List of public IP addresses assigned to the instances, if applicable | 33 | | security\_group\_id | List of key names of instances | 34 | 35 | -------------------------------------------------------------------------------- /modules/aws/ec2/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "security_group" { 2 | name = var.security_group_name 3 | description = var.security_group_description 4 | 5 | vpc_id = var.vpc_id 6 | 7 | ingress { 8 | from_port = 22 9 | to_port = 22 10 | protocol = "tcp" 11 | cidr_blocks = ["0.0.0.0/0"] 12 | } 13 | 14 | ingress { 15 | from_port = 80 16 | to_port = 80 17 | protocol = "tcp" 18 | cidr_blocks = ["0.0.0.0/0"] 19 | } 20 | 21 | ingress { 22 | from_port = 443 23 | to_port = 443 24 | protocol = "tcp" 25 | cidr_blocks = ["0.0.0.0/0"] 26 | } 27 | 28 | egress { 29 | from_port = 0 30 | to_port = 0 31 | protocol = "-1" 32 | cidr_blocks = ["0.0.0.0/0"] 33 | } 34 | 35 | tags = { 36 | Name = var.security_group_name 37 | } 38 | } 39 | 40 | resource "aws_instance" "ec2" { 41 | 42 | ami = var.ami 43 | instance_type = var.instance_type 44 | 45 | subnet_id = var.public_subnet_id 46 | vpc_security_group_ids = [aws_security_group.security_group.id] 47 | associate_public_ip_address = true 48 | user_data = var.seed_data 49 | 50 | tags = { 51 | Name = var.name 52 | } 53 | } 54 | 55 | 56 | resource "aws_key_pair" "ec2_key_pair" { 57 | key_name = var.ssh_name 58 | public_key = var.ssh_public 59 | } 60 | -------------------------------------------------------------------------------- /modules/aws/ec2/outputs.tf: -------------------------------------------------------------------------------- 1 | output "id" { 2 | description = "The ID of the EC2" 3 | value = concat(aws_instance.ec2.*.id, [""])[0] 4 | } 5 | 6 | output "arn" { 7 | description = "The ARN of the EC2" 8 | value = concat(aws_instance.ec2.*.arn, [""])[0] 9 | } 10 | 11 | output "public_ip" { 12 | description = "List of public IP addresses assigned to the instances, if applicable" 13 | value = aws_instance.ec2.*.public_ip 14 | sensitive = true 15 | } 16 | 17 | output "ipv6_addresses" { 18 | description = "List of assigned IPv6 addresses of instances" 19 | value = aws_instance.ec2.*.ipv6_addresses 20 | sensitive = true 21 | } 22 | 23 | output "private_ip" { 24 | description = "List of private IP addresses assigned to the instances" 25 | value = aws_instance.ec2.*.private_ip 26 | sensitive = true 27 | } 28 | 29 | output "password_data" { 30 | description = "List of Base-64 encoded encrypted password data for the instance" 31 | value = aws_instance.ec2.*.password_data 32 | sensitive = true 33 | } 34 | 35 | output "public_dns" { 36 | description = "List of public DNS names assigned to the instances. For EC2-VPC, this is only available if you've enabled DNS hostnames for your VPC" 37 | value = aws_instance.ec2.*.public_dns 38 | } 39 | 40 | output "names" { 41 | description = "List of key names of instances" 42 | value = aws_instance.ec2.*.key_name 43 | } 44 | 45 | output "security_group_id" { 46 | description = "List of key names of instances" 47 | value = aws_security_group.security_group.id 48 | } 49 | -------------------------------------------------------------------------------- /modules/aws/ec2/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | description = "The Name of the EC2" 3 | type = string 4 | default = "Free Tier EC2" 5 | } 6 | 7 | variable "security_group_name" { 8 | description = "The Name of the EC2 Security Group" 9 | type = string 10 | default = "Free Tier EC2 Security Group" 11 | } 12 | 13 | variable "security_group_description" { 14 | description = "The Description of the EC2 Security Group" 15 | type = string 16 | default = "Free Tier EC2 Security Group" 17 | } 18 | 19 | variable "ami" { 20 | description = "The Amazon Machine Image" 21 | type = string 22 | default = "ami-04b9e92b5572fa0d1" # Ubuntu 18.04 LTS (64-bit x86) Free Tier eligible 23 | } 24 | 25 | variable "instance_type" { 26 | description = "The EC2 Instance type" 27 | type = string 28 | default = "t2.micro" # Free Tier eligible 29 | } 30 | 31 | variable "vpc_id" { 32 | description = "The ID of the VPC" 33 | sensitive = true 34 | type = string 35 | } 36 | 37 | variable "public_subnet_id" { 38 | description = "The ID of the Public Subnet" 39 | sensitive = true 40 | type = string 41 | } 42 | 43 | variable "ssh_name" { 44 | description = "The SSH Key Name" 45 | type = string 46 | default = "free-tier-ec2-key" 47 | } 48 | 49 | variable "ssh_public" { 50 | description = "The local path to the SSH Public Key" 51 | sensitive = true 52 | type = string 53 | } 54 | variable "seed_data" { 55 | description = "The local path to the SSH Public Key" 56 | default = "" 57 | type = string 58 | } 59 | -------------------------------------------------------------------------------- /modules/aws/firewall/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | internet\_gateway\_id | The ID of the Internet Gateway | `string` | n/a | 11 | | name | The Name of the Route Table | `string` | `"Free Tier Route Table"` | 12 | | public\_subnet\_id | The ID of the Public Subnet | `string` | n/a | 13 | | should\_be\_created | Should the Route Table be created? | `bool` | `true` | 14 | | vpc\_id | The ID of the VPC | `string` | n/a | 15 | 16 | ### Outputs 17 | 18 | | Name | Description | 19 | |------|-------------| 20 | | id | The ID of the Route Table | 21 | 22 | -------------------------------------------------------------------------------- /modules/aws/firewall/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_route_table" "route_table" { 2 | vpc_id = var.vpc_id 3 | 4 | route { 5 | cidr_block = "0.0.0.0/0" 6 | gateway_id = var.internet_gateway_id 7 | } 8 | 9 | tags = { 10 | Name = var.name 11 | } 12 | } 13 | 14 | resource "aws_route_table_association" "route_table_association" { 15 | subnet_id = var.public_subnet_id 16 | route_table_id = concat(aws_route_table.route_table.*.id, [""])[0] 17 | } 18 | -------------------------------------------------------------------------------- /modules/aws/firewall/outputs.tf: -------------------------------------------------------------------------------- 1 | output "id" { 2 | description = "The ID of the Route Table" 3 | value = concat(aws_route_table.route_table.*.id, [""])[0] 4 | } 5 | -------------------------------------------------------------------------------- /modules/aws/firewall/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | description = "The Name of the Route Table" 3 | type = string 4 | default = "Free Tier Route Table" 5 | } 6 | 7 | variable "vpc_id" { 8 | description = "The ID of the VPC" 9 | sensitive = true 10 | type = string 11 | } 12 | 13 | variable "internet_gateway_id" { 14 | description = "The ID of the Internet Gateway" 15 | type = string 16 | } 17 | 18 | variable "public_subnet_id" { 19 | description = "The ID of the Public Subnet" 20 | sensitive = true 21 | type = string 22 | } 23 | -------------------------------------------------------------------------------- /modules/aws/gateway/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | name | The Name of the Internet Gateway | `string` | `"Free Tier Internet Gateway"` | 11 | | should\_be\_created | Should the Internet Gateway be created? | `bool` | `true` | 12 | | vpc\_id | The ID of the VPC | `string` | n/a | 13 | 14 | ### Outputs 15 | 16 | | Name | Description | 17 | |------|-------------| 18 | | id | The ID of the Internet Gateway | 19 | 20 | -------------------------------------------------------------------------------- /modules/aws/gateway/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_internet_gateway" "internet_gateway" { 2 | vpc_id = var.vpc_id 3 | 4 | tags = { 5 | Name = var.name 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /modules/aws/gateway/outputs.tf: -------------------------------------------------------------------------------- 1 | output "id" { 2 | description = "The ID of the Internet Gateway" 3 | value = concat(aws_internet_gateway.internet_gateway.*.id, [""])[0] 4 | } 5 | -------------------------------------------------------------------------------- /modules/aws/gateway/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | description = "The Name of the Internet Gateway" 3 | type = string 4 | default = "Free Tier Internet Gateway" 5 | } 6 | 7 | variable "vpc_id" { 8 | description = "The ID of the VPC" 9 | sensitive = true 10 | type = string 11 | } 12 | -------------------------------------------------------------------------------- /modules/aws/main.tf: -------------------------------------------------------------------------------- 1 | module "vpc" { 2 | source = "./vpc" 3 | region = var.region 4 | } 5 | 6 | module "ec2" { 7 | source = "./ec2" 8 | count = var.ec2_enable ? 1 : 0 9 | 10 | vpc_id = module.vpc.id 11 | public_subnet_id = module.vpc.public_subnets[0] 12 | 13 | ssh_name = var.ec2_ssh_name 14 | ssh_public = file(var.ec2_ssh_public) 15 | depends_on = [ 16 | module.vpc.public_subnets 17 | ] 18 | } 19 | 20 | module "rds" { 21 | source = "./rds" 22 | count = var.rds_enable ? 1 : 0 23 | 24 | region = var.region 25 | vpc_id = module.vpc.id 26 | vpc_cidr_block = module.vpc.cidr_block 27 | vpc_subnet_ids = ["${module.vpc.database_subnets[0]}", "${module.vpc.database_subnets[1]}"] 28 | } 29 | -------------------------------------------------------------------------------- /modules/aws/outputs.tf: -------------------------------------------------------------------------------- 1 | output "ec2_public_ip" { 2 | description = "List of public IP addresses assigned to the instances, if applicable" 3 | value = module.ec2.*.public_ip 4 | sensitive = true 5 | } 6 | 7 | output "ec2_ipv6_addresses" { 8 | description = "List of assigned IPv6 addresses of instances" 9 | value = module.ec2.*.ipv6_addresses 10 | sensitive = true 11 | } 12 | 13 | output "ec2_private_ip" { 14 | description = "List of private IP addresses assigned to the instances" 15 | value = module.ec2.*.private_ip 16 | sensitive = true 17 | } 18 | 19 | output "ec2_password_data" { 20 | description = "List of Base-64 encoded encrypted password data for the instance" 21 | value = module.ec2.*.password_data 22 | sensitive = true 23 | } 24 | 25 | output "ec2_key_name" { 26 | description = "List of key names of instances" 27 | value = module.ec2.*.names 28 | sensitive = true 29 | } 30 | 31 | output "db_id" { 32 | description = "List of key names of instances" 33 | value = module.rds.*.db_default_instance_id 34 | sensitive = true 35 | } 36 | -------------------------------------------------------------------------------- /modules/aws/rds/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | db\_default | terraform-aws-modules/rds/aws | n/a | 7 | | security\_group | terraform-aws-modules/security-group/aws | n/a | 8 | 9 | ### Inputs 10 | 11 | | Name | Description | Type | Default | 12 | |------|-------------|------|---------| 13 | | db\_engine | The local path to the SSH Public Key | `string` | `"postgres"` | 14 | | db\_family | The local path to the SSH Public Key | `string` | `"postgres12"` | 15 | | db\_instance\_type | Instance type for database | `string` | `"db.t2.micro"` | 16 | | db\_major\_engine | n/a | `string` | `"12"` | 17 | | db\_name | n/a | `string` | `"newtable"` | 18 | | db\_password | Region for AWS resources | `string` | `"forALEKkjkfeajme"` | 19 | | db\_security\_group\_name | Instance type for database | `string` | `"security-db"` | 20 | | db\_user | Region for AWS resources | `string` | `"defaultuser"` | 21 | | db\_version | The SSH Key Name | `string` | `"12.6"` | 22 | | disk\_size | n/a | `number` | `20` | 23 | | license | Region for AWS resources | `string` | `"postgresql-license"` | 24 | | name | Region for AWS resources | `string` | `"databasetf"` | 25 | | region | n/a | `string` | n/a | 26 | | subnet\_group\_name | Instance type for database | `string` | `"subnet-db"` | 27 | | vpc\_cidr\_block | n/a | `string` | n/a | 28 | | vpc\_id | n/a | `string` | n/a | 29 | | vpc\_subnet\_ids | n/a | `any` | n/a | 30 | 31 | ### Outputs 32 | 33 | | Name | Description | 34 | |------|-------------| 35 | | db\_default\_instance\_address | The address of the RDS instance | 36 | | db\_default\_instance\_arn | The ARN of the RDS instance | 37 | | db\_default\_instance\_availability\_zone | The availability zone of the RDS instance | 38 | | db\_default\_instance\_endpoint | The connection endpoint | 39 | | db\_default\_instance\_hosted\_zone\_id | The canonical hosted zone ID of the DB instance (to be used in a Route 53 Alias record) | 40 | | db\_default\_instance\_id | The RDS instance ID | 41 | | db\_default\_instance\_name | The database name | 42 | | db\_default\_instance\_port | The database port | 43 | | db\_default\_instance\_resource\_id | The RDS Resource ID of this instance | 44 | | db\_default\_instance\_status | The RDS instance status | 45 | | db\_default\_parameter\_group\_arn | The ARN of the db parameter group | 46 | | db\_default\_parameter\_group\_id | The db parameter group id | 47 | | db\_default\_subnet\_group\_arn | The ARN of the db subnet group | 48 | | db\_default\_subnet\_group\_id | The db subnet group name | 49 | 50 | -------------------------------------------------------------------------------- /modules/aws/rds/main.tf: -------------------------------------------------------------------------------- 1 | 2 | module "security_group" { 3 | source = "terraform-aws-modules/security-group/aws" 4 | 5 | name = var.name 6 | description = "Complete PostgreSQL example security group" 7 | vpc_id = var.vpc_id 8 | 9 | # ingress 10 | ingress_with_cidr_blocks = [ 11 | { 12 | from_port = 5432 13 | to_port = 5432 14 | protocol = "tcp" 15 | description = "PostgreSQL access from within VPC" 16 | cidr_blocks = var.vpc_cidr_block 17 | }, 18 | ] 19 | } 20 | 21 | module "db_default" { 22 | source = "terraform-aws-modules/rds/aws" 23 | 24 | identifier = "${var.name}-default" 25 | 26 | create_db_option_group = false 27 | create_db_parameter_group = false 28 | 29 | # All available versions: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts 30 | engine = var.db_engine 31 | engine_version = var.db_version 32 | family = var.db_family # DB parameter group 33 | major_engine_version = var.db_major_engine # DB option group 34 | instance_class = var.db_instance_type 35 | 36 | allocated_storage = var.disk_size 37 | 38 | # NOTE: Do NOT use 'user' as the value for 'username' as it throws: 39 | # "Error creating DB Instance: InvalidParameterValue: MasterUsername 40 | # user cannot be used as it is a reserved word used by the engine" 41 | db_name = "${var.db_name}" 42 | username = var.db_user 43 | create_random_password = true 44 | random_password_length = 12 45 | port = 5432 46 | 47 | subnet_ids = var.vpc_subnet_ids 48 | vpc_security_group_ids = [module.security_group.security_group_id] 49 | 50 | maintenance_window = "Mon:00:00-Mon:03:00" 51 | backup_window = "03:00-06:00" 52 | 53 | backup_retention_period = 0 // no backup 54 | } 55 | -------------------------------------------------------------------------------- /modules/aws/rds/outputs.tf: -------------------------------------------------------------------------------- 1 | 2 | # Default 3 | output "db_default_instance_address" { 4 | description = "The address of the RDS instance" 5 | value = concat(module.db_default.*.db_instance_address, [""])[0] 6 | } 7 | 8 | output "db_default_instance_arn" { 9 | description = "The ARN of the RDS instance" 10 | value = concat(module.db_default.*.db_instance_arn, [""])[0] 11 | } 12 | 13 | output "db_default_instance_availability_zone" { 14 | description = "The availability zone of the RDS instance" 15 | value = concat(module.db_default.*.db_instance_availability_zone, [""])[0] 16 | } 17 | 18 | output "db_default_instance_endpoint" { 19 | description = "The connection endpoint" 20 | value = concat(module.db_default.*.db_instance_endpoint, [""])[0] 21 | } 22 | 23 | output "db_default_instance_hosted_zone_id" { 24 | description = "The canonical hosted zone ID of the DB instance (to be used in a Route 53 Alias record)" 25 | value = concat(module.db_default.*.db_instance_hosted_zone_id, [""])[0] 26 | } 27 | 28 | output "db_default_instance_id" { 29 | description = "The RDS instance ID" 30 | value = concat(module.db_default.*.db_instance_id, [""])[0] 31 | } 32 | 33 | output "db_default_instance_resource_id" { 34 | description = "The RDS Resource ID of this instance" 35 | value = concat(module.db_default.*.db_instance_resource_id, [""])[0] 36 | } 37 | 38 | output "db_default_instance_status" { 39 | description = "The RDS instance status" 40 | value = concat(module.db_default.*.db_instance_status, [""])[0] 41 | } 42 | 43 | output "db_default_instance_name" { 44 | description = "The database name" 45 | value = concat(module.db_default.*.db_instance_name, [""])[0] 46 | } 47 | 48 | output "db_default_instance_port" { 49 | description = "The database port" 50 | value = concat(module.db_default.*.db_instance_port, [""])[0] 51 | } 52 | 53 | output "db_default_subnet_group_id" { 54 | description = "The db subnet group name" 55 | value = concat(module.db_default.*.db_subnet_group_id, [""])[0] 56 | } 57 | 58 | output "db_default_subnet_group_arn" { 59 | description = "The ARN of the db subnet group" 60 | value = concat(module.db_default.*.db_subnet_group_arn, [""])[0] 61 | } 62 | 63 | output "db_default_parameter_group_id" { 64 | description = "The db parameter group id" 65 | value = concat(module.db_default.*.db_parameter_group_id, [""])[0] 66 | } 67 | 68 | output "db_default_parameter_group_arn" { 69 | description = "The ARN of the db parameter group" 70 | value = concat(module.db_default.*.db_parameter_group_arn, [""])[0] 71 | } 72 | 73 | -------------------------------------------------------------------------------- /modules/aws/rds/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | description = "Region for AWS resources" 3 | type = string 4 | default = "databasetf" 5 | } 6 | 7 | variable "db_version" { 8 | description = "The SSH Key Name" 9 | type = string 10 | default = "12.6" 11 | } 12 | 13 | variable "db_family" { 14 | description = "The local path to the SSH Public Key" 15 | type = string 16 | default = "postgres12" 17 | } 18 | 19 | variable "db_major_engine" { 20 | type = string 21 | default = "12" 22 | } 23 | 24 | variable "db_engine" { 25 | description = "The local path to the SSH Public Key" 26 | type = string 27 | default = "postgres" 28 | } 29 | 30 | variable "disk_size" { 31 | type = number 32 | default = 20 33 | } 34 | 35 | variable "db_user" { 36 | description = "Region for AWS resources" 37 | default = "defaultuser" 38 | sensitive = true 39 | type = string 40 | } 41 | 42 | variable "db_password" { 43 | description = "Region for AWS resources" 44 | sensitive = true 45 | default = "forALEKkjkfeajme" 46 | type = string 47 | } 48 | 49 | 50 | variable "license" { 51 | description = "Region for AWS resources" 52 | default = "postgresql-license" 53 | type = string 54 | } 55 | 56 | variable "db_instance_type" { 57 | description = "Instance type for database" 58 | type = string 59 | default = "db.t2.micro" 60 | } 61 | 62 | variable "subnet_group_name" { 63 | description = "Instance type for database" 64 | sensitive = true 65 | type = string 66 | default = "subnet-db" 67 | } 68 | 69 | 70 | variable "db_security_group_name" { 71 | description = "Instance type for database" 72 | type = string 73 | sensitive = true 74 | default = "security-db" 75 | } 76 | 77 | variable "region" { 78 | type = string 79 | } 80 | 81 | variable "db_name" { 82 | type = string 83 | default = "newtable" 84 | } 85 | 86 | variable "vpc_id" { 87 | type = string 88 | } 89 | 90 | variable "vpc_cidr_block" { 91 | type = string 92 | } 93 | 94 | variable "vpc_subnet_ids" { 95 | } 96 | -------------------------------------------------------------------------------- /modules/aws/variables.tf: -------------------------------------------------------------------------------- 1 | variable "profile" { 2 | description = "AWS Profile" 3 | type = string 4 | default = "terraform" 5 | } 6 | 7 | variable "region" { 8 | description = "Region for AWS resources" 9 | type = string 10 | default = "us-east-1" 11 | } 12 | 13 | variable "ec2_enable" { 14 | description = "AWS Profile" 15 | type = bool 16 | default = true 17 | } 18 | 19 | variable "rds_enable" { 20 | description = "AWS Profile" 21 | type = bool 22 | default = true 23 | } 24 | 25 | variable "ec2_ssh_name" { 26 | description = "The SSH Key Name" 27 | type = string 28 | default = "free-tier-ec2-key" 29 | } 30 | 31 | variable "ec2_ssh_public" { 32 | description = "The local path to the SSH Public Key" 33 | type = string 34 | sensitive = true 35 | default = "~/.ssh-temp/id_rsa.pub" 36 | } 37 | 38 | variable "rds_user" { 39 | description = "Region for AWS resources" 40 | type = string 41 | sensitive = true 42 | default = "testing" 43 | } 44 | 45 | variable "rds_password" { 46 | description = "Region for the RDS database" 47 | type = string 48 | sensitive = true 49 | default = "testingdatabase89372934279" 50 | } 51 | -------------------------------------------------------------------------------- /modules/aws/vpc/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | vpc | terraform-aws-modules/vpc/aws | n/a | 7 | 8 | ### Inputs 9 | 10 | | Name | Description | Type | Default | 11 | |------|-------------|------|---------| 12 | | cidr | n/a | `string` | `"10.99"` | 13 | | db\_group\_create | n/a | `bool` | `true` | 14 | | name | Region for AWS resources | `string` | `"main-vpc"` | 15 | | nat | n/a | `bool` | `true` | 16 | | region | Region for AWS resources | `string` | n/a | 17 | | vpn | n/a | `bool` | `true` | 18 | 19 | ### Outputs 20 | 21 | | Name | Description | 22 | |------|-------------| 23 | | cidr\_block | n/a | 24 | | database\_subnets | n/a | 25 | | id | n/a | 26 | | public\_subnets | n/a | 27 | -------------------------------------------------------------------------------- /modules/aws/vpc/main.tf: -------------------------------------------------------------------------------- 1 | module "vpc" { 2 | source = "terraform-aws-modules/vpc/aws" 3 | 4 | name = var.name 5 | cidr = "${var.cidr}.0.0/18" 6 | 7 | azs = ["${var.region}a", "${var.region}b", "${var.region}c"] 8 | public_subnets = ["${var.cidr}.0.0/24", "${var.cidr}.1.0/24", "${var.cidr}.2.0/24"] 9 | private_subnets = ["${var.cidr}.3.0/24", "${var.cidr}.4.0/24", "${var.cidr}.5.0/24"] 10 | database_subnets = ["${var.cidr}.7.0/24", "${var.cidr}.8.0/24", "${var.cidr}.9.0/24"] 11 | 12 | create_database_subnet_group = var.db_group_create 13 | enable_nat_gateway = var.nat 14 | enable_vpn_gateway = var.vpn 15 | } 16 | -------------------------------------------------------------------------------- /modules/aws/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | output "id" { 2 | value = module.vpc.vpc_id 3 | } 4 | output "cidr_block" { 5 | value = module.vpc.vpc_cidr_block 6 | } 7 | output "database_subnets" { 8 | value = module.vpc.database_subnets 9 | } 10 | output "public_subnets" { 11 | value = module.vpc.public_subnets 12 | } 13 | -------------------------------------------------------------------------------- /modules/aws/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | description = "Region for AWS resources" 3 | type = string 4 | default = "main-vpc" 5 | } 6 | 7 | variable "cidr" { 8 | type = string 9 | default = "10.99" //10.99.0.0/18 10 | } 11 | 12 | variable "region" { 13 | description = "Region for AWS resources" 14 | type = string 15 | } 16 | 17 | variable "db_group_create" { 18 | type = bool 19 | default = true 20 | } 21 | 22 | variable "vpn" { 23 | type = bool 24 | default = true 25 | } 26 | variable "nat" { 27 | type = bool 28 | default = true 29 | } -------------------------------------------------------------------------------- /modules/azure/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | compute | ./compute | n/a | 7 | | networking | ./vpc | n/a | 8 | 9 | ### Inputs 10 | 11 | | Name | Description | Type | Default | 12 | |------|-------------|------|---------| 13 | | database\_db\_name | n/a | `string` | `"mydatabase"` | 14 | | database\_name | n/a | `string` | `"myapp"` | 15 | | database\_password | n/a | `string` | `"P@ssw0rd12345!"` | 16 | | database\_user | n/a | `string` | `"mradministrator"` | 17 | | ldns\_server | n/a | `string` | `"uniquename"` | 18 | | linux\_name | n/a | `string` | `"linux-pc"` | 19 | | location | n/a | `string` | `"East US"` | 20 | | resource\_group\_name | n/a | `string` | `"my-azure-group"` | 21 | | wdns\_server | n/a | `string` | `"uniquename2"` | 22 | | windows\_name | n/a | `string` | `"windows-pc"` | 23 | 24 | ### Outputs 25 | 26 | No outputs. 27 | 28 | -------------------------------------------------------------------------------- /modules/azure/compute/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | linuxservers | Azure/compute/azurerm | n/a | 7 | | windowsservers | Azure/compute/azurerm | n/a | 8 | 9 | ### Inputs 10 | 11 | | Name | Description | Type | Default | 12 | |------|-------------|------|---------| 13 | | linux\_dns\_server | n/a | `string` | `"linsimplevmips"` | 14 | | linux\_hostname | n/a | `string` | `"mywinvm"` | 15 | | linux\_password | n/a | `string` | `"mywinvj33j4k3"` | 16 | | resource\_group\_name | n/a | `string` | n/a | 17 | | subnet\_id | n/a | `string` | `"dev"` | 18 | | windows\_dns\_server | n/a | `string` | `"winsimplevmips"` | 19 | | windows\_hostname | n/a | `string` | `"mywinvm"` | 20 | | windows\_password | n/a | `string` | `"ComplxP@ssw0rd!"` | 21 | 22 | ### Outputs 23 | 24 | | Name | Description | 25 | |------|-------------| 26 | | linux\_vm\_public\_name | n/a | 27 | | windows\_vm\_public\_name | n/a | 28 | 29 | -------------------------------------------------------------------------------- /modules/azure/compute/main.tf: -------------------------------------------------------------------------------- 1 | module "linuxservers" { 2 | source = "Azure/compute/azurerm" 3 | resource_group_name = var.resource_group_name 4 | vm_os_simple = "UbuntuServer" 5 | public_ip_dns = [var.linux_dns_server] // change to a unique name per datacenter region 6 | vnet_subnet_id = var.subnet_id //module.network.vnet_subnets[0] 7 | 8 | //depends_on = [azurerm_resource_group.example] 9 | } 10 | 11 | module "windowsservers" { 12 | source = "Azure/compute/azurerm" 13 | resource_group_name = var.resource_group_name 14 | is_windows_image = true 15 | vm_hostname = var.windows_hostname // line can be removed if only one VM module per resource group 16 | admin_password = var.windows_password 17 | vm_os_simple = "WindowsServer" 18 | public_ip_dns = [var.windows_dns_server] // change to a unique name per datacenter region 19 | vnet_subnet_id = var.subnet_id // module.network.vnet_subnets[0] 20 | 21 | //depends_on = [azurerm_resource_group.example] 22 | } 23 | 24 | -------------------------------------------------------------------------------- /modules/azure/compute/outputs.tf: -------------------------------------------------------------------------------- 1 | output "linux_vm_public_name" { 2 | value = module.linuxservers.public_ip_dns_name 3 | } 4 | 5 | output "windows_vm_public_name" { 6 | value = module.windowsservers.public_ip_dns_name 7 | } 8 | -------------------------------------------------------------------------------- /modules/azure/compute/variables.tf: -------------------------------------------------------------------------------- 1 | variable "windows_password" { 2 | type = string 3 | default = "ComplxP@ssw0rd!" 4 | } 5 | 6 | variable "windows_hostname" { 7 | type = string 8 | default = "mywinvm" 9 | } 10 | 11 | variable "windows_dns_server" { 12 | type = string 13 | default = "winsimplevmips" 14 | } 15 | 16 | variable "linux_hostname" { 17 | type = string 18 | default = "mywinvm" 19 | } 20 | 21 | variable "linux_password" { 22 | type = string 23 | default = "mywinvj33j4k3" 24 | } 25 | variable "linux_dns_server" { 26 | type = string 27 | default = "linsimplevmips" 28 | } 29 | 30 | variable "subnet_id" { 31 | type = string 32 | default = "dev" 33 | } 34 | 35 | variable "resource_group_name" { 36 | type = string 37 | } 38 | -------------------------------------------------------------------------------- /modules/azure/db/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | database | Azure/database/azurerm | n/a | 7 | 8 | ### Inputs 9 | 10 | | Name | Description | Type | Default | 11 | |------|-------------|------|---------| 12 | | db\_name | n/a | `string` | `"mydatabase"` | 13 | | location | n/a | `string` | `"westus"` | 14 | | name | n/a | `string` | `"myapp"` | 15 | | sql\_password | n/a | `string` | `"P@ssw0rd12345!"` | 16 | | sql\_user | n/a | `string` | `"mradministrator"` | 17 | 18 | ### Outputs 19 | 20 | | Name | Description | 21 | |------|-------------| 22 | | connection\_url | n/a | 23 | | sql\_name | n/a | 24 | 25 | -------------------------------------------------------------------------------- /modules/azure/db/main.tf: -------------------------------------------------------------------------------- 1 | module "database" { 2 | source = "Azure/database/azurerm" 3 | resource_group_name = var.name 4 | location = var.location 5 | db_name = var.db_name 6 | sql_username = var.sql_user 7 | sql_password = var.sql_password 8 | } 9 | 10 | -------------------------------------------------------------------------------- /modules/azure/db/outputs.tf: -------------------------------------------------------------------------------- 1 | 2 | output "sql_name" { 3 | value = module.database.database_name 4 | } 5 | 6 | output "connection_url" { 7 | value = module.database.connection_string 8 | } 9 | 10 | -------------------------------------------------------------------------------- /modules/azure/db/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | type = string 3 | default = "myapp" 4 | } 5 | 6 | variable "location" { 7 | type = string 8 | default = "westus" 9 | } 10 | 11 | variable "db_name" { 12 | type = string 13 | default = "mydatabase" 14 | } 15 | 16 | variable "sql_user" { 17 | type = string 18 | default = "mradministrator" 19 | } 20 | 21 | variable "sql_password" { 22 | type = string 23 | default = "P@ssw0rd12345!" 24 | } 25 | 26 | -------------------------------------------------------------------------------- /modules/azure/main.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "azurerm_resource_group" "default" { 3 | name = var.resource_group_name 4 | location = var.location 5 | } 6 | 7 | module "networking" { 8 | depends_on = [azurerm_resource_group.default] 9 | resource_group_name = var.resource_group_name 10 | location = var.location 11 | source = "./vpc" 12 | } 13 | 14 | // module "database" { 15 | // source = "./db" 16 | // location = var.location 17 | // name = var.database_name 18 | // db_name = var.database_db_name 19 | // sql_username = var.database_user 20 | // depends_on = [ 21 | // azurerm_resource_group.default, 22 | // networking.default 23 | // ] 24 | // } 25 | 26 | module "compute" { 27 | source = "./compute" 28 | resource_group_name = var.resource_group_name 29 | windows_hostname = var.windows_name 30 | linux_hostname = var.linux_name 31 | windows_dns_server = var.wdns_server 32 | linux_dns_server = var.ldns_server 33 | subnet_id = module.networking.vpc_id 34 | depends_on = [azurerm_resource_group.default] 35 | } 36 | -------------------------------------------------------------------------------- /modules/azure/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/modules/azure/outputs.tf -------------------------------------------------------------------------------- /modules/azure/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group_name" { 2 | type = string 3 | default = "my-azure-group" 4 | } 5 | 6 | variable "location" { 7 | type = string 8 | default = "East US" 9 | } 10 | 11 | variable "database_name" { 12 | type = string 13 | default = "myapp" 14 | } 15 | 16 | variable "database_db_name" { 17 | type = string 18 | default = "mydatabase" 19 | } 20 | 21 | variable "database_user" { 22 | type = string 23 | default = "mradministrator" 24 | } 25 | 26 | variable "database_password" { 27 | type = string 28 | default = "P@ssw0rd12345!" 29 | } 30 | 31 | variable "ldns_server" { 32 | type = string 33 | default = "uniquename" 34 | } 35 | 36 | variable "wdns_server" { 37 | type = string 38 | default = "uniquename2" 39 | } 40 | 41 | variable "windows_name" { 42 | type = string 43 | default = "windows-pc" 44 | } 45 | 46 | variable "linux_name" { 47 | type = string 48 | default = "linux-pc" 49 | } -------------------------------------------------------------------------------- /modules/azure/vpc/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | location | Azure's specific deployment location. [Azure Terraform Provider Docs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group#location) | `string` | n/a | 11 | | resource\_group\_name | The name which should be used for a specific resource group. [Azure Terraform Provider Docs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group#name) | `string` | n/a | 12 | 13 | ### Outputs 14 | 15 | | Name | Description | 16 | |------|-------------| 17 | | vpc\_id | The id of the newly created vNet | 18 | | vpc\_location | The location of the newly created vNet | 19 | | vpc\_name | The name of the newly created vNet | 20 | | vpc\_space | The address space of the newly created vNet | 21 | 22 | -------------------------------------------------------------------------------- /modules/azure/vpc/main.tf: -------------------------------------------------------------------------------- 1 | resource "azurerm_virtual_network" "example" { 2 | name = "virtualNetwork1" 3 | location = var.location 4 | resource_group_name = var.resource_group_name 5 | address_space = ["10.0.0.0/16"] 6 | dns_servers = ["10.0.0.4", "10.0.0.5"] 7 | subnet { 8 | name = "subnet1" 9 | address_prefix = "10.0.1.0/24" 10 | } 11 | } 12 | 13 | resource "azurerm_network_security_group" "ssh" { 14 | name = "ssh" 15 | resource_group_name = var.resource_group_name 16 | location = var.location 17 | security_rule { 18 | name = "test123" 19 | priority = 100 20 | direction = "Inbound" 21 | access = "Allow" 22 | protocol = "Tcp" 23 | source_port_range = "*" 24 | destination_port_range = "22" 25 | source_address_prefix = "*" 26 | destination_address_prefix = "*" 27 | } 28 | 29 | } 30 | 31 | resource "azurerm_route_table" "example" { 32 | name = "MyRouteTable" 33 | resource_group_name = var.resource_group_name 34 | location = var.location 35 | } 36 | 37 | resource "azurerm_route" "example" { 38 | name = "acceptanceTestRoute1" 39 | resource_group_name = var.resource_group_name 40 | route_table_name = azurerm_route_table.example.name 41 | address_prefix = "10.1.0.0/16" 42 | next_hop_type = "vnetlocal" 43 | } 44 | 45 | -------------------------------------------------------------------------------- /modules/azure/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | description = "The id of the newly created vNet" 3 | value = azurerm_virtual_network.example.id 4 | } 5 | 6 | output "vpc_name" { 7 | description = "The name of the newly created vNet" 8 | value = azurerm_virtual_network.example.name 9 | } 10 | 11 | output "vpc_location" { 12 | description = "The location of the newly created vNet" 13 | value = azurerm_virtual_network.example.location 14 | } 15 | 16 | output "vpc_space" { 17 | description = "The address space of the newly created vNet" 18 | value = azurerm_virtual_network.example.address_space 19 | } 20 | -------------------------------------------------------------------------------- /modules/azure/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group_name" { 2 | type = string 3 | description = "The name which should be used for a specific resource group. [Azure Terraform Provider Docs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group#name)" 4 | } 5 | 6 | variable "location" { 7 | type = string 8 | description = "Azure's specific deployment location. [Azure Terraform Provider Docs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group#location)" 9 | } 10 | -------------------------------------------------------------------------------- /modules/gcp/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | | Name | Source | Version | 5 | |------|--------|---------| 6 | | gcp\_firewall | ./firewall | n/a | 7 | | gcp\_instance | ./compute | n/a | 8 | | gcp\_storage | ./storage | n/a | 9 | | gcp\_vpc | ./vpc | n/a | 10 | 11 | ### Inputs 12 | 13 | | Name | Description | Type | Default | 14 | |------|-------------|------|---------| 15 | | bucket\_name | Public name of your storage bucket on GCP. [Naming guidelines for Storage Buckets \| GCP Docs](https://cloud.google.com/storage/docs/naming-buckets) | `string` | `"averynoncommonbuck"` | 16 | | firestore\_name | Your instance's network on GCP. | `string` | `"firestore-db-1"` | 17 | | gcp\_project\_id | Google Cloud SDK project's ID number identifier. [Indetifying projects \| GCP Docs](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects) | `string` | n/a | 18 | | google\_project | n/a | `string` | `""` | 19 | | instance\_name | GCP Compute Instance Name. [Resource Naming Convention \| GCP Compute Docs](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"example-machine"` | 20 | | network\_name | Creates and names a VPC network. A VPC network is not the same as a GCP Subnetwork, see: [VPC Network Overview \| GCP Docs](https://cloud.google.com/vpc/docs/vpc#vpc_networks_and_subnets) | `string` | `"gcp-network2"` | 21 | | permissions | Your instance's network on GCP. | `string` | `"publicread"` | 22 | | project\_region | Identifier for default resource location based on GCP region naming convention. [Regions and Zones \| GCP Docs](https://cloud.google.com/compute/docs/regions-zones) | `string` | `"us-west1"` | 23 | 24 | ### Outputs 25 | 26 | | Name | Description | 27 | |------|-------------| 28 | | machine\_ip | n/a | 29 | 30 | -------------------------------------------------------------------------------- /modules/gcp/compute/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | disk\_size | Allocated GB's of disk to your GCE instance | `number` | `30` | 11 | | disk\_type | Storage Disk Type. [GCP Official documentation](https://cloud.google.com/compute/docs/disks#disk-types) | `string` | `"pd-standard"` | 12 | | image | Image to initialize your GCE Instance, a full list of options [is available on GCP's official documentation](https://cloud.google.com/compute/docs/images) | `string` | `"debian-cloud/debian-10"` | 13 | | ip\_addr | The IP address that will be 1:1 mapped to the instance's network ip. If not given, one will be generated. [Docs Ref.](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#access_config) | `string` | `null` | 14 | | name | A name for GCP's Virtual Machine instance. [Naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"private"` | 15 | | network\_name | GCP Network Name. [Oficial GCP Documentation](https://cloud.google.com/compute/docs/machine-types) - [Terraform provider Documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#machine_type) | `string` | `"example-network"` | 16 | | region | Zone location of your instance, you can choose a region on [GCP's Official Documentation](https://cloud.google.com/compute/docs/regions-zones#available) - [Terraform provider documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#zone) | `string` | `"us-west1"` | 17 | | type | GCP Instance Machine type. [Oficial GCP Documentation](https://cloud.google.com/compute/docs/machine-types) - [Terraform provider Documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#machine_type) | `string` | `"e2-micro"` | 18 | 19 | ### Outputs 20 | 21 | | Name | Description | 22 | |------|-------------| 23 | | external\_ip | n/a | 24 | | instance\_id | n/a | 25 | | internal\_ip | n/a | 26 | | resulting\_name | n/a | 27 | | resulting\_type | n/a | 28 | 29 | -------------------------------------------------------------------------------- /modules/gcp/compute/main.tf: -------------------------------------------------------------------------------- 1 | resource "google_compute_instance" "gcp_example" { 2 | name = var.name 3 | machine_type = var.type 4 | zone = "${var.region}-b" 5 | 6 | allow_stopping_for_update = true 7 | 8 | boot_disk { 9 | initialize_params { 10 | image = var.image 11 | size = var.disk_size 12 | type = var.disk_type 13 | } 14 | } 15 | 16 | network_interface { 17 | network = var.network_name 18 | access_config { 19 | nat_ip = var.ip_addr 20 | } 21 | } 22 | tags = [ 23 | "web", 24 | "ssh" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /modules/gcp/compute/outputs.tf: -------------------------------------------------------------------------------- 1 | output "instance_id" { 2 | value = google_compute_instance.gcp_example.instance_id 3 | } 4 | output "internal_ip" { 5 | value = google_compute_instance.gcp_example.network_interface.0.network_ip 6 | sensitive = true 7 | } 8 | output "external_ip" { 9 | value = google_compute_instance.gcp_example.network_interface.0.access_config.0.nat_ip 10 | sensitive = true 11 | } 12 | output "resulting_name" { 13 | value = google_compute_instance.gcp_example.name 14 | sensitive = true 15 | } 16 | output "resulting_type" { 17 | value = google_compute_instance.gcp_example.machine_type 18 | sensitive = true 19 | } 20 | -------------------------------------------------------------------------------- /modules/gcp/compute/variables.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | type = string 3 | default = "private" 4 | description = "A name for GCP's Virtual Machine instance. [Naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 5 | validation { 6 | condition = can(regex("^[a-z0-9][-a-z0-9]*[a-z0-9]$", var.name)) 7 | error_message = "The instance name can contain only dashes, lowercase letters, and numbers. It must be at least 2 characters and can neither start nor end with a dash." 8 | } 9 | } 10 | 11 | variable "type" { 12 | type = string 13 | default = "e2-micro" 14 | description = "GCP Instance Machine type. [Oficial GCP Documentation](https://cloud.google.com/compute/docs/machine-types) - [Terraform provider Documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#machine_type)" 15 | validation { 16 | condition = var.type == "e2-micro" 17 | error_message = "Error: Only `e2-micro` instances are elligible for the free Tier on GCP. `f1-micro` were deprecated as of August 2021." 18 | } 19 | } 20 | 21 | variable "region" { 22 | type = string 23 | default = "us-west1" 24 | description = "Zone location of your instance, you can choose a region on [GCP's Official Documentation](https://cloud.google.com/compute/docs/regions-zones#available) - [Terraform provider documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#zone)" 25 | validation { 26 | condition = can(index(["us-west1", "us-central1", "us-east1"], var.region)) 27 | error_message = "Error: Only U.S. regions are available for the free tier GCE instances." 28 | } 29 | } 30 | 31 | variable "image" { 32 | type = string 33 | default = "debian-cloud/debian-10" 34 | description = "Image to initialize your GCE Instance, a full list of options [is available on GCP's official documentation](https://cloud.google.com/compute/docs/images)" 35 | } 36 | 37 | variable "disk_size" { 38 | type = number 39 | default = 30 40 | description = "Allocated GB's of disk to your GCE instance" 41 | validation { 42 | condition = var.disk_size > 10 || var.disk_size < 30 43 | error_message = "Error: Minimum disk size is 10GB (for most Linux OS) and the Free tier maximum disk size is 30GB." 44 | } 45 | } 46 | 47 | variable "disk_type" { 48 | type = string 49 | default = "pd-standard" 50 | description = "Storage Disk Type. [GCP Official documentation](https://cloud.google.com/compute/docs/disks#disk-types)" 51 | validation { 52 | condition = var.disk_type == "pd-standard" 53 | error_message = "Error: Only Standard Persistent Disks ('pd-standard') are elligible for the free tier on GCP." 54 | } 55 | } 56 | 57 | variable "network_name" { 58 | type = string 59 | default = "example-network" 60 | description = "GCP Network Name. [Oficial GCP Documentation](https://cloud.google.com/compute/docs/machine-types) - [Terraform provider Documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#machine_type)" 61 | } 62 | 63 | variable "ip_addr" { 64 | type = string 65 | default = null 66 | sensitive = true 67 | description = "The IP address that will be 1:1 mapped to the instance's network ip. If not given, one will be generated. [Docs Ref.](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#access_config)" 68 | } 69 | -------------------------------------------------------------------------------- /modules/gcp/firewall/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | firewall\_ssh\_name | A name for your firewall rule that allows access to the port 22, used for SSH connections. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"allow-ssh"` | 11 | | firewall\_web\_name | A name for your firewall rule that allows acces to both ports 80 and 443, used for common web applications. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"allow-web"` | 12 | | network\_name | Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"gcp-internal-network"` | 13 | 14 | ### Outputs 15 | 16 | No outputs. 17 | 18 | -------------------------------------------------------------------------------- /modules/gcp/firewall/main.tf: -------------------------------------------------------------------------------- 1 | resource "google_compute_firewall" "allow_web" { 2 | name = var.firewall_web_name 3 | network = var.network_name 4 | 5 | 6 | allow { 7 | protocol = "tcp" 8 | ports = ["80", "443"] 9 | } 10 | 11 | source_ranges = ["0.0.0.0/0"] 12 | target_tags = ["web"] 13 | } 14 | 15 | resource "google_compute_firewall" "allow_ssh" { 16 | name = var.firewall_ssh_name 17 | network = var.network_name 18 | 19 | allow { 20 | protocol = "tcp" 21 | ports = ["22"] 22 | } 23 | 24 | source_ranges = ["0.0.0.0/0"] 25 | target_tags = ["ssh"] 26 | } 27 | -------------------------------------------------------------------------------- /modules/gcp/firewall/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/modules/gcp/firewall/outputs.tf -------------------------------------------------------------------------------- /modules/gcp/firewall/variables.tf: -------------------------------------------------------------------------------- 1 | variable "firewall_web_name" { 2 | type = string 3 | default = "allow-web" 4 | description = "A name for your firewall rule that allows acces to both ports 80 and 443, used for common web applications. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 5 | } 6 | 7 | variable "firewall_ssh_name" { 8 | type = string 9 | default = "allow-ssh" 10 | description = "A name for your firewall rule that allows access to the port 22, used for SSH connections. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 11 | } 12 | 13 | variable "network_name" { 14 | type = string 15 | sensitive = true 16 | default = "gcp-internal-network" 17 | description = "Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 18 | } 19 | -------------------------------------------------------------------------------- /modules/gcp/main.tf: -------------------------------------------------------------------------------- 1 | module "gcp_vpc" { 2 | vpc_name = var.network_name 3 | source = "./vpc" 4 | google_project = var.gcp_project_id 5 | } 6 | 7 | module "gcp_firewall" { 8 | depends_on = [ 9 | module.gcp_vpc.network_name 10 | ] 11 | source = "./firewall" 12 | network_name = module.gcp_vpc.network_name 13 | } 14 | 15 | module "gcp_instance" { 16 | depends_on = [ 17 | module.gcp_vpc.network_name, 18 | module.gcp_vpc.ipv4_add 19 | ] 20 | source = "./compute" 21 | name = var.instance_name 22 | region = var.project_region 23 | network_name = module.gcp_vpc.network_name 24 | } 25 | 26 | module "gcp_storage" { 27 | depends_on = [ 28 | module.gcp_vpc.network_name, 29 | module.gcp_instance.resulting_name, 30 | ] 31 | source = "./storage" 32 | region = var.project_region 33 | project_id = var.google_project 34 | name = var.bucket_name 35 | permissions = var.permissions 36 | firestore_name = var.firestore_name 37 | network_name = module.gcp_vpc.network_name 38 | } 39 | -------------------------------------------------------------------------------- /modules/gcp/outputs.tf: -------------------------------------------------------------------------------- 1 | output "machine_ip" { 2 | value = module.gcp_instance.external_ip 3 | sensitive = true 4 | } 5 | -------------------------------------------------------------------------------- /modules/gcp/storage/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | enable\_destroy | When deleting a bucket, this boolean option will delete all contained objects. If you try to delete a bucket that contains objects, Terraform will fail that run. | `bool` | `true` | 11 | | fire\_size | Your Firestore Database size in GB's. | `number` | `5` | 12 | | firestore\_name | Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"my-firestore"` | 13 | | name | Public name of your storage bucket on GCP. [Naming guidelines for Storage Buckets \| GCP Docs](https://cloud.google.com/storage/docs/naming-buckets) | `string` | `"regionaltftest"` | 14 | | network\_name | Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | n/a | 15 | | permissions | Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"publicread"` | 16 | | project\_id | Google Cloud SDK project's ID number identifier. [Indetifying projects \| GCP Docs](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects) | `string` | n/a | 17 | | region | Identifier for default resource location based on GCP region naming convention. [Regions and Zones \| GCP Docs](https://cloud.google.com/compute/docs/regions-zones) | `string` | `"us-west1"` | 18 | | storage\_class | [Storage Bucket Classes \| GCP Docs](https://cloud.google.com/storage/docs/storage-classes) \| [GCP Storage Classes on Terraform Provider](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/storage_bucket#storage_class) | `string` | `"STANDARD"` | 19 | | table\_name | Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"share1"` | 20 | 21 | ### Outputs 22 | 23 | | Name | Description | 24 | |------|-------------| 25 | | bucket\_name | Name of the GCS bucket that will receive the objects. | 26 | 27 | -------------------------------------------------------------------------------- /modules/gcp/storage/main.tf: -------------------------------------------------------------------------------- 1 | data "google_project" "current" { 2 | project_id = var.project_id 3 | } 4 | 5 | locals { 6 | default_role_entities = [ 7 | "OWNER:project-owners-${data.google_project.current.number}", 8 | "OWNER:project-editors-${data.google_project.current.number}", 9 | "READER:project-viewers-${data.google_project.current.number}", 10 | "READER:allUsers", 11 | ] 12 | } 13 | 14 | resource "google_storage_bucket" "default" { 15 | project = var.project_id 16 | name = var.name 17 | location = "US" 18 | storage_class = var.storage_class 19 | force_destroy = var.enable_destroy 20 | } 21 | 22 | resource "google_storage_bucket_acl" "default" { 23 | bucket = google_storage_bucket.default.name 24 | default_acl = var.permissions 25 | role_entity = local.default_role_entities 26 | } 27 | 28 | /* resource "google_filestore_instance" "instance" { 29 | provider = google-beta 30 | name = var.firestore_name 31 | zone = "${var.region}-b" 32 | tier = var.storage_class 33 | 34 | file_shares { 35 | capacity_gb = var.fire_size 36 | name = var.table_name 37 | 38 | nfs_export_options { 39 | ip_ranges = ["10.0.0.0/24"] 40 | access_mode = "READ_WRITE" 41 | squash_mode = "NO_ROOT_SQUASH" 42 | } 43 | 44 | nfs_export_options { 45 | ip_ranges = ["10.10.0.0/24"] 46 | access_mode = "READ_ONLY" 47 | squash_mode = "ROOT_SQUASH" 48 | anon_uid = 123 49 | anon_gid = 456 50 | } 51 | } 52 | 53 | networks { 54 | network = var.network_name 55 | modes = ["MODE_IPV4"] 56 | } 57 | } 58 | */ 59 | -------------------------------------------------------------------------------- /modules/gcp/storage/outputs.tf: -------------------------------------------------------------------------------- 1 | output "bucket_name" { 2 | description = "Name of the GCS bucket that will receive the objects." 3 | value = google_storage_bucket.default.name 4 | } 5 | /* output "firestore_id" { 6 | description = "Name of the GCS bucket that will receive the objects." 7 | value = google_filestore_instance.instance.id 8 | } 9 | */ 10 | -------------------------------------------------------------------------------- /modules/gcp/storage/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project_id" { 2 | type = string 3 | sensitive = true 4 | description = "Google Cloud SDK project's ID number identifier. [Indetifying projects | GCP Docs](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects)" 5 | } 6 | variable "name" { 7 | type = string 8 | default = "regionaltftest" 9 | description = "Public name of your storage bucket on GCP. [Naming guidelines for Storage Buckets | GCP Docs](https://cloud.google.com/storage/docs/naming-buckets)" 10 | } 11 | 12 | variable "storage_class" { 13 | type = string 14 | default = "STANDARD" 15 | description = "[Storage Bucket Classes | GCP Docs](https://cloud.google.com/storage/docs/storage-classes) | [GCP Storage Classes on Terraform Provider](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/storage_bucket#storage_class)" 16 | } 17 | 18 | variable "enable_destroy" { 19 | type = bool 20 | default = true 21 | description = "When deleting a bucket, this boolean option will delete all contained objects. If you try to delete a bucket that contains objects, Terraform will fail that run." 22 | } 23 | 24 | variable "permissions" { 25 | type = string 26 | default = "publicread" 27 | description = "Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 28 | } 29 | 30 | variable "firestore_name" { 31 | type = string 32 | default = "my-firestore" 33 | description = "Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 34 | } 35 | 36 | variable "region" { 37 | type = string 38 | default = "us-west1" 39 | description = "Identifier for default resource location based on GCP region naming convention. [Regions and Zones | GCP Docs](https://cloud.google.com/compute/docs/regions-zones)" 40 | } 41 | 42 | variable "fire_size" { 43 | type = number 44 | default = 5 45 | description = "Your Firestore Database size in GB's." 46 | } 47 | 48 | variable "table_name" { 49 | type = string 50 | default = "share1" 51 | description = "Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 52 | } 53 | 54 | variable "network_name" { 55 | type = string 56 | description = "Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 57 | } 58 | -------------------------------------------------------------------------------- /modules/gcp/variables.tf: -------------------------------------------------------------------------------- 1 | variable "google_project" { 2 | type = string 3 | default = "" 4 | } 5 | 6 | variable "gcp_project_id" { 7 | description = "Google Cloud SDK project's ID number identifier. [Indetifying projects | GCP Docs](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects)" 8 | type = string 9 | sensitive = true 10 | } 11 | 12 | variable "instance_name" { 13 | type = string 14 | default = "example-machine" 15 | description = "GCP Compute Instance Name. [Resource Naming Convention | GCP Compute Docs](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 16 | } 17 | 18 | variable "project_region" { 19 | type = string 20 | default = "us-west1" 21 | description = "Identifier for default resource location based on GCP region naming convention. [Regions and Zones | GCP Docs](https://cloud.google.com/compute/docs/regions-zones)" 22 | } 23 | 24 | variable "network_name" { 25 | type = string 26 | default = "gcp-network2" 27 | description = "Creates and names a VPC network. A VPC network is not the same as a GCP Subnetwork, see: [VPC Network Overview | GCP Docs](https://cloud.google.com/vpc/docs/vpc#vpc_networks_and_subnets)" 28 | } 29 | 30 | variable "bucket_name" { 31 | type = string 32 | default = "averynoncommonbuck" 33 | description = "Public name of your storage bucket on GCP. [Naming guidelines for Storage Buckets | GCP Docs](https://cloud.google.com/storage/docs/naming-buckets)" 34 | } 35 | 36 | variable "permissions" { 37 | type = string 38 | default = "publicread" 39 | description = "Your instance's network on GCP." 40 | } 41 | 42 | variable "firestore_name" { 43 | type = string 44 | default = "firestore-db-1" 45 | description = "Your instance's network on GCP." 46 | } 47 | -------------------------------------------------------------------------------- /modules/gcp/vpc/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Modules 3 | 4 | No modules. 5 | 6 | ### Inputs 7 | 8 | | Name | Description | Type | Default | 9 | |------|-------------|------|---------| 10 | | google\_project | Your static IP network resource name on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | n/a | 11 | | vpc\_name | Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format) | `string` | `"gcp-internal-network"` | 12 | 13 | ### Outputs 14 | 15 | | Name | Description | 16 | |------|-------------| 17 | | network\_name | n/a | 18 | 19 | -------------------------------------------------------------------------------- /modules/gcp/vpc/main.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "google_compute_network" "default" { 3 | name = var.vpc_name 4 | auto_create_subnetworks = "true" 5 | project = var.google_project 6 | } 7 | 8 | output "network_name" { 9 | value = google_compute_network.default.name 10 | } 11 | -------------------------------------------------------------------------------- /modules/gcp/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_name" { 2 | type = string 3 | default = "gcp-internal-network" 4 | description = "Your instance's network on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 5 | } 6 | 7 | variable "google_project" { 8 | type = string 9 | description = "Your static IP network resource name on GCP. [GCP's Official documentation on naming resources](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 10 | } 11 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "s3_backend_domain" { 2 | value = module.terraform_state_backend.s3_bucket_domain_name 3 | description = "Domain name of the S3 bucket created on AWS as part of the backend infrastructure" 4 | sensitive = true 5 | } 6 | 7 | output "s3_backend_bucket" { 8 | description = "ID of the resulting S3 bucket created on AWS as part of the backend infrastructure" 9 | value = module.terraform_state_backend.s3_bucket_id 10 | sensitive = true 11 | } 12 | 13 | output "db_backend_name" { 14 | description = "Name of the resulting DynamoDB created for locking state files." 15 | value = module.terraform_state_backend.dynamodb_table_name 16 | sensitive = true 17 | } 18 | 19 | output "gcp_public_ip" { 20 | description = "GCP VM Compute IPv4 Public Address" 21 | value = module.google_cloud.machine_ip 22 | sensitive = true 23 | } 24 | 25 | output "aws_ec2_public_ip" { 26 | description = "AWS EC2 IPv4 Public Address" 27 | value = module.aws.ec2_public_ip 28 | sensitive = true 29 | } 30 | 31 | output "aws_ec2_ipv6_addresses" { 32 | description = "AWS EC2 IPv6 Public Address" 33 | value = module.aws.ec2_ipv6_addresses 34 | sensitive = true 35 | } 36 | 37 | output "aws_ec2_private_ip" { 38 | description = "AWS EC2 assigned Private IP" 39 | value = module.aws.ec2_private_ip 40 | sensitive = true 41 | } 42 | 43 | output "aws_ec2_password_data" { 44 | description = "List of Base-64 encoded encrypted password data for AWS EC2 instances" 45 | value = module.aws.ec2_password_data 46 | sensitive = true 47 | } 48 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /scripts/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p ~/.ssh 3 | chmod 700 ~/.ssh 4 | echo -e "Host *\n\tStrictHostKeyChecking no\n\tIdentityFile ~/ssh_key\n\n" > ~/.ssh/config 5 | ssh-keygen -t rsa -b 4096 -C "${GITHUB_EMAIL}" -N '${GITHUB_USER}' -f /root/.ssh/id_rsa 6 | git config --global url.'https://${GITHUB_USER}:${GITHUB_KEY}@github.com'.insteadOf 'https://github.com' 7 | 8 | if [ -f ~/.gcloud/credentials.json ]; then 9 | export GOOGLE_APPLICATION_CREDENTIALS=~/.gcloud/credentials.json 10 | fi 11 | if [ -f /project/credentials/gcp.json ]; then 12 | export GOOGLE_APPLICATION_CREDENTIALS=/project/credentials/gcp.json 13 | fi 14 | export GOOGLE_PROJECT=$GCP_PROJECT_ID 15 | #exec ./bin "$@" 16 | clear 17 | curl -sL https://git.io/_has | bash -s git tfscan \ 18 | tfsec terraform-docs terraform go task 19 | exec "$@" 20 | -------------------------------------------------------------------------------- /scripts/plan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if echo "$AWS_DEFAULT_REGION" | grep -q "$AWS_DEFAULT_REGION"; then 3 | echo "Adding default region key" 4 | echo "aws_default_region = $AWS_DEAFULT_REGION" >> terraform.tfvars 5 | else 6 | echo "No region was set." 7 | fi 8 | 9 | if echo "$AWS_ACCOUNT_ID" | grep -q "$AWS_ACCOUNT_ID"; then 10 | echo "Adding AWS account ID" 11 | echo "aws_account_id = $AWS_ACCOUNT_ID" >> terraform.tfvars 12 | else 13 | echo "No account ID was set." 14 | fi 15 | 16 | if echo "$AWS_SECRET_ACCESS_KEY" | grep -q "$AWS_SECRET_ACCESS_KEY"; then 17 | echo "Adding secret account key" 18 | echo "aws_account_key = $AWS_SECRET_ACCESS_KEY" >> terraform.tfvars 19 | else 20 | echo "No secret key was set." 21 | fi 22 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | awscli==1.25.47 2 | -------------------------------------------------------------------------------- /scripts/slim.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/scripts/slim.yml -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "stdout: passed" 5 | >&2 echo -e "stderr: building error" -------------------------------------------------------------------------------- /tasks/aws.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | vars: 3 | PATH_ERROR: is not installed or correctly configured in PATH. 4 | 5 | silent: true 6 | 7 | tasks: 8 | init: 9 | desc: Bootstrapping AWS provider testing files 10 | cmds: 11 | - cd test/aws && rm go.mod || true 12 | - cd test/aws && rm go.sum || true 13 | - cd test/aws && go mod init "github.com/gruberdev/tf-free" && go mod tidy 14 | 15 | test: 16 | deps: 17 | - init 18 | desc: Terraform testing (AWS provider) 19 | cmds: 20 | - cd test/aws && go test -v -timeout 10m -run TestUnitEC2 21 | - cd test/aws && go test -v -timeout 10m -run TestUnitRDS 22 | 23 | test:unit:ec2: 24 | deps: 25 | - aws-init 26 | cmds: 27 | - cd test/aws && go test -v -timeout 15m -run TestUnitEC2 28 | 29 | test:unit:rds: 30 | deps: 31 | - aws-init 32 | cmds: 33 | - cd test/aws && go test -v -timeout 30m -run TestUnitRDS 34 | 35 | apply: 36 | desc: Terraform standard initialization 37 | cmds: 38 | - cd modules/aws && terraform apply -auto-approve 39 | 40 | destroy:db: 41 | desc: Terraform standard initialization 42 | cmds: 43 | - terraform destroy -target module.aws.module.rds.aws_db_instance.rds -auto-approve 44 | -------------------------------------------------------------------------------- /tasks/clean.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | vars: 3 | PATH_ERROR: is not installed or correctly configured in PATH. 4 | 5 | silent: true 6 | 7 | tasks: 8 | aws: 9 | env: 10 | AWS_DEFAULT_REGION: "us-east-1" 11 | preconditions: 12 | - sh: 'which awsweeper' 13 | msg: 'kustomize {{.PATH_ERROR}}' 14 | cmds: 15 | - awsweeper config/aws-filter.yaml 16 | silent: true 17 | 18 | gcp: 19 | preconditions: 20 | - sh: 'which gcloud' 21 | msg: 'kustomize {{.PATH_ERROR}}' 22 | cmds: 23 | - docker run --rm --name cloudblaster -w /config -v ./config:/config docker.io/grubertech/cloudblaster:0.1 24 | silent: true 25 | -------------------------------------------------------------------------------- /tasks/docker.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gruberdev/tf-free/c0311e73485e8f151172cbf97a25b1c52a28676a/tasks/docker.yaml -------------------------------------------------------------------------------- /tasks/gcp.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | vars: 3 | PATH_ERROR: is not installed or correctly configured in PATH. 4 | 5 | silent: true 6 | 7 | tasks: 8 | init:test: 9 | desc: test 10 | cmds: 11 | - cd test/gcp && rm go.mod || true 12 | - cd test/gcp && rm go.sum || true 13 | - cd test/gcp && go mod init "github.com/gruberdev/tf-free" || true 14 | - cd test/gcp && go mod tidy || true 15 | 16 | test: 17 | desc: Terraform testing (GCP provider) 18 | deps: 19 | - task: init:test 20 | - task: init 21 | - task: test:unit:network 22 | - task: test:unit:compute 23 | - task: test:unit:storage 24 | cmds: 25 | - cd test/gcp && go test -v -timeout 10m -run TestIntegrationGCP 26 | 27 | test:unit:compute: 28 | deps: 29 | - init 30 | cmds: 31 | - cd test/gcp && go test -v -timeout 5m -run TestUnitCompute 32 | 33 | test:unit:storage: 34 | deps: 35 | - init 36 | cmds: 37 | - cd test/gcp && go test -v -timeout 5m -run TestUnitStorage 38 | 39 | test:unit:network: 40 | deps: 41 | - init 42 | cmds: 43 | - cd test/gcp && go test -v -timeout 5m -run TestUnitVPC 44 | 45 | apply: 46 | desc: Terraform standard initialization 47 | cmds: 48 | - cd modules/gcp && terraform apply -auto-approve 49 | 50 | destroy: 51 | desc: Terraform standard initialization 52 | cmds: 53 | - cd modules/gcp && terraform destroy -auto-approve 54 | 55 | init: 56 | desc: Login into Google Cloud Platform 57 | cmds: 58 | - gcloud auth application-default login 59 | -------------------------------------------------------------------------------- /test/aws/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Requirements 3 | 4 | No requirements. 5 | 6 | ## Providers 7 | 8 | No providers. 9 | 10 | ## Modules 11 | 12 | No modules. 13 | 14 | ## Resources 15 | 16 | No resources. 17 | 18 | ## Inputs 19 | 20 | No inputs. 21 | 22 | ## Outputs 23 | 24 | No outputs. 25 | -------------------------------------------------------------------------------- /test/aws/ec2_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | 8 | "github.com/gruntwork-io/terratest/modules/aws" 9 | "github.com/gruntwork-io/terratest/modules/environment" 10 | http_helper "github.com/gruntwork-io/terratest/modules/http-helper" 11 | "github.com/gruntwork-io/terratest/modules/random" 12 | "github.com/gruntwork-io/terratest/modules/ssh" 13 | "github.com/gruntwork-io/terratest/modules/terraform" 14 | ) 15 | 16 | var accessList = []string{ 17 | "AWS_ACCESS_KEY_ID", 18 | } 19 | 20 | var secretList = []string{ 21 | "AWS_SECRET_ACCESS_KEY", 22 | } 23 | 24 | func TestUnitEC2(t *testing.T) { 25 | t.Parallel() 26 | sshName := fmt.Sprintf("ssh-key-%s", random.UniqueId()) 27 | // Pick a random AWS region to test in. This helps ensure your code works in all regions. 28 | awsRegion := aws.GetRandomStableRegion(t, []string{"us-east-1"}, nil) 29 | awsAvailability := aws.GetAvailabilityZones(t, awsRegion) 30 | awsAccessID := environment.GetFirstNonEmptyEnvVarOrEmptyString(t, accessList) 31 | awsSecretKey := environment.GetFirstNonEmptyEnvVarOrEmptyString(t, secretList) 32 | // retryable errors in terraform testing. 33 | keyPair := ssh.GenerateRSAKeyPair(t, 2048) 34 | amiID := aws.GetUbuntu1604Ami(t, awsRegion) 35 | keyPublic := fmt.Sprintf("%s", keyPair.PublicKey) 36 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 37 | // website::tag::1:: The path to where our Terraform code is located 38 | TerraformDir: "../../examples/aws/unit/ec2", 39 | // Environment variables to set when running Terraform 40 | Vars: map[string]interface{}{ 41 | "aws_default_region": awsRegion, 42 | "ssh_name": sshName, 43 | "ssh_public": keyPublic, 44 | "subnet_region": awsAvailability[0], 45 | "ami_id": amiID, 46 | }, 47 | EnvVars: map[string]string{ 48 | "AWS_DEFAULT_REGION": awsRegion, 49 | "AWS_ACCESS_KEY_ID": awsAccessID, 50 | "AWS_SECRET_ACCESS_KEY": awsSecretKey, 51 | }, 52 | }) 53 | 54 | // At the end of the test, run `terraform destroy` to clean up any resources that were created 55 | defer terraform.Destroy(t, terraformOptions) 56 | 57 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors 58 | terraform.InitAndApply(t, terraformOptions) 59 | publicIp := terraform.Output(t, terraformOptions, "public_ip") 60 | 61 | // website::tag::5:: Make an HTTP request to the instance and make sure we get back a 200 OK with the body "Hello, World!" 62 | url := fmt.Sprintf("http://%s:80", publicIp) 63 | http_helper.HttpGetWithRetry(t, url, nil, 200, "Hello, World!", 30, 5*time.Second) 64 | } 65 | -------------------------------------------------------------------------------- /test/aws/network_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/aws" 7 | "github.com/gruntwork-io/terratest/modules/terraform" 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | // An example of how to test the Terraform module in examples/terraform-aws-network-example using Terratest. 13 | func TestUnitAWSNetworking(t *testing.T) { 14 | t.Parallel() 15 | 16 | // Pick a random AWS region to test in. This helps ensure your code works in all regions. 17 | awsRegion := aws.GetRandomStableRegion(t, nil, nil) 18 | 19 | // Give the VPC and the subnets correct CIDRs 20 | vpcCidr := "10.10.0.0/16" 21 | privateSubnetCidr := "10.10.1.0/24" 22 | publicSubnetCidr := "10.10.2.0/24" 23 | 24 | // Construct the terraform options with default retryable errors to handle the most common retryable errors in 25 | // terraform testing. 26 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 27 | // The path to where our Terraform code is located 28 | TerraformDir: "../examples/terraform-aws-network-example", 29 | 30 | // Variables to pass to our Terraform code using -var options 31 | Vars: map[string]interface{}{ 32 | "main_vpc_cidr": vpcCidr, 33 | "private_subnet_cidr": privateSubnetCidr, 34 | "public_subnet_cidr": publicSubnetCidr, 35 | "aws_region": awsRegion, 36 | }, 37 | }) 38 | 39 | // At the end of the test, run `terraform destroy` to clean up any resources that were created 40 | defer terraform.Destroy(t, terraformOptions) 41 | 42 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors 43 | terraform.InitAndApply(t, terraformOptions) 44 | 45 | // Run `terraform output` to get the value of an output variable 46 | publicSubnetId := terraform.Output(t, terraformOptions, "public_subnet_id") 47 | privateSubnetId := terraform.Output(t, terraformOptions, "private_subnet_id") 48 | vpcId := terraform.Output(t, terraformOptions, "main_vpc_id") 49 | 50 | subnets := aws.GetSubnetsForVpc(t, vpcId, awsRegion) 51 | 52 | require.Equal(t, 2, len(subnets)) 53 | // Verify if the network that is supposed to be public is really public 54 | assert.True(t, aws.IsPublicSubnet(t, publicSubnetId, awsRegion)) 55 | // Verify if the network that is supposed to be private is really private 56 | assert.False(t, aws.IsPublicSubnet(t, privateSubnetId, awsRegion)) 57 | } 58 | -------------------------------------------------------------------------------- /test/aws/rds_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/gruntwork-io/terratest/modules/aws" 9 | "github.com/gruntwork-io/terratest/modules/random" 10 | "github.com/gruntwork-io/terratest/modules/terraform" 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | // An example of how to test the Terraform module in examples/terraform-aws-rds-example using Terratest. 15 | func TestUnitRDS(t *testing.T) { 16 | t.Parallel() 17 | 18 | // Give this RDS Instance a unique ID for a name tag so we can distinguish it from any other RDS Instance running 19 | // in your AWS account 20 | expectedName := fmt.Sprintf("terratest-aws-rds-example-%s", strings.ToLower(random.UniqueId())) 21 | expectedPort := int64(5432) 22 | expectedDatabaseName := "terratest" 23 | username := "username" 24 | password := "password" 25 | // Pick a random AWS region to test in. This helps ensure your code works in all regions. 26 | awsRegion := aws.GetRandomStableRegion(t, []string{"us-east-1"}, nil) 27 | instanceType := aws.GetRecommendedRdsInstanceType(t, awsRegion, "postgres", "12.6", []string{"db.t2.micro", "db.t3.micro"}) 28 | 29 | // Construct the terraform options with default retryable errors to handle the most common retryable errors in 30 | // terraform testing. 31 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 32 | // The path to where our Terraform code is located 33 | TerraformDir: "../../examples/aws/unit/rds", 34 | 35 | // Variables to pass to our Terraform code using -var options 36 | // "username" and "password" should not be passed from here in a production scenario. 37 | Vars: map[string]interface{}{ 38 | "name": expectedName, 39 | "engine_name": "postgres", 40 | "engine_version": "12.6", 41 | "instance_class": instanceType, 42 | "username": username, 43 | "password": password, 44 | "allocated_storage": 5, 45 | "db_port": expectedPort, 46 | "database_name": expectedDatabaseName, 47 | "aws_default_region": awsRegion, 48 | }, 49 | 50 | // Environment variables to set when running Terraform 51 | EnvVars: map[string]string{ 52 | "AWS_DEFAULT_REGION": awsRegion, 53 | }, 54 | }) 55 | 56 | // At the end of the test, run `terraform destroy` to clean up any resources that were created 57 | defer terraform.Destroy(t, terraformOptions) 58 | 59 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors 60 | terraform.InitAndApply(t, terraformOptions) 61 | // // Run `terraform output` to get the value of an output variable 62 | // dbInstanceID := terraform.Output(t, terraformOptions, "db_id") 63 | 64 | // // Look up the endpoint address and port of the RDS instance 65 | // address := aws.GetAddressOfRdsInstance(t, dbInstanceID, awsRegion) 66 | // port := aws.GetPortOfRdsInstance(t, dbInstanceID, awsRegion) 67 | // // Lookup parameter values. All defined values are strings in the API call response 68 | // // Lookup option values. All defined values are strings in the API call response 69 | // // Verify that the address is not null 70 | // assert.NotNil(t, address) 71 | // // Verify that the DB instance is listening on the port mentioned 72 | // assert.Equal(t, expectedPort, port) 73 | dbInstanceID := terraform.Output(t, terraformOptions, "db_id") 74 | address := aws.GetAddressOfRdsInstance(t, dbInstanceID, awsRegion) 75 | port := aws.GetPortOfRdsInstance(t, dbInstanceID, awsRegion) 76 | assert.NotNil(t, address) 77 | // Verify that the DB instance is listening on the port mentioned 78 | assert.Equal(t, expectedPort, port) 79 | // Verify that the table/schema requested for creation is actually present in the database 80 | } 81 | -------------------------------------------------------------------------------- /test/azure/azure_integrated_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/terraform" 7 | ) 8 | 9 | func TestIntegrationAzure(t *testing.T) { 10 | t.Parallel() 11 | 12 | /* subscriptionID := "" 13 | uniquePostfix := random.UniqueId() */ 14 | 15 | // Configure Terraform setting up a path to Terraform code. 16 | terraformOptions := &terraform.Options{ 17 | // The path to where our Terraform code is located. 18 | TerraformDir: "../../examples/azure/e2e", 19 | 20 | // Variables to pass to our Terraform code using -var options. 21 | Vars: map[string]interface{}{ 22 | "location": "eastus", 23 | "resource_group_name": "test", 24 | }, 25 | } 26 | 27 | // At the end of the test, run `terraform destroy` to clean up any resources that were created. 28 | defer terraform.Destroy(t, terraformOptions) 29 | 30 | // Run `terraform init` and `terraform apply`. Fail the test if there are any errors. 31 | terraform.InitAndApply(t, terraformOptions) 32 | 33 | // Run tests for the Virtual Machine. 34 | } 35 | 36 | /* func testStrategiesForVMs(t *testing.T, terraformOptions *terraform.Options, subscriptionID string) { 37 | // Run `terraform output` to get the values of output variables. 38 | resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") 39 | virtualMachineName := terraform.Output(t, terraformOptions, "linux_name") 40 | expectedVMSize := compute.VirtualMachineSizeTypes(terraform.Output(t, terraformOptions, "vm_size")) 41 | 42 | // 1. Check the VM Size directly. This strategy gets one specific property of the VM per method. 43 | actualVMSize := azure.GetSizeOfVirtualMachine(t, virtualMachineName, resourceGroupName, subscriptionID) 44 | assert.Equal(t, expectedVMSize, actualVMSize) 45 | 46 | // 2. Check the VM size by reference. This strategy is beneficial when checking multiple properties 47 | // by using one VM reference. Optional parameters have to be checked first to avoid nil panics. 48 | vmByRef := azure.GetVirtualMachine(t, virtualMachineName, resourceGroupName, subscriptionID) 49 | actualVMSize = vmByRef.HardwareProfile.VMSize 50 | assert.Equal(t, expectedVMSize, actualVMSize) 51 | 52 | // 3. Check the VM size by instance. This strategy is beneficial when checking multiple properties 53 | // by using one VM instance and making calls against it with the added benefit of property check abstraction. 54 | vmInstance := azure.Instance{VirtualMachine: vmByRef} 55 | actualVMSize = vmInstance.GetVirtualMachineInstanceSize() 56 | assert.Equal(t, expectedVMSize, actualVMSize) 57 | } 58 | */ 59 | -------------------------------------------------------------------------------- /test/docker/dockerfile_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/docker" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestDockerBuild(t *testing.T) { 11 | t.Parallel() 12 | dockerComposeFile := "../../deployments/test.yml" 13 | docker.RunDockerCompose( 14 | t, 15 | &docker.Options{}, 16 | "-f", 17 | dockerComposeFile, 18 | "build", 19 | ) 20 | 21 | output := docker.RunDockerComposeAndGetStdOut( 22 | t, 23 | &docker.Options{}, 24 | "-f", 25 | dockerComposeFile, 26 | "run", 27 | "--rm", 28 | "simple_stdout", 29 | ) 30 | assert.Contains(t, output, "stdout: passed") 31 | assert.NotContains(t, output, "stderr: building error") 32 | } 33 | -------------------------------------------------------------------------------- /test/gcp/compute_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/gcp" 7 | "github.com/gruntwork-io/terratest/modules/terraform" 8 | test_structure "github.com/gruntwork-io/terratest/modules/test-structure" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestUnitCompute(t *testing.T) { 13 | t.Parallel() 14 | 15 | projectId := gcp.GetGoogleProjectIDFromEnvVar(t) 16 | gsCreds := gcp.GetGoogleCredentialsFromEnvVar(t) 17 | exampleDir := test_structure.CopyTerraformFolderToTemp(t, "../../", "examples/gcp/unit/compute") 18 | region := gcp.GetRandomRegion(t, projectId, []string{"us-west1", "us-central1", "us-east1"}, nil) 19 | randomValidGcpName := gcp.RandomValidGcpName() 20 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 21 | TerraformDir: exampleDir, 22 | Vars: map[string]interface{}{ 23 | "gcp_project_region": region, 24 | "gcp_instance_name": randomValidGcpName, 25 | "gcp_project_id": projectId, 26 | }, 27 | EnvVars: map[string]string{ 28 | "GOOGLE_PROJECT": projectId, 29 | "GOOGLE_APPLICATION_CREDENTIALS": gsCreds, 30 | }, 31 | }) 32 | 33 | defer terraform.Destroy(t, terraformOptions) 34 | terraform.InitAndApply(t, terraformOptions) 35 | 36 | resultingInstanceName := terraform.OutputRequired(t, terraformOptions, "resulting_name") 37 | resultingInstanceType := terraform.OutputRequired(t, terraformOptions, "resulting_type") 38 | assert.Equal(t, randomValidGcpName, resultingInstanceName) 39 | assert.Equal(t, "f1-micro", resultingInstanceType) 40 | } 41 | -------------------------------------------------------------------------------- /test/gcp/gcp_test.go: -------------------------------------------------------------------------------- 1 | // NOTE: We use build tags to differentiate GCP testing for better isolation and parallelism when executing our tests. 2 | 3 | package test 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | "testing" 9 | "time" 10 | 11 | "github.com/gruntwork-io/terratest/modules/gcp" 12 | "github.com/gruntwork-io/terratest/modules/retry" 13 | "github.com/gruntwork-io/terratest/modules/ssh" 14 | "github.com/gruntwork-io/terratest/modules/terraform" 15 | test_structure "github.com/gruntwork-io/terratest/modules/test-structure" 16 | ) 17 | 18 | func TestIntegrationGCP(t *testing.T) { 19 | t.Parallel() 20 | 21 | projectId := gcp.GetGoogleProjectIDFromEnvVar(t) 22 | exampleDir := test_structure.CopyTerraformFolderToTemp(t, "../../", "examples/gcp/e2e") 23 | region := gcp.GetRandomRegion(t, projectId, []string{"us-west1", "us-central1", "us-east1"}, nil) 24 | randomValidGcpName := gcp.RandomValidGcpName() 25 | randomValidNetworkGcpName := gcp.RandomValidGcpName() 26 | randomValidBucketGcpName := gcp.RandomValidGcpName() 27 | gsCreds := gcp.GetGoogleCredentialsFromEnvVar(t) 28 | // Variables to pass to our Terraform code using -var options 29 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 30 | // The path to where our Terraform code is located 31 | TerraformDir: exampleDir, 32 | Vars: map[string]interface{}{ 33 | "gcp_project_region": region, 34 | "gcp_instance_name": randomValidGcpName, 35 | "gcp_network_name": randomValidNetworkGcpName, 36 | "gcp_bucket_name": randomValidBucketGcpName, 37 | "gcp_project_id": projectId, 38 | }, 39 | EnvVars: map[string]string{ 40 | "GOOGLE_PROJECT": projectId, 41 | "GOOGLE_APPLICATION_CREDENTIALS": gsCreds, 42 | }, 43 | }) 44 | defer terraform.Destroy(t, terraformOptions) 45 | terraform.InitAndApply(t, terraformOptions) 46 | publicIp := terraform.Output(t, terraformOptions, "gcp_public_ip") 47 | instance := gcp.FetchInstance(t, projectId, randomValidGcpName) 48 | sampleText := "Hello World" 49 | sshUsername := "root" 50 | keyPair := ssh.GenerateRSAKeyPair(t, 2048) 51 | instance.AddSshKey(t, sshUsername, keyPair.PublicKey) 52 | host := ssh.Host{ 53 | Hostname: publicIp, 54 | SshKeyPair: keyPair, 55 | SshUserName: sshUsername, 56 | } 57 | maxRetries := 20 58 | sleepBetweenRetries := 4 * time.Second 59 | retry.DoWithRetry(t, "Attempting to SSH", maxRetries, sleepBetweenRetries, func() (string, error) { 60 | output, err := ssh.CheckSshCommandE(t, host, fmt.Sprintf("echo '%s'", sampleText)) 61 | if err != nil { 62 | return "", err 63 | } 64 | 65 | if strings.TrimSpace(sampleText) != strings.TrimSpace(output) { 66 | return "", fmt.Errorf("Expected: %s. Got: %s\n", sampleText, output) 67 | } 68 | 69 | return "", nil 70 | }) 71 | } 72 | -------------------------------------------------------------------------------- /test/gcp/storage_test.go: -------------------------------------------------------------------------------- 1 | // NOTE: We use build tags to differentiate GCP testing for better isolation and parallelism when executing our tests. 2 | 3 | package test 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "strings" 9 | "testing" 10 | 11 | "github.com/gruntwork-io/terratest/modules/gcp" 12 | "github.com/gruntwork-io/terratest/modules/logger" 13 | "github.com/gruntwork-io/terratest/modules/random" 14 | "github.com/gruntwork-io/terratest/modules/terraform" 15 | test_structure "github.com/gruntwork-io/terratest/modules/test-structure" 16 | "github.com/stretchr/testify/require" 17 | ) 18 | 19 | func TestUnitStorage(t *testing.T) { 20 | t.Parallel() 21 | 22 | projectId := gcp.GetGoogleProjectIDFromEnvVar(t) 23 | gsCreds := gcp.GetGoogleCredentialsFromEnvVar(t) 24 | exampleDir := test_structure.CopyTerraformFolderToTemp(t, "../../", "examples/gcp/unit/storage") 25 | region := gcp.GetRandomRegion(t, projectId, []string{"us-east1"}, nil) 26 | 27 | gsNetworkName := gcp.RandomValidGcpName() 28 | gsBucketName := gcp.RandomValidGcpName() 29 | 30 | // Variables to pass to our Terraform code using -var options 31 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 32 | // The path to where our Terraform code is located 33 | TerraformDir: exampleDir, 34 | Vars: map[string]interface{}{ 35 | "gcp_project_region": region, 36 | "gcp_network_name": gsNetworkName, 37 | "gcp_project_id": projectId, 38 | "gcp_bucket_name": gsBucketName, 39 | }, 40 | EnvVars: map[string]string{ 41 | "GOOGLE_PROJECT": projectId, 42 | "GOOGLE_APPLICATION_CREDENTIALS": gsCreds, 43 | }, 44 | }) 45 | 46 | defer terraform.Destroy(t, terraformOptions) 47 | terraform.InitAndApply(t, terraformOptions) 48 | 49 | testFilePath := fmt.Sprintf("test-file-%s.txt", random.UniqueId()) 50 | testFileBody := "test file text" 51 | logger.Logf(t, "Random values selected Bucket Name = %s, Test Filepath: %s\n", gsBucketName, testFilePath) 52 | objectURL := gcp.WriteBucketObject(t, gsBucketName, testFilePath, strings.NewReader(testFileBody), "text/plain") 53 | logger.Logf(t, "Got URL: %s", objectURL) 54 | fileReader := gcp.ReadBucketObject(t, gsBucketName, testFilePath) 55 | buf := new(bytes.Buffer) 56 | buf.ReadFrom(fileReader) 57 | result := buf.String() 58 | require.Equal(t, testFileBody, result) 59 | } 60 | -------------------------------------------------------------------------------- /test/gcp/vpc_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/gcp" 7 | "github.com/gruntwork-io/terratest/modules/terraform" 8 | test_structure "github.com/gruntwork-io/terratest/modules/test-structure" 9 | ) 10 | 11 | func TestUnitVPC(t *testing.T) { 12 | t.Parallel() 13 | randomValidNetworkGcpName := gcp.RandomValidGcpName() 14 | projectId := gcp.GetGoogleProjectIDFromEnvVar(t) 15 | gsCreds := gcp.GetGoogleCredentialsFromEnvVar(t) 16 | exampleDir := test_structure.CopyTerraformFolderToTemp(t, "../../", "examples/gcp/unit/vpc") 17 | region := gcp.GetRandomRegion(t, projectId, []string{"us-west1", "us-central1", "us-east1"}, nil) 18 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 19 | TerraformDir: exampleDir, 20 | Vars: map[string]interface{}{ 21 | "gcp_project_region": region, 22 | "gcp_network_name": randomValidNetworkGcpName, 23 | "gcp_project_id": projectId, 24 | }, 25 | EnvVars: map[string]string{ 26 | "GOOGLE_PROJECT": projectId, 27 | "GOOGLE_CREDENTIALS": gsCreds, 28 | }, 29 | }) 30 | defer terraform.Destroy(t, terraformOptions) 31 | terraform.InitAndApply(t, terraformOptions) 32 | } 33 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_project_id" { 2 | type = string 3 | default = "test" 4 | description = "Your static IP network nameP. [Naming resources convention](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 5 | validation { 6 | condition = can(regex("^[a-z0-9][-a-z0-9]*[a-z0-9]$", var.gcp_project_id)) 7 | error_message = "Error: Your Google Cloud Project ID seems to have an invalid value." 8 | } 9 | } 10 | 11 | variable "gcp_project_region" { 12 | type = string 13 | default = "us-west1" 14 | description = "Zone location of your instance, [see the list of available regions](https://cloud.google.com/compute/docs/regions-zones#available) - [Terraform provider documentation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance#zone)" 15 | validation { 16 | condition = can(index(["us-west1", "us-central1", "us-east1"], var.gcp_project_region)) 17 | error_message = "Error: Only some U.S. regions are available regarding the free offer of GCP Compute VM instances." 18 | } 19 | } 20 | 21 | variable "gcp_instance_name" { 22 | type = string 23 | default = "gcp-machine" 24 | description = "Your VM instance name. [Naming resources convention](https://cloud.google.com/compute/docs/naming-resources#resource-name-format)" 25 | validation { 26 | condition = can(regex("^[a-z0-9][-a-z0-9]*[a-z0-9]$", var.gcp_instance_name)) 27 | error_message = "Error: The instance name can contain only dashes, lowercase letters, and numbers. It must be at least 2 characters and can neither start nor end with a dash." 28 | } 29 | } 30 | 31 | variable "gcp_storage_permissions" { 32 | type = string 33 | default = "publicread" 34 | description = "See all available values for the parameter at [Predefined ACL's on GCS Permissions](https://cloud.google.com/storage/docs/access-control/lists#predefined-acl)" 35 | validation { 36 | condition = can(index(["private", "bucketownerread", "bucketOwnerfullcontrol", "projectprivate", " authenticateread", "publicread", "publicreadwrite"], var.gcp_storage_permissions)) 37 | error_message = "Error: Invalid permissions set for GCS Bucket. Please adjust it according to the documentation.." 38 | } 39 | } 40 | 41 | variable "aws_default_region" { 42 | type = string 43 | default = "us-east-1" 44 | description = "Your default region for AWS resources creation. [Available regions for Google Compute on Free Tier.](https://free.terraform.gruber.dev.br/docs/resources/providers/aws#options)" 45 | } 46 | 47 | variable "backend_destroy" { 48 | type = string 49 | default = "false" 50 | description = "Allows destroying all resourcesinside the configured S3 Remote Backend. See more at [tf-free's Backend Documentation](https://free.terraform.gruber.dev.br/docs/setup/backend)" 51 | validation { 52 | condition = can(index(["false", "true"], var.backend_destroy)) 53 | error_message = "Error: Only 'true' or 'false' input as a string are acceptable values to this variable." 54 | } 55 | } 56 | 57 | variable "prevents_destroy" { 58 | type = bool 59 | default = true 60 | description = "Prevents destroying the previously provisioned S3 Remote Backend. See more at [tf-free's Backend Documentation](https://free.terraform.gruber.dev.br/docs/setup/backend)" 61 | } 62 | 63 | variable "backend_stage" { 64 | type = string 65 | default = "test" 66 | description = "Stages possible for Backend. Set for a random string." 67 | } 68 | 69 | variable "ec2_aws" { 70 | description = "Allow for the creation of EC2 instances on AWS." 71 | type = bool 72 | default = true 73 | } 74 | 75 | variable "rds_aws" { 76 | description = "Allow for the creation of a PostgreSQL database on AWS" 77 | type = bool 78 | default = true 79 | } 80 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13" 3 | required_providers { 4 | google = { 5 | source = "hashicorp/google" 6 | version = "4.31.0" 7 | } 8 | google-beta = { 9 | source = "hashicorp/google-beta" 10 | version = "4.31.0" 11 | } 12 | aws = { 13 | source = "hashicorp/aws" 14 | version = "4.25.0" 15 | } 16 | azurerm = { 17 | source = "hashicorp/azurerm" 18 | version = "3.17.0" 19 | } 20 | } 21 | } 22 | 23 | provider "aws" { 24 | region = var.aws_default_region 25 | } 26 | 27 | provider "google" { 28 | region = var.gcp_project_region 29 | } 30 | 31 | provider "google-beta" { 32 | region = var.gcp_project_region 33 | } 34 | 35 | provider "azurerm" { 36 | features {} 37 | } 38 | --------------------------------------------------------------------------------