diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md
new file mode 100644
index 000000000..a58b0e452
--- /dev/null
+++ b/.chglog/CHANGELOG.tpl.md
@@ -0,0 +1,51 @@
+{{ if .Versions -}}
+
+## [Unreleased]
+{{ if .Unreleased.CommitGroups -}}
+{{ range .Unreleased.CommitGroups -}}
+### {{ .Title }}
+{{ range .Commits -}}
+- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
+{{ end }}
+{{ end -}}
+{{ else }}
+{{ range .Unreleased.Commits -}}
+- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
+{{ end }}
+{{ end -}}
+{{ end -}}
+
+{{ range .Versions }}
+
+## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
+{{ if .CommitGroups -}}
+{{ range .CommitGroups -}}
+### {{ .Title }}
+{{ range .Commits -}}
+- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
+{{ end }}
+{{ end -}}
+{{ else }}
+{{ range .Commits -}}
+- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
+{{ end }}
+{{ end -}}
+
+{{- if .NoteGroups -}}
+{{ range .NoteGroups -}}
+### {{ .Title }}
+{{ range .Notes }}
+{{ .Body }}
+{{ end }}
+{{ end -}}
+{{ end -}}
+{{ end -}}
+
+{{- if .Versions }}
+[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
+{{ range .Versions -}}
+{{ if .Tag.Previous -}}
+[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
+{{ end -}}
+{{ end -}}
+{{ end -}}
diff --git a/.chglog/config.yml b/.chglog/config.yml
new file mode 100644
index 000000000..3529dbcd6
--- /dev/null
+++ b/.chglog/config.yml
@@ -0,0 +1,10 @@
+style: github
+template: CHANGELOG.tpl.md
+info:
+ title: CHANGELOG
+ repository_url: https://github.com/antonbabenko/pre-commit-terraform
+options:
+ header:
+ pattern: "^(.*)$"
+ pattern_maps:
+ - Subject
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 70a21ad98..f80cfc805 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: git://github.com/pre-commit/pre-commit-hooks
- rev: v1.2.3
+ rev: v2.2.3
hooks:
- id: check-yaml
- id: end-of-file-fixer
diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml
index 2fda38ba1..c7f403941 100644
--- a/.pre-commit-hooks.yaml
+++ b/.pre-commit-hooks.yaml
@@ -9,23 +9,51 @@
- id: terraform_docs
name: Terraform docs
description: Inserts input and output documentation into README.md (using terraform-docs).
+ require_serial: true
entry: terraform_docs.sh
+ args: [--args=--with-aggregate-type-defaults]
language: script
files: (\.tf)$
exclude: \.terraform\/.*$
-- id: terraform_validate_no_variables
+- id: terraform_docs_without_aggregate_type_defaults
+ name: Terraform docs (without aggregate type defaults)
+ description: Inserts input and output documentation into README.md (using terraform-docs).
+ require_serial: true
+ entry: terraform_docs.sh
+ language: script
+ files: (\.tf)$
+ exclude: \.terraform\/.*$
+
+- id: terraform_docs_replace
+ name: Terraform docs (overwrite README.md)
+ description: Overwrite content of README.md with terraform-docs.
+ require_serial: true
+ entry: terraform_docs_replace
+ language: python
+ files: (\.tf)$
+ exclude: \.terraform\/.*$
+
+- id: terraform_validate
name: Terraform validate without variables
- description: Validates all Terraform configuration files without checking whether all required variables were set (basic check).
- entry: terraform_validate_no_variables.sh
+ description: Validates all Terraform configuration files.
+ entry: terraform_validate.sh
language: script
files: (\.tf|\.tfvars)$
exclude: \.terraform\/.*$
-- id: terraform_validate_with_variables
- name: Terraform validate with variables
- description: Validates all Terraform configuration files and checks whether all required variables were specified.
- entry: terraform_validate_with_variables.sh
+- id: terraform_tflint
+ name: Terraform validate with tflint
+ description: Validates all Terraform configuration files with TFLint.
+ entry: terraform_tflint.sh
language: script
files: (\.tf|\.tfvars)$
exclude: \.terraform\/.*$
+
+- id: terragrunt_fmt
+ name: Terragrunt fmt
+ description: Rewrites all Terragrunt configuration files to a canonical format.
+ entry: terragrunt_fmt.sh
+ language: script
+ files: (\.hcl)$
+ exclude: \.terraform\/.*$
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..8496bac9a
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,227 @@
+
+## [Unreleased]
+
+
+
+
+## [v1.19.0] - 2019-08-20
+
+- Updated README with terraform_tflint hook
+- Added support for TFLint with --deep parameter ([#53](https://github.com/antonbabenko/pre-commit-terraform/issues/53))
+
+
+
+## [v1.18.0] - 2019-08-20
+
+- Updated CHANGELOG
+- Updated README with terragrunt_fmt hook
+- Formatter for Terragrunt HCL files ([#60](https://github.com/antonbabenko/pre-commit-terraform/issues/60))
+
+
+
+## [v1.17.0] - 2019-06-25
+
+- Updated CHANGELOG
+- Fixed enquoted types in terraform_docs (fixed [#52](https://github.com/antonbabenko/pre-commit-terraform/issues/52))
+- Fix typo in README ([#51](https://github.com/antonbabenko/pre-commit-terraform/issues/51))
+
+
+
+## [v1.16.0] - 2019-06-18
+
+- Updated CHANGELOG
+- Add slash to mktemp dir (fixed [#50](https://github.com/antonbabenko/pre-commit-terraform/issues/50))
+
+
+
+## [v1.15.0] - 2019-06-18
+
+- Updated CHANGELOG
+- Fixed awk script for terraform-docs (kudos [@cytopia](https://github.com/cytopia)) and mktemp on Mac (closes [#47](https://github.com/antonbabenko/pre-commit-terraform/issues/47), [#48](https://github.com/antonbabenko/pre-commit-terraform/issues/48), [#49](https://github.com/antonbabenko/pre-commit-terraform/issues/49))
+- Fix version in README.md ([#46](https://github.com/antonbabenko/pre-commit-terraform/issues/46))
+
+
+
+## [v1.14.0] - 2019-06-17
+
+- Updated CHANGELOG
+- Upgraded to work with Terraform >= 0.12 ([#44](https://github.com/antonbabenko/pre-commit-terraform/issues/44))
+
+
+
+## [v1.13.0] - 2019-06-17
+
+- Updated CHANGELOG
+- Added support for terraform_docs for Terraform 0.12 ([#45](https://github.com/antonbabenko/pre-commit-terraform/issues/45))
+
+
+
+## [v1.12.0] - 2019-05-27
+
+- Updated CHANGELOG
+- Added note about incompatibility of terraform-docs with Terraform 0.12 ([#41](https://github.com/antonbabenko/pre-commit-terraform/issues/41))
+- Fixed broken "maintained badge"
+- Update README.md ([#36](https://github.com/antonbabenko/pre-commit-terraform/issues/36))
+
+
+
+## [v1.11.0] - 2019-03-01
+
+- Updated changelog
+- fix check for errors at the end ([#35](https://github.com/antonbabenko/pre-commit-terraform/issues/35))
+
+
+
+## [v1.10.0] - 2019-02-21
+
+- Bump new version
+- Add exit code for 'terraform validate' so pre-commit check fails ([#34](https://github.com/antonbabenko/pre-commit-terraform/issues/34))
+
+
+
+## [v1.9.0] - 2019-02-18
+
+- Added CHANGELOG.md
+- Added chglog (hi [@robinbowes](https://github.com/robinbowes) :))
+- Merge pull request [#33](https://github.com/antonbabenko/pre-commit-terraform/issues/33) from chrisgilmerproj/run_terraform_docs_in_serial
+- Require terraform-docs runs in serial to avoid pre-commit doing parallel operations on similar file paths
+
+
+
+## [v1.8.1] - 2018-12-15
+
+- Merge pull request [#30](https://github.com/antonbabenko/pre-commit-terraform/issues/30) from RothAndrew/feature/fix_issue_29
+- Fix bug not letting terraform_docs_replace work in the root directory of a repo
+
+
+
+## [v1.8.0] - 2018-12-14
+
+- Merge pull request [#27](https://github.com/antonbabenko/pre-commit-terraform/issues/27) from RothAndrew/feature/new_hook
+- fix typo
+- Address requested changes
+- Add `--dest` argument
+- Address requested changes
+- Add new hook for running terraform-docs with replacing README.md from doc in main.tf
+
+
+
+## [v1.7.4] - 2018-12-11
+
+- Merge remote-tracking branch 'origin/master' into pr25
+- Added followup after [#25](https://github.com/antonbabenko/pre-commit-terraform/issues/25)
+- Merge pull request [#25](https://github.com/antonbabenko/pre-commit-terraform/issues/25) from getcloudnative/feat-pass-terraform-docs-opts
+- Add feature to pass options to terraform-docs.
+- Added license file (fixed [#21](https://github.com/antonbabenko/pre-commit-terraform/issues/21))
+
+
+
+## [v1.7.3] - 2018-05-24
+
+- Updated README
+- Only run validate if .tf files exist in the directory. ([#20](https://github.com/antonbabenko/pre-commit-terraform/issues/20))
+
+
+
+## [v1.7.2] - 2018-05-20
+
+- Replace terraform_docs use of GNU sed with perl ([#15](https://github.com/antonbabenko/pre-commit-terraform/issues/15))
+- Fixes use of md5 for tempfile name ([#16](https://github.com/antonbabenko/pre-commit-terraform/issues/16))
+
+
+
+## [v1.7.1] - 2018-05-16
+
+- Run terraform_docs only if README.md is present
+- Run terraform_docs only if README.md is present
+
+
+
+## [v1.7.0] - 2018-05-16
+
+- Added terraform-docs integration ([#13](https://github.com/antonbabenko/pre-commit-terraform/issues/13))
+
+
+
+## [v1.6.0] - 2018-04-21
+
+- Allow to have spaces in directories ([#11](https://github.com/antonbabenko/pre-commit-terraform/issues/11))
+
+
+
+## [v1.5.0] - 2018-03-06
+
+- Bump new version
+- Format tfvars files explicitely, because terraform fmt ignores them ([#9](https://github.com/antonbabenko/pre-commit-terraform/issues/9))
+
+
+
+## [v1.4.0] - 2018-01-24
+
+- Updated readme
+- Show failed path
+- Show failed path
+- Show failed path
+- Updated scripts
+- Added scripts to validate terraform files
+
+
+
+## [v1.3.0] - 2018-01-15
+
+- Added badges
+- Added formatting for tfvars (fixes [#4](https://github.com/antonbabenko/pre-commit-terraform/issues/4)) ([#6](https://github.com/antonbabenko/pre-commit-terraform/issues/6))
+- Merge pull request [#5](https://github.com/antonbabenko/pre-commit-terraform/issues/5) from schneems/schneems/codetriage-badge
+- [ci skip] Get more Open Source Helpers
+
+
+
+## [v1.2.0] - 2017-06-08
+
+- Renamed shell script file to the correct one
+- Updated .pre-commit-hooks.yaml
+- Updated sha in README
+- Merge pull request [#3](https://github.com/antonbabenko/pre-commit-terraform/issues/3) from pecigonzalo/master
+- Exclude .terraform even on subfolders
+
+
+
+## [v1.1.0] - 2017-02-04
+
+- Copied to .pre-commit-hooks.yaml for compatibility (closes [#1](https://github.com/antonbabenko/pre-commit-terraform/issues/1))
+
+
+
+## v1.0.0 - 2016-09-27
+
+- Updated README
+- Ready, probably :)
+- Initial commit
+- Initial commit
+
+
+[Unreleased]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.19.0...HEAD
+[v1.19.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.18.0...v1.19.0
+[v1.18.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.17.0...v1.18.0
+[v1.17.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.16.0...v1.17.0
+[v1.16.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.15.0...v1.16.0
+[v1.15.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.14.0...v1.15.0
+[v1.14.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.13.0...v1.14.0
+[v1.13.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.12.0...v1.13.0
+[v1.12.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.11.0...v1.12.0
+[v1.11.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.10.0...v1.11.0
+[v1.10.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.9.0...v1.10.0
+[v1.9.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.8.1...v1.9.0
+[v1.8.1]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.8.0...v1.8.1
+[v1.8.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.7.4...v1.8.0
+[v1.7.4]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.7.3...v1.7.4
+[v1.7.3]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.7.2...v1.7.3
+[v1.7.2]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.7.1...v1.7.2
+[v1.7.1]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.7.0...v1.7.1
+[v1.7.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.6.0...v1.7.0
+[v1.6.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.5.0...v1.6.0
+[v1.5.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.4.0...v1.5.0
+[v1.4.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.3.0...v1.4.0
+[v1.3.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.2.0...v1.3.0
+[v1.2.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.1.0...v1.2.0
+[v1.1.0]: https://github.com/antonbabenko/pre-commit-terraform/compare/v1.0.0...v1.1.0
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..558dac5a6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+.PHONY: changelog release
+
+changelog:
+ git-chglog -o CHANGELOG.md --next-tag `semtag final -s minor -o`
+
+release:
+ semtag final -s minor
diff --git a/README.md b/README.md
index ce242a35c..6637beec6 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,91 @@
-# pre-commit-terraform hook
+# Collection of git hooks for Terraform to be used with [pre-commit framework](http://pre-commit.com/)
-[](https://github.com/antonbabenko/pre-commit-terraform/releases)  [](https://www.codetriage.com/antonbabenko/pre-commit-terraform)
+[](https://github.com/antonbabenko/pre-commit-terraform/releases)  [](https://www.codetriage.com/antonbabenko/pre-commit-terraform)
-Several [pre-commit](http://pre-commit.com/) hooks to keep Terraform configurations (both `*.tf` and `*.tfvars`) in a good shape:
-* `terraform_fmt` - Rewrites all Terraform configuration files to a canonical format.
-* `terraform_validate_no_variables` - Validates all Terraform configuration files without checking whether all required variables were set.
-* `terraform_validate_with_variables` - Validates all Terraform configuration files and checks whether all required variables were specified.
-* `terraform_docs` - Inserts input and output documentation into `README.md`.
+## How to install
-## Notes about hooks
+### Step 1
-1. `terraform_validate_no_variables` and `terraform_validate_with_variables` will not work if variables are being set dynamically (eg, when using [Terragrunt](https://github.com/gruntwork-io/terragrunt)). Use `terragrunt validate` command instead.
+On MacOSX install the `pre-commit` and `awk` (required for Terraform 0.12) package
+
+```bash
+brew install pre-commit awk
+```
-1. `terraform_docs` will insert/update documentation generated by [terraform-docs](https://github.com/segmentio/terraform-docs) between markers - `` and `` if they are present in `README.md`. Make sure that `terraform-docs` is installed.
+For other operating systems check the [official documentation](http://pre-commit.com/#install)
-## Example
+### Step 2
-`.pre-commit-config.yaml`:
+Step into the repository you want to have the pre-commit hooks installed and run:
-```yaml
+```bash
+cat < .pre-commit-config.yaml
- repo: git://github.com/antonbabenko/pre-commit-terraform
- rev: v1.7.3
+ rev: v1.18.0
hooks:
- id: terraform_fmt
- id: terraform_docs
+EOF
+```
+
+### Step 3
+
+Install the pre-commit hook
+
+```bash
+pre-commit install
```
+### Step 4
+
+After pre-commit hook has been installed you can run it manually on all files in the repository
+
+```bash
+pre-commit run -a
+```
+
+## Available Hooks
+
+There are several [pre-commit](http://pre-commit.com/) hooks to keep Terraform configurations (both `*.tf` and `*.tfvars`) and Terragrunt configurations (`*.hcl`) in a good shape:
+* `terraform_fmt` - Rewrites all Terraform configuration files to a canonical format.
+* `terraform_validate` - Validates all Terraform configuration files.
+* `terraform_docs` - Inserts input and output documentation into `README.md`. Recommended.
+* `terraform_docs_without_aggregate_type_defaults` - Inserts input and output documentation into `README.md` without aggregate type defaults.
+* `terraform_docs_replace` - Runs `terraform-docs` and pipes the output directly to README.md
+* `terraform_tflint` - Validates all Terraform configuration files with [TFLint](https://github.com/wata727/tflint).
+* `terragrunt_fmt` - Rewrites all Terragrunt configuration files (`*.hcl`) to a canonical format.
+
+Check the [source file](https://github.com/antonbabenko/pre-commit-terraform/blob/master/.pre-commit-hooks.yaml) to know arguments used for each hook.
+
+## Notes about hooks
+
+1. `terraform_docs` and `terraform_docs_without_aggregate_type_defaults` will insert/update documentation generated by [terraform-docs](https://github.com/segmentio/terraform-docs) between markers - `` and `` if they are present in `README.md`. Make sure that `terraform-docs` is installed.
+
+1. `terraform_docs_replace` replaces the entire README.md rather than doing string replacement between markers. Put your additional documentation at the top of your `main.tf` for it to be pulled in. The optional `--dest` argument lets you change the name of the file that gets created/modified.
+
+ 1. Example:
+ ```yaml
+ hooks:
+ - id: terraform_docs_replace
+ args: ['--with-aggregate-type-defaults', '--sort-inputs-by-required', '--dest=TEST.md']
+ ```
+
+1. It is possible to pass additional arguments to shell scripts when using `terraform_docs` and `terraform_docs_without_aggregate_type_defaults`. Send pull-request with the new hook if there is something missing.
+
+1. `terraform-docs` works with Terraform 0.12 but support is hackish (it requires `awk` to be installed) and may contain bugs. You can follow the native support of Terraform 0.12 in `terraform-docs` in [issue #62](https://github.com/segmentio/terraform-docs/issues/62).
+
+## Notes for developers
+
+1. Python hooks are supported now too. All you have to do is:
+ 1. add a line to the `console_scripts` array in `entry_points` in `setup.py`
+ 1. Put your python script in the `pre_commit_hooks` folder
+
Enjoy the clean and documented code!
+
+## Authors
+
+This repository is managed by [Anton Babenko](https://github.com/antonbabenko) with help from [these awesome contributors](https://github.com/antonbabenko/pre-commit-terraform/graphs/contributors).
+
+## License
+
+MIT licensed. See LICENSE for full details.
diff --git a/hooks.yaml b/hooks.yaml
deleted file mode 100644
index 2fda38ba1..000000000
--- a/hooks.yaml
+++ /dev/null
@@ -1,31 +0,0 @@
-- id: terraform_fmt
- name: Terraform fmt
- description: Rewrites all Terraform configuration files to a canonical format.
- entry: terraform_fmt.sh
- language: script
- files: (\.tf|\.tfvars)$
- exclude: \.terraform\/.*$
-
-- id: terraform_docs
- name: Terraform docs
- description: Inserts input and output documentation into README.md (using terraform-docs).
- entry: terraform_docs.sh
- language: script
- files: (\.tf)$
- exclude: \.terraform\/.*$
-
-- id: terraform_validate_no_variables
- name: Terraform validate without variables
- description: Validates all Terraform configuration files without checking whether all required variables were set (basic check).
- entry: terraform_validate_no_variables.sh
- language: script
- files: (\.tf|\.tfvars)$
- exclude: \.terraform\/.*$
-
-- id: terraform_validate_with_variables
- name: Terraform validate with variables
- description: Validates all Terraform configuration files and checks whether all required variables were specified.
- entry: terraform_validate_with_variables.sh
- language: script
- files: (\.tf|\.tfvars)$
- exclude: \.terraform\/.*$
diff --git a/pre_commit_hooks/__init__.py b/pre_commit_hooks/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pre_commit_hooks/terraform_docs_replace.py b/pre_commit_hooks/terraform_docs_replace.py
new file mode 100644
index 000000000..05fec622e
--- /dev/null
+++ b/pre_commit_hooks/terraform_docs_replace.py
@@ -0,0 +1,54 @@
+import argparse
+import os
+import subprocess
+import sys
+
+
+def main(argv=None):
+ parser = argparse.ArgumentParser(
+ description="""Run terraform-docs on a set of files. Follows the standard convention of
+ pulling the documentation from main.tf in order to replace the entire
+ README.md file each time."""
+ )
+ parser.add_argument(
+ '--dest', dest='dest', default='README.md',
+ )
+ parser.add_argument(
+ '--sort-inputs-by-required', dest='sort', action='store_true',
+ )
+ parser.add_argument(
+ '--with-aggregate-type-defaults', dest='aggregate', action='store_true',
+ )
+ parser.add_argument('filenames', nargs='*', help='Filenames to check.')
+ args = parser.parse_args(argv)
+
+ dirs = []
+ for filename in args.filenames:
+ if (os.path.realpath(filename) not in dirs and \
+ (filename.endswith(".tf") or filename.endswith(".tfvars"))):
+ dirs.append(os.path.dirname(filename))
+
+ retval = 0
+
+ for dir in dirs:
+ try:
+ procArgs = []
+ procArgs.append('terraform-docs')
+ if args.sort:
+ procArgs.append('--sort-inputs-by-required')
+ if args.aggregate:
+ procArgs.append('--with-aggregate-type-defaults')
+ procArgs.append('md')
+ procArgs.append("./{dir}".format(dir=dir))
+ procArgs.append("| sed -e '$ d' -e 'N;/^\\n$/D;P;D'")
+ procArgs.append('>')
+ procArgs.append("./{dir}/{dest}".format(dir=dir,dest=args.dest))
+ subprocess.check_call(" ".join(procArgs), shell=True)
+ except subprocess.CalledProcessError as e:
+ print(e)
+ retval = 1
+ return retval
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/setup.py b/setup.py
new file mode 100644
index 000000000..4c2b47668
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,33 @@
+from setuptools import find_packages
+from setuptools import setup
+
+
+setup(
+ name='pre-commit-terraform',
+ description='Pre-commit hooks for terraform_docs_replace',
+ url='https://github.com/antonbabenko/pre-commit-terraform',
+ version_format='{tag}+{gitsha}',
+
+ author='Contributors',
+
+ classifiers=[
+ 'License :: OSI Approved :: MIT License',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ ],
+
+ packages=find_packages(exclude=('tests*', 'testing*')),
+ install_requires=[
+ 'setuptools-git-version',
+ ],
+ entry_points={
+ 'console_scripts': [
+ 'terraform_docs_replace = pre_commit_hooks.terraform_docs_replace:main',
+ ],
+ },
+)
diff --git a/terraform_docs.sh b/terraform_docs.sh
index 781973aa7..0935b69e6 100755
--- a/terraform_docs.sh
+++ b/terraform_docs.sh
@@ -1,45 +1,694 @@
#!/usr/bin/env bash
+
set -e
-declare -a paths
-declare -a tfvars_files
+main() {
+ declare argv
+ argv=$(getopt -o a: --long args: -- "$@") || return
+ eval "set -- $argv"
+
+ declare args
+ declare files
-index=0
+ for argv; do
+ case $argv in
+ (-a|--args)
+ shift
+ args="$1"
+ shift
+ ;;
+ (--)
+ shift
+ files="$@"
+ break
+ ;;
+ esac
+ done
-for file_with_path in "$@"; do
- file_with_path="${file_with_path// /__REPLACED__SPACE__}"
+ local hack_terraform_docs=$(terraform version | head -1 | grep -c 0.12)
- paths[index]=$(dirname "$file_with_path")
+ if [[ "$hack_terraform_docs" == "1" ]]; then
+ which awk 2>&1 >/dev/null || ( echo "awk is required for terraform-docs hack to work with Terraform 0.12"; exit 1)
- if [[ "$file_with_path" == *".tfvars" ]]; then
- tfvars_files+=("$file_with_path")
+ tmp_file_awk=$(mktemp "${TMPDIR:-/tmp}/terraform-docs-XXXXXXXXXX")
+ terraform_docs_awk "$tmp_file_awk"
+ terraform_docs "$tmp_file_awk" "$args" "$files"
+ rm -f "$tmp_file_awk"
+ else
+ terraform_docs "0" "$args" "$files"
fi
- ((index+=1))
-done
+}
-readonly tmp_file=$(mktemp)
-readonly text_file="README.md"
+terraform_docs() {
+ readonly terraform_docs_awk_file="$1"
+ readonly args="$2"
+ readonly files="$3"
-for path_uniq in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
- path_uniq="${path_uniq//__REPLACED__SPACE__/ }"
+ declare -a paths
+ declare -a tfvars_files
- pushd "$path_uniq" > /dev/null
+ index=0
- if [[ ! -f "$text_file" ]]; then
- popd > /dev/null
- continue
+ for file_with_path in $files; do
+ file_with_path="${file_with_path// /__REPLACED__SPACE__}"
+
+ paths[index]=$(dirname "$file_with_path")
+
+ if [[ "$file_with_path" == *".tfvars" ]]; then
+ tfvars_files+=("$file_with_path")
+ fi
+
+ ((index+=1))
+ done
+
+ readonly tmp_file=$(mktemp)
+ readonly text_file="README.md"
+
+ for path_uniq in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
+ path_uniq="${path_uniq//__REPLACED__SPACE__/ }"
+
+ pushd "$path_uniq" > /dev/null
+
+ if [[ ! -f "$text_file" ]]; then
+ popd > /dev/null
+ continue
+ fi
+
+ if [[ "$terraform_docs_awk_file" == "0" ]]; then
+ terraform-docs $args md ./ > "$tmp_file"
+ else
+ # Can't append extension for mktemp, so renaming instead
+ tmp_file_docs=$(mktemp "${TMPDIR:-/tmp}/terraform-docs-XXXXXXXXXX")
+ mv "$tmp_file_docs" "$tmp_file_docs.tf"
+ tmp_file_docs_tf="$tmp_file_docs.tf"
+
+ awk -f "$terraform_docs_awk_file" ./*.tf > "$tmp_file_docs_tf"
+ terraform-docs $args md "$tmp_file_docs_tf" > "$tmp_file"
+ rm -f "$tmp_file_docs_tf"
fi
- terraform-docs md ./ > "$tmp_file"
+ # Replace content between markers with the placeholder - https://stackoverflow.com/questions/1212799/how-do-i-extract-lines-between-two-line-delimiters-in-perl#1212834
+ perl -i -ne 'if (/BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK/../END OF PRE-COMMIT-TERRAFORM DOCS HOOK/) { print $_ if /BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK/; print "I_WANT_TO_BE_REPLACED\n$_" if /END OF PRE-COMMIT-TERRAFORM DOCS HOOK/;} else { print $_ }' "$text_file"
+
+ # Replace placeholder with the content of the file
+ perl -i -e 'open(F, "'"$tmp_file"'"); $f = join "", ; while(<>){if (/I_WANT_TO_BE_REPLACED/) {print $f} else {print $_};}' "$text_file"
+
+ rm -f "$tmp_file"
+
+ popd > /dev/null
+ done
+}
+
+terraform_docs_awk() {
+ readonly output_file=$1
+
+ cat <<"EOF" > $output_file
+# This script converts Terraform 0.12 variables/outputs to something suitable for `terraform-docs`
+# As of terraform-docs v0.6.0, HCL2 is not supported. This script is a *dirty hack* to get around it.
+# https://github.com/segmentio/terraform-docs/
+# https://github.com/segmentio/terraform-docs/issues/62
+
+# Script was originally found here: https://github.com/cloudposse/build-harness/blob/master/bin/terraform-docs.awk
+
+{
+ if ( $0 ~ /\{/ ) {
+ braceCnt++
+ }
+
+ if ( $0 ~ /\}/ ) {
+ braceCnt--
+ }
+
+ # [START] variable or output block started
+ if ($0 ~ /^[[:space:]]*(variable|output)[[:space:]][[:space:]]*"(.*?)"/) {
+ # Normalize the braceCnt (should be 1 now)
+ braceCnt = 1
+ # [CLOSE] "default" block
+ if (blockDefCnt > 0) {
+ blockDefCnt = 0
+ }
+ blockCnt++
+ print $0
+ }
+
+ # [START] multiline default statement started
+ if (blockCnt > 0) {
+ if ($0 ~ /^[[:space:]][[:space:]]*(default)[[:space:]][[:space:]]*=/) {
+ if ($3 ~ "null") {
+ print " default = \"null\""
+ } else {
+ print $0
+ blockDefCnt++
+ blockDefStart=1
+ }
+ }
+ }
+
+ # [PRINT] single line "description"
+ if (blockCnt > 0) {
+ if (blockDefCnt == 0) {
+ if ($0 ~ /^[[:space:]][[:space:]]*description[[:space:]][[:space:]]*=/) {
+ # [CLOSE] "default" block
+ if (blockDefCnt > 0) {
+ blockDefCnt = 0
+ }
+ print $0
+ }
+ }
+ }
+
+ # [PRINT] single line "type"
+ if (blockCnt > 0) {
+ if ($0 ~ /^[[:space:]][[:space:]]*type[[:space:]][[:space:]]*=/ ) {
+ # [CLOSE] "default" block
+ if (blockDefCnt > 0) {
+ blockDefCnt = 0
+ }
+ type=$3
+ if (type ~ "object") {
+ print " type = \"object\""
+ } else {
+ # legacy quoted types: "string", "list", and "map"
+ if ($3 ~ /^[[:space:]]*"(.*?)"[[:space:]]*$/) {
+ print " type = " $3
+ } else {
+ print " type = \"" $3 "\""
+ }
+ }
+ }
+ }
+
+ # [CLOSE] variable/output block
+ if (blockCnt > 0) {
+ if (braceCnt == 0 && blockCnt > 0) {
+ blockCnt--
+ print $0
+ }
+ }
+
+ # [PRINT] Multiline "default" statement
+ if (blockCnt > 0 && blockDefCnt > 0) {
+ if (blockDefStart == 1) {
+ blockDefStart = 0
+ } else {
+ print $0
+ }
+ }
+}
+EOF
+
+}
+
+getopt() {
+ # pure-getopt, a drop-in replacement for GNU getopt in pure Bash.
+ # version 1.4.3
+ #
+ # Copyright 2012-2018 Aron Griffis
+ #
+ # 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.
+
+ _getopt_main() {
+ # Returns one of the following statuses:
+ # 0 success
+ # 1 error parsing parameters
+ # 2 error in getopt invocation
+ # 3 internal error
+ # 4 reserved for -T
+ #
+ # For statuses 0 and 1, generates normalized and shell-quoted
+ # "options -- parameters" on stdout.
+
+ declare parsed status
+ declare short long name flags
+ declare have_short=false
+
+ # Synopsis from getopt man-page:
+ #
+ # getopt optstring parameters
+ # getopt [options] [--] optstring parameters
+ # getopt [options] -o|--options optstring [options] [--] parameters
+ #
+ # The first form can be normalized to the third form which
+ # _getopt_parse() understands. The second form can be recognized after
+ # first parse when $short hasn't been set.
+
+ if [[ -n ${GETOPT_COMPATIBLE+isset} || $1 == [^-]* ]]; then
+ # Enable compatibility mode
+ flags=c$flags
+ # Normalize first to third synopsis form
+ set -- -o "$1" -- "${@:2}"
+ fi
+
+ # First parse always uses flags=p since getopt always parses its own
+ # arguments effectively in this mode.
+ parsed=$(_getopt_parse getopt ahl:n:o:qQs:TuV \
+ alternative,help,longoptions:,name:,options:,quiet,quiet-output,shell:,test,version \
+ p "$@")
+ status=$?
+ if [[ $status != 0 ]]; then
+ if [[ $status == 1 ]]; then
+ echo "Try \`getopt --help' for more information." >&2
+ # Since this is the first parse, convert status 1 to 2
+ status=2
+ fi
+ return $status
+ fi
+ eval "set -- $parsed"
+
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+ (-a|--alternative)
+ flags=a$flags ;;
+
+ (-h|--help)
+ _getopt_help
+ return 2 # as does GNU getopt
+ ;;
+
+ (-l|--longoptions)
+ long="$long${long:+,}$2"
+ shift ;;
+
+ (-n|--name)
+ name=$2
+ shift ;;
+
+ (-o|--options)
+ short=$2
+ have_short=true
+ shift ;;
+
+ (-q|--quiet)
+ flags=q$flags ;;
+
+ (-Q|--quiet-output)
+ flags=Q$flags ;;
+
+ (-s|--shell)
+ case $2 in
+ (sh|bash)
+ flags=${flags//t/} ;;
+ (csh|tcsh)
+ flags=t$flags ;;
+ (*)
+ echo 'getopt: unknown shell after -s or --shell argument' >&2
+ echo "Try \`getopt --help' for more information." >&2
+ return 2 ;;
+ esac
+ shift ;;
+
+ (-u|--unquoted)
+ flags=u$flags ;;
+
+ (-T|--test)
+ return 4 ;;
+
+ (-V|--version)
+ echo "pure-getopt 1.4.3"
+ return 0 ;;
+
+ (--)
+ shift
+ break ;;
+ esac
+
+ shift
+ done
+
+ if ! $have_short; then
+ # $short was declared but never set, not even to an empty string.
+ # This implies the second form in the synopsis.
+ if [[ $# == 0 ]]; then
+ echo 'getopt: missing optstring argument' >&2
+ echo "Try \`getopt --help' for more information." >&2
+ return 2
+ fi
+ short=$1
+ have_short=true
+ shift
+ fi
+
+ if [[ $short == -* ]]; then
+ # Leading dash means generate output in place rather than reordering,
+ # unless we're already in compatibility mode.
+ [[ $flags == *c* ]] || flags=i$flags
+ short=${short#?}
+ elif [[ $short == +* ]]; then
+ # Leading plus means POSIXLY_CORRECT, unless we're already in
+ # compatibility mode.
+ [[ $flags == *c* ]] || flags=p$flags
+ short=${short#?}
+ fi
+
+ # This should fire if POSIXLY_CORRECT is in the environment, even if
+ # it's an empty string. That's the difference between :+ and +
+ flags=${POSIXLY_CORRECT+p}$flags
+
+ _getopt_parse "${name:-getopt}" "$short" "$long" "$flags" "$@"
+ }
+
+ _getopt_parse() {
+ # Inner getopt parser, used for both first parse and second parse.
+ # Returns 0 for success, 1 for error parsing, 3 for internal error.
+ # In the case of status 1, still generates stdout with whatever could
+ # be parsed.
+ #
+ # $flags is a string of characters with the following meanings:
+ # a - alternative parsing mode
+ # c - GETOPT_COMPATIBLE
+ # i - generate output in place rather than reordering
+ # p - POSIXLY_CORRECT
+ # q - disable error reporting
+ # Q - disable normal output
+ # t - quote for csh/tcsh
+ # u - unquoted output
+
+ declare name="$1" short="$2" long="$3" flags="$4"
+ shift 4
+
+ # Split $long on commas, prepend double-dashes, strip colons;
+ # for use with _getopt_resolve_abbrev
+ declare -a longarr
+ _getopt_split longarr "$long"
+ longarr=( "${longarr[@]/#/--}" )
+ longarr=( "${longarr[@]%:}" )
+ longarr=( "${longarr[@]%:}" )
+
+ # Parse and collect options and parameters
+ declare -a opts params
+ declare o alt_recycled=false error=0
+
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+ (--)
+ params=( "${params[@]}" "${@:2}" )
+ break ;;
+
+ (--*=*)
+ o=${1%%=*}
+ if ! o=$(_getopt_resolve_abbrev "$o" "${longarr[@]}"); then
+ error=1
+ elif [[ ,"$long", == *,"${o#--}"::,* ]]; then
+ opts=( "${opts[@]}" "$o" "${1#*=}" )
+ elif [[ ,"$long", == *,"${o#--}":,* ]]; then
+ opts=( "${opts[@]}" "$o" "${1#*=}" )
+ elif [[ ,"$long", == *,"${o#--}",* ]]; then
+ if $alt_recycled; then o=${o#-}; fi
+ _getopt_err "$name: option '$o' doesn't allow an argument"
+ error=1
+ else
+ echo "getopt: assertion failed (1)" >&2
+ return 3
+ fi
+ alt_recycled=false
+ ;;
+
+ (--?*)
+ o=$1
+ if ! o=$(_getopt_resolve_abbrev "$o" "${longarr[@]}"); then
+ error=1
+ elif [[ ,"$long", == *,"${o#--}",* ]]; then
+ opts=( "${opts[@]}" "$o" )
+ elif [[ ,"$long", == *,"${o#--}::",* ]]; then
+ opts=( "${opts[@]}" "$o" '' )
+ elif [[ ,"$long", == *,"${o#--}:",* ]]; then
+ if [[ $# -ge 2 ]]; then
+ shift
+ opts=( "${opts[@]}" "$o" "$1" )
+ else
+ if $alt_recycled; then o=${o#-}; fi
+ _getopt_err "$name: option '$o' requires an argument"
+ error=1
+ fi
+ else
+ echo "getopt: assertion failed (2)" >&2
+ return 3
+ fi
+ alt_recycled=false
+ ;;
+
+ (-*)
+ if [[ $flags == *a* ]]; then
+ # Alternative parsing mode!
+ # Try to handle as a long option if any of the following apply:
+ # 1. There's an equals sign in the mix -x=3 or -xy=3
+ # 2. There's 2+ letters and an abbreviated long match -xy
+ # 3. There's a single letter and an exact long match
+ # 4. There's a single letter and no short match
+ o=${1::2} # temp for testing #4
+ if [[ $1 == *=* || $1 == -?? || \
+ ,$long, == *,"${1#-}"[:,]* || \
+ ,$short, != *,"${o#-}"[:,]* ]]; then
+ o=$(_getopt_resolve_abbrev "${1%%=*}" "${longarr[@]}" 2>/dev/null)
+ case $? in
+ (0)
+ # Unambiguous match. Let the long options parser handle
+ # it, with a flag to get the right error message.
+ set -- "-$1" "${@:2}"
+ alt_recycled=true
+ continue ;;
+ (1)
+ # Ambiguous match, generate error and continue.
+ _getopt_resolve_abbrev "${1%%=*}" "${longarr[@]}" >/dev/null
+ error=1
+ shift
+ continue ;;
+ (2)
+ # No match, fall through to single-character check.
+ true ;;
+ (*)
+ echo "getopt: assertion failed (3)" >&2
+ return 3 ;;
+ esac
+ fi
+ fi
+
+ o=${1::2}
+ if [[ "$short" == *"${o#-}"::* ]]; then
+ if [[ ${#1} -gt 2 ]]; then
+ opts=( "${opts[@]}" "$o" "${1:2}" )
+ else
+ opts=( "${opts[@]}" "$o" '' )
+ fi
+ elif [[ "$short" == *"${o#-}":* ]]; then
+ if [[ ${#1} -gt 2 ]]; then
+ opts=( "${opts[@]}" "$o" "${1:2}" )
+ elif [[ $# -ge 2 ]]; then
+ shift
+ opts=( "${opts[@]}" "$o" "$1" )
+ else
+ _getopt_err "$name: option requires an argument -- '${o#-}'"
+ error=1
+ fi
+ elif [[ "$short" == *"${o#-}"* ]]; then
+ opts=( "${opts[@]}" "$o" )
+ if [[ ${#1} -gt 2 ]]; then
+ set -- "$o" "-${1:2}" "${@:2}"
+ fi
+ else
+ if [[ $flags == *a* ]]; then
+ # Alternative parsing mode! Report on the entire failed
+ # option. GNU includes =value but we omit it for sanity with
+ # very long values.
+ _getopt_err "$name: unrecognized option '${1%%=*}'"
+ else
+ _getopt_err "$name: invalid option -- '${o#-}'"
+ if [[ ${#1} -gt 2 ]]; then
+ set -- "$o" "-${1:2}" "${@:2}"
+ fi
+ fi
+ error=1
+ fi ;;
+
+ (*)
+ # GNU getopt in-place mode (leading dash on short options)
+ # overrides POSIXLY_CORRECT
+ if [[ $flags == *i* ]]; then
+ opts=( "${opts[@]}" "$1" )
+ elif [[ $flags == *p* ]]; then
+ params=( "${params[@]}" "$@" )
+ break
+ else
+ params=( "${params[@]}" "$1" )
+ fi
+ esac
+
+ shift
+ done
+
+ if [[ $flags == *Q* ]]; then
+ true # generate no output
+ else
+ echo -n ' '
+ if [[ $flags == *[cu]* ]]; then
+ printf '%s -- %s' "${opts[*]}" "${params[*]}"
+ else
+ if [[ $flags == *t* ]]; then
+ _getopt_quote_csh "${opts[@]}" -- "${params[@]}"
+ else
+ _getopt_quote "${opts[@]}" -- "${params[@]}"
+ fi
+ fi
+ echo
+ fi
+
+ return $error
+ }
+
+ _getopt_err() {
+ if [[ $flags != *q* ]]; then
+ printf '%s\n' "$1" >&2
+ fi
+ }
+
+ _getopt_resolve_abbrev() {
+ # Resolves an abbrevation from a list of possibilities.
+ # If the abbreviation is unambiguous, echoes the expansion on stdout
+ # and returns 0. If the abbreviation is ambiguous, prints a message on
+ # stderr and returns 1. (For first parse this should convert to exit
+ # status 2.) If there is no match at all, prints a message on stderr
+ # and returns 2.
+ declare a q="$1"
+ declare -a matches
+ shift
+ for a; do
+ if [[ $q == "$a" ]]; then
+ # Exact match. Squash any other partial matches.
+ matches=( "$a" )
+ break
+ elif [[ $flags == *a* && $q == -[^-]* && $a == -"$q" ]]; then
+ # Exact alternative match. Squash any other partial matches.
+ matches=( "$a" )
+ break
+ elif [[ $a == "$q"* ]]; then
+ # Abbreviated match.
+ matches=( "${matches[@]}" "$a" )
+ elif [[ $flags == *a* && $q == -[^-]* && $a == -"$q"* ]]; then
+ # Abbreviated alternative match.
+ matches=( "${matches[@]}" "${a#-}" )
+ fi
+ done
+ case ${#matches[@]} in
+ (0)
+ [[ $flags == *q* ]] || \
+ printf "$name: unrecognized option %s\\n" >&2 \
+ "$(_getopt_quote "$q")"
+ return 2 ;;
+ (1)
+ printf '%s' "${matches[0]}"; return 0 ;;
+ (*)
+ [[ $flags == *q* ]] || \
+ printf "$name: option %s is ambiguous; possibilities: %s\\n" >&2 \
+ "$(_getopt_quote "$q")" "$(_getopt_quote "${matches[@]}")"
+ return 1 ;;
+ esac
+ }
+
+ _getopt_split() {
+ # Splits $2 at commas to build array specified by $1
+ declare IFS=,
+ eval "$1=( \$2 )"
+ }
+
+ _getopt_quote() {
+ # Quotes arguments with single quotes, escaping inner single quotes
+ declare s space q=\'
+ for s; do
+ printf "$space'%s'" "${s//$q/$q\\$q$q}"
+ space=' '
+ done
+ }
+
+ _getopt_quote_csh() {
+ # Quotes arguments with single quotes, escaping inner single quotes,
+ # bangs, backslashes and newlines
+ declare s i c space
+ for s; do
+ echo -n "$space'"
+ for ((i=0; i<${#s}; i++)); do
+ c=${s:i:1}
+ case $c in
+ (\\|\'|!)
+ echo -n "'\\$c'" ;;
+ ($'\n')
+ echo -n "\\$c" ;;
+ (*)
+ echo -n "$c" ;;
+ esac
+ done
+ echo -n \'
+ space=' '
+ done
+ }
+
+ _getopt_help() {
+ cat <<-EOT >&2
+
+ Usage:
+ getopt
+ getopt [options] [--]
+ getopt [options] -o|--options [options] [--]
+
+ Parse command options.
+
+ Options:
+ -a, --alternative allow long options starting with single -
+ -l, --longoptions the long options to be recognized
+ -n, --name the name under which errors are reported
+ -o, --options the short options to be recognized
+ -q, --quiet disable error reporting by getopt(3)
+ -Q, --quiet-output no normal output
+ -s, --shell set quoting conventions to those of
+ -T, --test test for getopt(1) version
+ -u, --unquoted do not quote the output
+
+ -h, --help display this help and exit
+ -V, --version output version information and exit
+
+ For more details see getopt(1).
+ EOT
+ }
+
+ _getopt_version_check() {
+ if [[ -z $BASH_VERSION ]]; then
+ echo "getopt: unknown version of bash might not be compatible" >&2
+ return 1
+ fi
- # Replace content between markers with the placeholder - https://stackoverflow.com/questions/1212799/how-do-i-extract-lines-between-two-line-delimiters-in-perl#1212834
- perl -i -ne 'if (/BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK/../END OF PRE-COMMIT-TERRAFORM DOCS HOOK/) { print $_ if /BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK/; print "I_WANT_TO_BE_REPLACED\n$_" if /END OF PRE-COMMIT-TERRAFORM DOCS HOOK/;} else { print $_ }' "$text_file"
+ # This is a lexical comparison that should be sufficient forever.
+ if [[ $BASH_VERSION < 2.05b ]]; then
+ echo "getopt: bash $BASH_VERSION might not be compatible" >&2
+ return 1
+ fi
- # Replace placeholder with the content of the file
- perl -i -e 'open(F, "'"$tmp_file"'"); $f = join "", ; while(<>){if (/I_WANT_TO_BE_REPLACED/) {print $f} else {print $_};}' "$text_file"
+ return 0
+ }
- rm -f "$tmp_file"
+ _getopt_version_check
+ _getopt_main "$@"
+ declare status=$?
+ unset -f _getopt_main _getopt_err _getopt_parse _getopt_quote \
+ _getopt_quote_csh _getopt_resolve_abbrev _getopt_split _getopt_help \
+ _getopt_version_check
+ return $status
+}
- popd > /dev/null
-done
+[[ $BASH_SOURCE != "$0" ]] || main "$@"
diff --git a/terraform_validate_with_variables.sh b/terraform_tflint.sh
similarity index 59%
rename from terraform_validate_with_variables.sh
rename to terraform_tflint.sh
index 706443ade..4e6c23e76 100755
--- a/terraform_validate_with_variables.sh
+++ b/terraform_tflint.sh
@@ -2,25 +2,22 @@
set -e
declare -a paths
+declare -a tfvars_files
+
index=0
for file_with_path in "$@"; do
file_with_path="${file_with_path// /__REPLACED__SPACE__}"
paths[index]=$(dirname "$file_with_path")
- (( "index+=1" ))
+
+ let "index+=1"
done
for path_uniq in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
path_uniq="${path_uniq//__REPLACED__SPACE__/ }"
pushd "$path_uniq" > /dev/null
- if [[ -n "$(find . -maxdepth 1 -name '*.tf' -print -quit)" ]] ; then
- if ! terraform validate -check-variables=true ; then
- echo
- echo "Failed path: $path_uniq"
- echo "================================"
- fi
- fi
+ tflint --deep
popd > /dev/null
done
diff --git a/terraform_validate_no_variables.sh b/terraform_validate.sh
similarity index 82%
rename from terraform_validate_no_variables.sh
rename to terraform_validate.sh
index 2e190448a..6f7eccac2 100755
--- a/terraform_validate_no_variables.sh
+++ b/terraform_validate.sh
@@ -3,6 +3,7 @@ set -e
declare -a paths
index=0
+error=0
for file_with_path in "$@"; do
file_with_path="${file_with_path// /__REPLACED__SPACE__}"
@@ -14,13 +15,16 @@ done
for path_uniq in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
path_uniq="${path_uniq//__REPLACED__SPACE__/ }"
- pushd "$path_uniq" > /dev/null
if [[ -n "$(find . -maxdepth 1 -name '*.tf' -print -quit)" ]] ; then
- if ! terraform validate -check-variables=false ; then
+ if ! terraform validate $path_uniq; then
+ error=1
echo
echo "Failed path: $path_uniq"
echo "================================"
fi
fi
- popd > /dev/null
done
+
+if [[ "${error}" -ne 0 ]] ; then
+ exit 1
+fi
diff --git a/terragrunt_fmt.sh b/terragrunt_fmt.sh
new file mode 100755
index 000000000..ee23131e7
--- /dev/null
+++ b/terragrunt_fmt.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -e
+
+declare -a paths
+
+index=0
+
+for file_with_path in "$@"; do
+ file_with_path="${file_with_path// /__REPLACED__SPACE__}"
+
+ paths[index]=$(dirname "$file_with_path")
+
+ let "index+=1"
+done
+
+for path_uniq in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
+ path_uniq="${path_uniq//__REPLACED__SPACE__/ }"
+
+ pushd "$path_uniq" > /dev/null
+ terragrunt hclfmt
+ popd > /dev/null
+done