{"id":14128189,"url":"https://github.com/pgporada/terraform-makefile","last_synced_at":"2025-04-12T20:42:41.222Z","repository":{"id":52701187,"uuid":"78214478","full_name":"pgporada/terraform-makefile","owner":"pgporada","description":"Helps me actually use terraform for multiple environments","archived":false,"fork":false,"pushed_at":"2025-02-26T17:56:14.000Z","size":75,"stargazers_count":203,"open_issues_count":2,"forks_count":61,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-04T00:56:23.907Z","etag":null,"topics":["hashicorp","make","makefile","terraform"],"latest_commit_sha":null,"homepage":null,"language":"Makefile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pgporada.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-06T15:01:44.000Z","updated_at":"2025-03-09T23:12:48.000Z","dependencies_parsed_at":"2024-10-23T01:34:02.322Z","dependency_job_id":null,"html_url":"https://github.com/pgporada/terraform-makefile","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgporada%2Fterraform-makefile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgporada%2Fterraform-makefile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgporada%2Fterraform-makefile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgporada%2Fterraform-makefile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pgporada","download_url":"https://codeload.github.com/pgporada/terraform-makefile/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631669,"owners_count":21136554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hashicorp","make","makefile","terraform"],"created_at":"2024-08-15T16:01:23.402Z","updated_at":"2025-04-12T20:42:41.202Z","avatar_url":"https://github.com/pgporada.png","language":"Makefile","funding_links":[],"categories":["Makefile","terraform"],"sub_categories":[],"readme":"# Overview: terraform-makefile\n![TF](https://img.shields.io/badge/Supports%20Terraform%20Version-%3E%3D0.11.10-blue.svg)\n[![License](https://img.shields.io/badge/license-Apache--2.0-brightgreen.svg)](LICENSE)\n\nThis is my [terraform](https://www.terraform.io/) workflow for every terraform project that I use personally/professionaly. If you've never heard of Terraform, may I suggest [checking out my Ansible role](https://github.com/pgporada/ansible-role-terraform) to download, verify, and install Terraform for you!\n\n- - - -\n# Usage\n\n* Keeps state in S3 and utilizes DynamoDB for locking.\n\n**Note - this could be out of date.**\n\nView a description of Makefile targets with help via the [self-documenting makefile](https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html).\n\n    $ make\n    apply                          Have terraform do the things. This will cost money.\n    destroy-backend                Destroy S3 bucket and DynamoDB table\n    destroy                        Destroy the things\n    destroy-target                 Destroy a specific resource. Caution though, this destroys chained resources.\n    plan-destroy                   Creates a destruction plan.\n    plan                           Show what terraform thinks it will do\n    plan-target                    Shows what a plan looks like for applying a specific resource\n    prep                           Prepare a new workspace (environment) if needed, configure the tfstate backend, update any modules, and switch to the workspace\n\n\n* Before each target, several private Makefile functions run to configure the remote state backend, `validate`,`set-env`, and `init`. You should never have to run these yourself.\n\nShow a plan from the remote state\n\n    $ ENV=qa make plan\n\tRemoving existing ENV.tfvars from local directory\n\n\tPulling fresh qa.tfvars from s3://qa-useast1-terraform-state/bastion/\n\tdownload: s3://qa-useast1-terraform-state/bastion/qa.tfvars to ./qa.tfvars\n\tInitialized blank state with remote state enabled!\n\tRemote state configured and pulled.\n\tLocal and remote state in sync\n\tRefreshing Terraform state in-memory prior to plan...\n\tThe refreshed state will be used to calculate this plan, but\n\twill not be persisted to local or remote state storage.\n\n\t-/+ module.bastion.aws_instance.bastion\n    ami:                               \"ami-61ce6c77\" =\u003e \"ami-35ab0823\" (forces new resource)\n    associate_public_ip_address:       \"true\" =\u003e \"\u003ccomputed\u003e\"\n    availability_zone:                 \"us-east-1a\" =\u003e \"\u003ccomputed\u003e\"\n    ebs_block_device.#:                \"0\" =\u003e \"\u003ccomputed\u003e\"\n    ephemeral_block_device.#:          \"0\" =\u003e \"\u003ccomputed\u003e\"\n    iam_instance_profile:              \"qa-bastion-instance-profile\" =\u003e \"qa-bastion-instance-profile\"\n    instance_state:                    \"running\" =\u003e \"\u003ccomputed\u003e\"\n    instance_type:                     \"t2.micro\" =\u003e \"t2.micro\"\n    ipv6_addresses.#:                  \"0\" =\u003e \"\u003ccomputed\u003e\"\n    key_name:                          \"qa_useast1_ec2key_bastion\" =\u003e \"qa_useast1_ec2key_bastion\"\n    network_interface_id:              \"eni-d00c2017\" =\u003e \"\u003ccomputed\u003e\"\n    placement_group:                   \"\" =\u003e \"\u003ccomputed\u003e\"\n    private_dns:                       \"ip-10-10-10-24.ec2.internal\" =\u003e \"\u003ccomputed\u003e\"\n    private_ip:                        \"10.10.10.24\" =\u003e \"\u003ccomputed\u003e\"\n    public_dns:                        \"ec2-52.52.52.52.compute-1.amazonaws.com\" =\u003e \"\u003ccomputed\u003e\"\n    public_ip:                         \"52.52.52.52\" =\u003e \"\u003ccomputed\u003e\"\n    root_block_device.#:               \"1\" =\u003e \"\u003ccomputed\u003e\"\n    security_groups.#:                 \"0\" =\u003e \"\u003ccomputed\u003e\"\n    source_dest_check:                 \"true\" =\u003e \"true\"\n    subnet_id:                         \"subnet-184a8440\" =\u003e \"subnet-184a8440\"\n    tags.%:                            \"6\" =\u003e \"6\"\n    tags.ENV:                          \"qa\" =\u003e \"qa\"\n    tags.Name:                         \"qa_useast1_bastion\" =\u003e \"qa_useast1_bastion\"\n    tags.ROLES:                        \"bastion\" =\u003e \"bastion\"\n    tags.TERRAFORM:                    \"true\" =\u003e \"true\"\n    tags.TYPE:                         \"bastion\" =\u003e \"bastion\"\n    tenancy:                           \"default\" =\u003e \"\u003ccomputed\u003e\"\n    user_data:                         \"1d902c0382fe19b53225a527fdc7bc95cfed875T\" =\u003e \"1d902c0382fe19b53225a527fdc7bc95cfed875T\"\n    vpc_security_group_ids.#:          \"1\" =\u003e \"1\"\n    vpc_security_group_ids.1449472535: \"sg-305ea24b\" =\u003e \"sg-305ea24b\"\n\n\t~ module.bastion.aws_route53_record.bastion-priv\n    records.#: \"\" =\u003e \"\u003ccomputed\u003e\"\n\n\t~ module.bastion.aws_route53_record.bastion-pub\n    records.#: \"\" =\u003e \"\u003ccomputed\u003e\"\n\n\tPlan: 1 to add, 2 to change, 1 to destroy.\n\nShow root level output\n\n    ENV=qa make output\n\t# Alternatively once you've run the make output, you can just run\n\tterraform output\n\nOutput a module\n\n    MODULE=network ENV=qa make output\n\nOutput a nested module\n\n    MODULE=network.nat ENV=qa make output\n\nPlan a specific module\n\n\tENV=prod make plan-target\n\nPlan it all\n\n\tENV=prod make plan\n\n- - - -\n# Example Terraform project layout\n\nTree output of a Terraform module I create\n\n    $ tree -F -l\n    terraform-bastion\n    ├── variables/\n    │   ├── prod-us-east-2.tfvars\n    │   └── qa-us-east-1.tfvars\n    ├── main.tf\n    ├── Makefile\n    ├── .gitignore\n    ├── .git/\n    ├── modules/\n    │   └── bastion/\n    │       ├── bastion.tf\n    │       └── init.sh\n    ├── README.md\n    └── LICENSE\n\n            5 directories, 10 files\n\nExample `main.tf` inside the tree\n\n    variable \"region\" {}\n\n    variable \"env\" {\n      default = \"qa\"\n    }\n    variable \"key_path\" {}\n    variable \"key_name\" {}\n    variable \"ec2_bastion_instance_type\" {}\n    variable \"ec2_bastion_user\" {}\n    variable \"accountid\" {}\n    variable \"profile\" {}\n\n    terraform {\n      required_version = \"\u003e= 0.11.10\"\n    }\n\n    provider \"aws\" {\n      region              = \"${var.region}\"\n      profile             = \"${var.env}\"\n      allowed_account_ids = [\"${var.accountid}\"]\n    }\n\n    data \"terraform_remote_state\" \"vpc\" {\n      backend = \"s3\"\n\n      // This must map to the workspace from the Makefile\n      workspace = \"${var.env}-${var.region}\"\n\n      // This must map to the bucket and key from the Makefile\n      config {\n        region         = \"${var.region}\"\n        acl            = \"private\"\n        profile        = \"${var.profile}\"\n        bucket         = \"${var.env}-${var.region}-yourCompany-terraform\"\n        key            = \"${var.env}/vpc/terraform.tfstate\"\n        dynamodb_table = \"${var.env}-${var.region}-yourCompany-terraform\"\n      }\n    }\n\n    module \"bastion\" {\n      source           = \"modules/bastion\"\n      env              = \"${var.env}\"\n      region           = \"${var.region}\"\n      instance_type    = \"${var.ec2_bastion_instance_type}\"\n      bastion_key_name = \"${var.key_name}\"\n      bastion_key_path = \"${var.key_path}\"\n      vpc_id           = \"${data.terraform_remote_state.vpc.vpc_id}\"\n      vpc_cidr         = \"${data.terraform_remote_state.vpc.vpc_cidr}\"\n      subnet_ids       = \"${data.terraform_remote_state.vpc.public_subnet_ids}\"\n      shell_username   = \"${var.ec2_bastion_user}\"\n    }\n\n    output \"environment\" {\n      value = \"${var.env}\"\n    }\n\n    output \"bastion_public_ip\" {\n      value = \"${module.bastion.public_ip}\"\n    }\n\n    output \"bastion_private_ip\" {\n      value = \"${module.bastion.private_ip}\"\n    }\n\n    output \"bastion_user\" {\n      value = \"${var.ec2_bastion_user}\"\n    }\n\n- - - -\n# Considerations\n\n* Each time this makefile is used, the remote state will be pulled from the backend onto your machine. This can result in slightly longer iteration times.\n* The makefile uses `.ONESHELL` which is a feature of gmake. OSX users may need to `brew install gmake`.\n* To use `ENV=qa make graph`, you will need to install `dot` via your systems package manager.\n* You should configure [remote state encryption for S3 via KMS](https://www.terraform.io/docs/state/remote/s3.html) via `encrypt` and `kms_key_id`. This is a `TODO` and should be automated by the Makefile.\n\n- - - -\n# Author Info and License\n\n![Apache-2.0](LICENSE)\n\n(C) [Philip Porada](https://github.com/pgporada/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgporada%2Fterraform-makefile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpgporada%2Fterraform-makefile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgporada%2Fterraform-makefile/lists"}