diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..ec25d53 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Flaconi/devops diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ad4645f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + day: monday + time: "08:00" + timezone: Europe/Berlin diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..7c7b2f3 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,24 @@ +# Configuration for Release Drafter: https://github.com/toolmantim/release-drafter +name-template: 'v$NEXT_MINOR_VERSION 🌈' +tag-template: 'v$NEXT_MINOR_VERSION' +categories: + - title: '🚀 Features' + labels: + - feature + - enhancement + - title: '🐛 Bug Fixes' + labels: + - fix + - bugfix + - bug + - title: '🧰 Maintenance' + labels: + - chore + - dependencies +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +branches: + - master +template: | + ## What's Changed + + $CHANGES diff --git a/.github/workflows/backups.yml b/.github/workflows/backups.yml new file mode 100644 index 0000000..b6194d4 --- /dev/null +++ b/.github/workflows/backups.yml @@ -0,0 +1,17 @@ +--- +name: Backup Repository + +on: + push: + branches: + - master + +jobs: + backup: + uses: Flaconi/github-reusable-workflow/.github/workflows/backups.yml@v1 + with: + enabled: True + region: eu-central-1 + secrets: + iam_role_arn: ${{ secrets.BACKUP_REPO_IAM_ROLE }} + bucket_name: ${{ secrets.BACKUP_REPO_BUCKET }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..b087fbe --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,62 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: lint + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + # Runs on Pull Requests + pull_request: + + +# ------------------------------------------------------------------------------------------------- +# What to run +# ------------------------------------------------------------------------------------------------- +jobs: + lint: + name: "Lint" + runs-on: ubuntu-latest + strategy: + fail-fast: False + matrix: + target: + - lint + - gen + + steps: + # ------------------------------------------------------------ + # Setup repository + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # ------------------------------------------------------------ + # Lint repository + # ------------------------------------------------------------ + - name: "make ${{ matrix.target }}" + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep 2; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + + retry make "${TARGET}" + git diff --quiet || { echo "Build Changes"; git diff; git status; false; } + env: + TARGET: ${{ matrix.target }} + RETRIES: 20 diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..73c0e8f --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,20 @@ +name: Release Drafter + +on: + push: + branches: + - master + +permissions: + contents: read + +jobs: + update_release_draft: + permissions: + contents: write + pull-requests: read + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b888ae3 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,50 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: test + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + # Runs on Pull Requests + pull_request: + + +# ------------------------------------------------------------------------------------------------- +# What to run +# ------------------------------------------------------------------------------------------------- +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + + # ------------------------------------------------------------ + # Checkout repository + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Test + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep 2; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + retry make test + env: + RETRIES: 20 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a147187 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Lock file +.terraform.lock.hcl + +# Vars file +/*.tfvars diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3221cee --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Flaconi GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..affb4f3 --- /dev/null +++ b/Makefile @@ -0,0 +1,278 @@ +ifneq (,) +.error This Makefile requires GNU Make. +endif + +.PHONY: help gen lint test _gen-main _gen-examples _gen-modules _lint-files _lint-fmt _lint-json _pull-tf _pull-tfdocs _pull-fl _pull-jl + +CURRENT_DIR = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +TF_EXAMPLES = $(sort $(dir $(wildcard $(CURRENT_DIR)examples/*/))) +TF_MODULES = $(sort $(dir $(wildcard $(CURRENT_DIR)modules/*/))) + +# ------------------------------------------------------------------------------------------------- +# Container versions +# ------------------------------------------------------------------------------------------------- +TF_VERSION = 1.3.9 +TFDOCS_VERSION = 0.16.0-0.34 +FL_VERSION = latest-0.8 +JL_VERSION = 1.6.0-0.14 + + +# ------------------------------------------------------------------------------------------------- +# Enable linter (file-lint, terraform fmt, jsonlint) +# ------------------------------------------------------------------------------------------------- +LINT_FL_ENABLE = 1 +LINT_TF_ENABLE = 1 +LINT_JL_ENABLE = 1 + + +# ------------------------------------------------------------------------------------------------- +# terraform-docs defines +# ------------------------------------------------------------------------------------------------- +# Adjust your delimiter here or overwrite via make arguments +DELIM_START = +DELIM_CLOSE = +# What arguments to append to terraform-docs command +TFDOCS_ARGS = --sort=false + + +# ------------------------------------------------------------------------------------------------- +# Default target +# ------------------------------------------------------------------------------------------------- +help: + @echo "gen Generate terraform-docs output and replace in README.md's" + @echo "lint Static source code analysis" + @echo "test Integration tests" + + +# ------------------------------------------------------------------------------------------------- +# Standard targets +# ------------------------------------------------------------------------------------------------- +gen: _pull-tfdocs + @echo "################################################################################" + @echo "# Terraform-docs generate" + @echo "################################################################################" + @$(MAKE) --no-print-directory _gen-main + @$(MAKE) --no-print-directory _gen-examples + @$(MAKE) --no-print-directory _gen-modules + +lint: + @if [ "$(LINT_FL_ENABLE)" = "1" ]; then \ + $(MAKE) --no-print-directory _lint-files; \ + fi + @if [ "$(LINT_TF_ENABLE)" = "1" ]; then \ + $(MAKE) --no-print-directory _lint-fmt; \ + fi + @if [ "$(LINT_JL_ENABLE)" = "1" ]; then \ + $(MAKE) --no-print-directory _lint-json; \ + fi + +test: _pull-tf + @$(foreach example,\ + $(TF_EXAMPLES),\ + DOCKER_PATH="/t/examples/$(notdir $(patsubst %/,%,$(example)))"; \ + echo "################################################################################"; \ + echo "# examples/$$( basename $${DOCKER_PATH} )"; \ + echo "################################################################################"; \ + echo; \ + echo "------------------------------------------------------------"; \ + echo "# Terraform init"; \ + echo "------------------------------------------------------------"; \ + if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \ + init \ + -lock=false \ + -upgrade \ + -reconfigure \ + -input=false \ + -get=true; \ + then \ + echo "OK"; \ + else \ + echo "Failed"; \ + docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \ + exit 1; \ + fi; \ + echo; \ + echo "------------------------------------------------------------"; \ + echo "# Terraform validate"; \ + echo "------------------------------------------------------------"; \ + if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \ + validate \ + $(ARGS) \ + .; then \ + echo "OK"; \ + docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \ + else \ + echo "Failed"; \ + docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" --entrypoint=rm hashicorp/terraform:$(TF_VERSION) -rf .terraform/ || true; \ + exit 1; \ + fi; \ + echo; \ + ) + + +# ------------------------------------------------------------------------------------------------- +# Helper Targets +# ------------------------------------------------------------------------------------------------- +_gen-main: + @echo "------------------------------------------------------------" + @echo "# Main module" + @echo "------------------------------------------------------------" + @if docker run $$(tty -s && echo "-it" || echo) --rm \ + -v $(CURRENT_DIR):/data \ + -e DELIM_START='' \ + -e DELIM_CLOSE='' \ + cytopia/terraform-docs:$(TFDOCS_VERSION) \ + terraform-docs-replace --show header markdown tbl --indent 2 --sort README.md; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi + @if docker run $$(tty -s && echo "-it" || echo) --rm \ + -v $(CURRENT_DIR):/data \ + -e DELIM_START='' \ + -e DELIM_CLOSE='' \ + cytopia/terraform-docs:$(TFDOCS_VERSION) \ + terraform-docs-replace --show providers markdown tbl --indent 2 --sort README.md; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi + @if docker run $$(tty -s && echo "-it" || echo) --rm \ + -v $(CURRENT_DIR):/data \ + -e DELIM_START='' \ + -e DELIM_CLOSE='' \ + cytopia/terraform-docs:$(TFDOCS_VERSION) \ + terraform-docs-replace --show requirements markdown tbl --indent 2 --sort README.md; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi + @if docker run $$(tty -s && echo "-it" || echo) --rm \ + -v $(CURRENT_DIR):/data \ + -e DELIM_START='' \ + -e DELIM_CLOSE='' \ + cytopia/terraform-docs:$(TFDOCS_VERSION) \ + terraform-docs-replace --show inputs markdown doc --indent 2 $(TFDOCS_ARGS) README.md; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi + @if docker run $$(tty -s && echo "-it" || echo) --rm \ + -v $(CURRENT_DIR):/data \ + -e DELIM_START='' \ + -e DELIM_CLOSE='' \ + cytopia/terraform-docs:$(TFDOCS_VERSION) \ + terraform-docs-replace --show outputs markdown tbl --indent 2 --sort README.md; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi + +_gen-examples: + @$(foreach example,\ + $(TF_EXAMPLES),\ + DOCKER_PATH="examples/$(notdir $(patsubst %/,%,$(example)))"; \ + echo "------------------------------------------------------------"; \ + echo "# $${DOCKER_PATH}"; \ + echo "------------------------------------------------------------"; \ + if docker run $$(tty -s && echo "-it" || echo) --rm \ + -v $(CURRENT_DIR):/data \ + -e DELIM_START='$(DELIM_START)' \ + -e DELIM_CLOSE='$(DELIM_CLOSE)' \ + cytopia/terraform-docs:$(TFDOCS_VERSION) \ + terraform-docs-replace $(TFDOCS_ARGS) markdown $${DOCKER_PATH}/README.md; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi; \ + ) + +_gen-modules: + @$(foreach module,\ + $(TF_MODULES),\ + DOCKER_PATH="modules/$(notdir $(patsubst %/,%,$(module)))"; \ + echo "------------------------------------------------------------"; \ + echo "# $${DOCKER_PATH}"; \ + echo "------------------------------------------------------------"; \ + if docker run $$(tty -s && echo "-it" || echo) --rm \ + -v $(CURRENT_DIR):/data \ + -e DELIM_START='$(DELIM_START)' \ + -e DELIM_CLOSE='$(DELIM_CLOSE)' \ + cytopia/terraform-docs:$(TFDOCS_VERSION) \ + terraform-docs-replace $(TFDOCS_ARGS) markdown $${DOCKER_PATH}/README.md; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi; \ + ) + +_lint-files: _pull-fl + @# Basic file linting + @echo "################################################################################" + @echo "# File-lint" + @echo "################################################################################" + @docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-cr --text --ignore '.git/,.github/,.terraform/' --path . + @docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-crlf --text --ignore '.git/,.github/,.terraform/' --path . + @docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-trailing-single-newline --text --ignore '.git/,.github/,.terraform/' --path . + @docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-trailing-space --text --ignore '.git/,.github/,.terraform/' --path . + @docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-utf8 --text --ignore '.git/,.github/,.terraform/' --path . + @docker run $$(tty -s && echo "-it" || echo) --rm -v $(CURRENT_DIR):/data cytopia/file-lint:$(FL_VERSION) file-utf8-bom --text --ignore '.git/,.github/,.terraform/' --path . + +_lint-fmt: _pull-tf + @# Lint all Terraform files + @echo "################################################################################" + @echo "# Terraform fmt" + @echo "################################################################################" + @echo + @echo "------------------------------------------------------------" + @echo "# *.tf files" + @echo "------------------------------------------------------------" + @if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t:ro" --workdir "/t" hashicorp/terraform:$(TF_VERSION) \ + fmt -recursive -check=true -diff=true -write=false -list=true .; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi; + @echo + @echo "------------------------------------------------------------" + @echo "# *.tfvars files" + @echo "------------------------------------------------------------" + @if docker run $$(tty -s && echo "-it" || echo) --rm --entrypoint=/bin/sh -v "$(CURRENT_DIR):/t:ro" --workdir "/t" hashicorp/terraform:$(TF_VERSION) \ + -c "find . -name '*.tfvars' -type f -print0 | xargs -0 -n1 terraform fmt -check=true -write=false -diff=true -list=true"; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi; + @echo + +_lint-json: _pull-jl + @# Lint all JSON files + @echo "################################################################################" + @echo "# Jsonlint" + @echo "################################################################################" + @if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/data:ro" cytopia/jsonlint:$(JL_VERSION) \ + -t ' ' -i '*.terraform/*' '*.json'; then \ + echo "OK"; \ + else \ + echo "Failed"; \ + exit 1; \ + fi; + @echo + +_pull-tf: + docker pull hashicorp/terraform:$(TF_VERSION) + +_pull-tfdocs: + docker pull cytopia/terraform-docs:$(TFDOCS_VERSION) + +_pull-fl: + docker pull cytopia/file-lint:$(FL_VERSION) diff --git a/README.md b/README.md new file mode 100644 index 0000000..da64134 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# terraform-module-template +Template for Terraform modules + + +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +For requirements regarding module structure: [style-guide-terraform.md](https://github.com/Flaconi/devops-docs/blob/master/doc/conventions/style-guide-terraform.md) + + + + + + + +## Providers + +No providers. + + + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | ~> 1.3 | + + + + +## Required Inputs + +No required inputs. + +## Optional Inputs + +No optional inputs. + + + + +## Outputs + +No outputs. + + + +## License + +**[MIT License](LICENSE)** + +Copyright (c) 2023 **[Flaconi GmbH](https://github.com/flaconi)** diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..e6b4cbd --- /dev/null +++ b/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = "~> 1.3" +}